Skip to main content

[JobConfig] Attribute

A class-level attribute that sets default behavior for a job. Applied to IJob<T> or IRecurringJob implementations. Per-call JobOptions take priority over these defaults.

Namespace: Zeridion.Flare · Assembly: Zeridion.Flare.dll

[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public sealed class JobConfigAttribute : Attribute
{
public string Queue { get; set; } = "default";
public int MaxAttempts { get; set; } = 3;
public int TimeoutSeconds { get; set; } = 1800;
public string? CronSchedule { get; set; }
}

Properties

PropertyTypeDefaultDescription
Queuestring"default"Default queue name for this job type.
MaxAttemptsint3Default maximum retry attempts before dead letter.
TimeoutSecondsint1800Default execution timeout in seconds (30 minutes).
CronSchedulestring?nullCron expression for recurring jobs. Only for IRecurringJob.

How it works

The JobTypeRegistry scans assemblies at startup (triggered by AddZeridionFlare) and reads [JobConfig] attributes from every discovered job class. The attribute values become the defaults for that job type.

When a job is enqueued, the SDK resolves settings in this order:

  1. JobOptions passed to the IJobClient method (highest priority)
  2. [JobConfig] attribute on the job class (or hardcoded defaults if no attribute)

If no [JobConfig] is applied, the attribute defaults ("default", 3, 1800) are used. See Option precedence for details.

Queue

Assign a job type to a specific queue. Workers can be configured to poll only certain queues, enabling workload isolation:

[JobConfig(Queue = "email")]
public class SendWelcomeEmail : IJob<NewUserEvent>
{
public async Task ExecuteAsync(NewUserEvent payload, JobContext ctx)
{
// This job always goes to the "email" queue unless overridden by JobOptions
}
}

MaxAttempts

Set the maximum number of execution attempts. After all attempts are exhausted, the job moves to DeadLetter:

[JobConfig(MaxAttempts = 5)]
public class ProcessPayment : IJob<PaymentPayload>
{
// Will retry up to 4 times (5 total attempts) with exponential backoff
}

TimeoutSeconds

Set the maximum execution time in seconds. The CancellationToken in JobContext is cancelled when the timeout elapses:

[JobConfig(TimeoutSeconds = 300)]  // 5 minutes
public class GeneratePdfReport : IJob<ReportPayload>
{
// Worker cancels the token after 5 minutes
}

CronSchedule

Set a cron expression for IRecurringJob implementations. Uses standard 5-field cron format (parsed by the Cronos library). This property is ignored on IJob<T> classes.

[JobConfig(CronSchedule = "0 3 * * *")]  // Daily at 3:00 AM UTC
public class CleanupExpiredSessions : IRecurringJob
{
public async Task ExecuteAsync(JobContext ctx)
{
// Runs once per day at 3 AM
}
}

Usage examples

Payload job with all options

[JobConfig(Queue = "critical", MaxAttempts = 10, TimeoutSeconds = 600)]
public class SyncInventory : IJob<InventoryPayload>
{
private readonly IInventoryService _inventory;

public SyncInventory(IInventoryService inventory) => _inventory = inventory;

public async Task ExecuteAsync(InventoryPayload payload, JobContext ctx)
{
await _inventory.SyncAsync(payload.WarehouseId, ctx.CancellationToken);
}
}

Recurring job with queue and schedule

[JobConfig(CronSchedule = "*/15 * * * *", Queue = "maintenance", TimeoutSeconds = 120)]
public class PurgeStaleTokens : IRecurringJob
{
private readonly ITokenStore _tokens;

public PurgeStaleTokens(ITokenStore tokens) => _tokens = tokens;

public async Task ExecuteAsync(JobContext ctx)
{
var count = await _tokens.PurgeExpiredAsync(ctx.CancellationToken);
ctx.Logger.LogInformation("Purged {Count} stale tokens", count);
}
}

See also