JobOptions
Per-call overrides passed to IJobClient methods. Any property left as null falls through to the next level in the option precedence chain.
Namespace: Zeridion.Flare · Assembly: Zeridion.Flare.dll
public sealed class JobOptions
{
public string? Queue { get; set; }
public int? MaxAttempts { get; set; }
public TimeSpan? Timeout { get; set; }
public Dictionary<string, string>? Tags { get; set; }
public string? IdempotencyKey { get; set; }
public string? RequestId { get; set; }
}
Properties
| Property | Type | Default | Description |
|---|---|---|---|
Queue | string? | null | Override the queue name for this job. |
MaxAttempts | int? | null | Override the maximum retry attempts. |
Timeout | TimeSpan? | null | Override the job execution timeout. |
Tags | Dictionary<string, string>? | null | Custom key-value metadata attached to the job. |
IdempotencyKey | string? | null | Prevents duplicate jobs with the same key. |
RequestId | string? | null | Client-supplied request ID sent as the X-Request-Id HTTP header for end-to-end log correlation. |
:::tip Option precedence
JobOptions has the highest priority. Values set here override the [JobConfig] attribute defaults and hardcoded SDK defaults. See Option precedence for the full resolution order.
:::
Queue
Override which queue the job is assigned to. Workers can be configured to poll specific queues, enabling workload isolation:
await jobs.EnqueueAsync<SendWelcomeEmail>(payload, new JobOptions
{
Queue = "email-priority"
});
MaxAttempts
Override how many times the job will be attempted before moving to the dead letter queue:
await jobs.EnqueueAsync<ProcessPayment>(payload, new JobOptions
{
MaxAttempts = 1 // no retries — fail immediately on error
});
Timeout
Override the maximum execution time. If the job runs longer than this, the CancellationToken in JobContext is cancelled:
await jobs.EnqueueAsync<GenerateReport>(payload, new JobOptions
{
Timeout = TimeSpan.FromMinutes(60) // allow up to 1 hour
});
Tags
Arbitrary key-value metadata attached to the job. Tags are stored with the job, returned in JobStatus.Tags, and visible in the dashboard. Use them for filtering, searching, and correlation:
await jobs.EnqueueAsync<SendWelcomeEmail>(payload, new JobOptions
{
Tags = new Dictionary<string, string>
{
["user_id"] = user.Id,
["campaign"] = "onboarding-q1",
["source"] = "api"
}
});
IdempotencyKey
Prevents duplicate jobs. If a job with the same idempotency key already exists, the API returns a 409 Conflict response and the SDK throws FlareConflictException.
This is critical for scenarios where the same event might trigger multiple enqueue calls — webhook handlers, payment processing, or retry logic in the caller:
await jobs.EnqueueAsync<ProcessPayment>(payload, new JobOptions
{
IdempotencyKey = $"payment:{payload.OrderId}"
});
The idempotency key is scoped to the project (API key). Two different projects can use the same key without conflict.
RequestId
Client-supplied correlation ID sent as the X-Request-Id HTTP header on the enqueue request. Pass your application's trace / correlation / request ID and grep for it in both Zeridion's logs and your own — every API log line and audit row for the request will carry it. If omitted, Zeridion's API generates a server-side ULID and returns it in the response's X-Request-Id header.
await jobs.EnqueueAsync<SendWelcomeEmail>(payload, new JobOptions
{
RequestId = Activity.Current?.TraceId.ToString() ?? Guid.NewGuid().ToString("N")
});
RequestId is set per-call only — it never cascades from [JobConfig] or ZeridionFlareOptions. The same applies to Tags and IdempotencyKey (see Option precedence).
Usage example
A complete example combining multiple options:
app.MapPost("/orders/{id}/fulfill", async (string id, IJobClient jobs) =>
{
var payload = new FulfillmentPayload { OrderId = id };
var jobId = await jobs.EnqueueAsync<FulfillOrder>(payload, new JobOptions
{
Queue = "fulfillment",
MaxAttempts = 3,
Timeout = TimeSpan.FromMinutes(10),
IdempotencyKey = $"fulfill:{id}",
Tags = new Dictionary<string, string>
{
["order_id"] = id,
["priority"] = "high"
}
});
return Results.Accepted(value: new { job_id = jobId });
});
See also
- [JobConfig] Attribute — class-level defaults (lower priority than
JobOptions) - ZeridionFlareOptions — global options (not currently used in the cascade)
- Option precedence — the two-level cascade
- Idempotency guide — patterns for preventing duplicate work