Skip to main content

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

PropertyTypeDefaultDescription
Queuestring?nullOverride the queue name for this job.
MaxAttemptsint?nullOverride the maximum retry attempts.
TimeoutTimeSpan?nullOverride the job execution timeout.
TagsDictionary<string, string>?nullCustom key-value metadata attached to the job.
IdempotencyKeystring?nullPrevents duplicate jobs with the same key.
RequestIdstring?nullClient-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