Reference

IDormantDependentContext

Package Trax.SchedulerNamespace Trax.Scheduler.Services.DormantDependentContextSource IDormantDependentContext.cs, DormantDependentContext.cs

A scoped service a running train injects to activate its own dormant dependents: manifests declared with .Dormant() (see Dependent scheduling) that never fire on their own. The JobRunner initializes it with the parent manifest before the train runs, and only dormant dependents of that manifest can be activated.

Signature

namespace Trax.Scheduler.Services.DormantDependentContext;
 
public interface IDormantDependentContext
{
    Task ActivateAsync<TTrain, TInput, TOutput>(
        string externalId,
        TInput input,
        CancellationToken ct = default
    )
        where TTrain : IServiceTrain<TInput, TOutput>
        where TInput : IManifestProperties;
 
    Task ActivateManyAsync<TTrain, TInput, TOutput>(
        IEnumerable<(string ExternalId, TInput Input)> activations,
        CancellationToken ct = default
    )
        where TTrain : IServiceTrain<TInput, TOutput>
        where TInput : IManifestProperties;
}

Members

MemberDescription
ActivateAsyncQueues one dormant dependent with the given input
ActivateManyAsyncQueues several, in one transaction

ActivateAsync

ParameterTypeDefaultDescription
externalIdstringrequiredThe external id of the dormant dependent manifest
inputTInputrequiredThe input the dependent runs with
ctCancellationTokendefaultCancels the activation

Throws: InvalidOperationException when the manifest does not exist, is not DormantDependent, or does not depend on the current parent.

A disabled manifest, or one in a disabled group, is skipped with a warning log. So is one that already has a queued work queue entry or an active run (Pending or InProgress metadata).

ActivateManyAsync

ParameterTypeDefaultDescription
activationsIEnumerable<(string ExternalId, TInput Input)>requiredThe manifests to activate and their inputs
ctCancellationTokendefaultCancels the activation

Every activation is made in one database transaction. A failed check (a wrong parent, a manifest that is not dormant) rolls back the whole batch; a skipped entry (disabled, already queued or active) does not.

Behavior

Outside a scheduled run (a train invoked through ITrainBus, a GraphQL mutation or a test) the context has no parent manifest. ActivateAsync and ActivateManyAsync then log a warning and return without activating anything or throwing, so the same train can run both ways.

AddScheduler and AddTraxJobRunner register the default DormantDependentContext as scoped.

Example

public class SelectiveDispatchJunction(IDormantDependentContext dormants)
    : Junction<DispatchInput, Unit>
{
    public override async Task<Unit> Run(DispatchInput input)
    {
        await dormants.ActivateAsync<IChildTrain, ChildInput, Unit>(
            "child-1",
            new ChildInput { Data = input.RuntimeData });
 
        var activations = input.Items
            .Select(item => ($"child-{item.Id}", new ChildInput { Data = item.Data }));
        await dormants.ActivateManyAsync<IChildTrain, ChildInput, Unit>(activations);
 
        return Unit.Default;
    }
}

See also