using ScadaLink.Commons.Interfaces.Services;
using ScadaLink.Commons.Messages.InboundApi;
using ScadaLink.Commons.Types;
namespace ScadaLink.InboundAPI;
///
/// WP-4: Route.To() helper for cross-site calls from inbound API scripts.
/// Resolves instance to site, routes via , blocks until
/// response or timeout. Site unreachable returns error (no store-and-forward).
///
/// InboundAPI-016: the helper carries the executing method's
/// (the method-level timeout). Routed calls inherit that deadline by default, so a
/// natural script — Route.To("inst").Call("doWork", p) — is timeout-bounded
/// without the script having to thread a token explicitly.
///
public class RouteHelper
{
private readonly IInstanceLocator _instanceLocator;
private readonly IInstanceRouter _instanceRouter;
private readonly CancellationToken _deadlineToken;
private readonly Guid? _parentExecutionId;
public RouteHelper(
IInstanceLocator instanceLocator,
IInstanceRouter instanceRouter)
: this(instanceLocator, instanceRouter, CancellationToken.None, parentExecutionId: null)
{
}
private RouteHelper(
IInstanceLocator instanceLocator,
IInstanceRouter instanceRouter,
CancellationToken deadlineToken,
Guid? parentExecutionId)
{
_instanceLocator = instanceLocator;
_instanceRouter = instanceRouter;
_deadlineToken = deadlineToken;
_parentExecutionId = parentExecutionId;
}
///
/// InboundAPI-016: returns a whose routed calls inherit
/// (the executing method's timeout) by default.
/// calls this when it builds the script
/// context so the method timeout actually covers routed calls, as the design doc
/// requires.
///
public RouteHelper WithDeadline(CancellationToken deadlineToken) =>
new(_instanceLocator, _instanceRouter, deadlineToken, _parentExecutionId);
///
/// Audit Log #23 (ParentExecutionId): returns a whose
/// routed requests carry
/// as .
/// For an inbound API request this is the inbound request's own per-request
/// execution id, so the routed site script records the inbound request as its
/// parent. calls this when it builds the
/// script context.
///
public RouteHelper WithParentExecutionId(Guid? parentExecutionId) =>
new(_instanceLocator, _instanceRouter, _deadlineToken, parentExecutionId);
///
/// Creates a route target for the specified instance.
///
public RouteTarget To(string instanceCode)
{
return new RouteTarget(
instanceCode, _instanceLocator, _instanceRouter, _deadlineToken, _parentExecutionId);
}
}
///
/// WP-4: Represents a route target (an instance) for cross-site calls.
///
public class RouteTarget
{
private readonly string _instanceCode;
private readonly IInstanceLocator _instanceLocator;
private readonly IInstanceRouter _instanceRouter;
private readonly CancellationToken _deadlineToken;
private readonly Guid? _parentExecutionId;
internal RouteTarget(
string instanceCode,
IInstanceLocator instanceLocator,
IInstanceRouter instanceRouter,
CancellationToken deadlineToken,
Guid? parentExecutionId)
{
_instanceCode = instanceCode;
_instanceLocator = instanceLocator;
_instanceRouter = instanceRouter;
_deadlineToken = deadlineToken;
_parentExecutionId = parentExecutionId;
}
///
/// Calls a script on the remote instance. Synchronous from API caller's
/// perspective. may be a dictionary or an
/// anonymous object (new { name = "Bob" }) — see .
///
/// InboundAPI-016: when is not supplied the
/// routed call inherits the executing method's timeout, so the call is bounded by
/// the method-level deadline with no token argument.
///
public async Task