# IJobDispatcher

> Tracon documentation. Tracon is a .NET package family that adds a control
> plane on Microsoft Agent Framework, published as NuGet packages that run
> inside your own ASP.NET Core application.
>
> Page: https://tracon.dev/api/tracon.ijobdispatcher/
> Summary: IJobDispatcher: Queues a job for a registered IJobHandler.

<div class="api-provenance">Namespace Tracon · Assembly <code>Tracon.Abstractions.dll</code></div>

Queues a job for a registered [IJobHandler](/api/tracon.ijobhandler/).

```csharp
public interface IJobDispatcher
```

## Remarks

The supported way for consumer code to create work. [IJobStore](/api/tracon.ijobstore/)
stays the persistence surface: it takes a fully formed
[JobRecord](/api/tracon.jobrecord/), so the caller has to invent the identifier, the
status and the timestamps, and it accepts **any** handler key,
including one nobody registered — such a job only fails later, in the
worker. This interface closes both gaps.

Call this interface to queue work; Tracon supplies the implementation, so do not
implement or replace it. To run work of your own kind, implement
[IJobHandler](/api/tracon.ijobhandler/).

It performs no authorization of its own: the caller is already inside the
process. The HTTP surface has its own, narrower gate
([TraconSchedulingOptions.HttpSchedulableHandlerKeys](/api/tracon.traconschedulingoptions/#Tracon_TraconSchedulingOptions_HttpSchedulableHandlerKeys)).

**Lifetime:** registered as a `singleton` and safe to
call from any thread; it holds no per-call state.

**Tenant:** takes an `expected tenant` —
[JobRequest.TenantId](/api/tracon.jobrequest/#Tracon_JobRequest_TenantId) is required and is the tenant the job is
queued for. The ambient tenant is not consulted; a caller that wants it
passes it explicitly.

**Delivery:** queueing itself is exactly one row — the method
either returns a queued [JobRecord](/api/tracon.jobrecord/) or throws, and it never
retries on its own. What happens afterwards is the queue's contract, and
that is `at-least-once`: the handler may run more than once for the
job this call created (see [IJobHandler.ExecuteAsync](/api/tracon.ijobhandler/#Tracon_IJobHandler_ExecuteAsync_Tracon_JobContext_System_Threading_CancellationToken_)).

**Attribution:** a [JobHandlerKeys.Workflow](/api/tracon.jobhandlerkeys/#Tracon_JobHandlerKeys_Workflow) or
[JobHandlerKeys.AgentBatch](/api/tracon.jobhandlerkeys/#Tracon_JobHandlerKeys_AgentBatch) job carries the user and labels
[IRunAttributionContext](/api/tracon.irunattributioncontext/) resolves at the time of this call: the
current request, or an open [AmbientRunAttributionScope](/api/tracon.ambientrunattributionscope/) with
the built-in context. The worker that runs the job sees neither, so they are
written into the stored payload as the envelope
`{"items": [...], "userId": "...", "labels": {...}}`, and every run the
job starts is attributed to them. A payload that is already such an
envelope keeps its own attribution. No other handler key is changed.

## Methods

### <a id="Tracon_IJobDispatcher_EnqueueAsync_Tracon_JobRequest_System_Threading_CancellationToken_"></a> EnqueueAsync\(JobRequest, CancellationToken\)

Validates the request and queues the job.

```csharp
ValueTask<JobRecord> EnqueueAsync(JobRequest request, CancellationToken cancellationToken = default)
```

#### Parameters

`request` [JobRequest](/api/tracon.jobrequest/)

What to run, for whom, and with what input.

`cancellationToken` [CancellationToken](https://learn.microsoft.com/dotnet/api/system.threading.cancellationtoken)

The cancellation token.

#### Returns

 [ValueTask](https://learn.microsoft.com/dotnet/api/system.threading.tasks.valuetask\-1)<[JobRecord](/api/tracon.jobrecord/)\>

The queued job record, with its identifier and counters filled in.

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`request` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

 [ArgumentException](https://learn.microsoft.com/dotnet/api/system.argumentexception)

[JobRequest.HandlerKey](/api/tracon.jobrequest/#Tracon_JobRequest_HandlerKey) is not registered, the request's
tenant, target or lane is not valid, [JobRequest.MaxDuration](/api/tracon.jobrequest/#Tracon_JobRequest_MaxDuration) is
outside one millisecond to about 49.7 days, or a workflow or agent batch
payload is an attribution envelope that is malformed or breaks a
[RunLabels](/api/tracon.runlabels/) limit.
