Skip to content
Tracon

IJobStore

Namespace Tracon · Assembly Tracon.Abstractions.dll

The store for queued jobs and their items.

public interface IJobStore

The PostgreSql implementation leases with FOR UPDATE SKIP LOCKED: even if multiple workers connect to the same database, a job is picked up by only one worker. The in-memory implementation provides the same contract with a lock and a timestamp.

Important: IJobStore.ReportItemAsync and state transitions must be idempotent — the same item may be reported twice if the lease expires and the job is re-leased.

CancelAsync(string, Guid, CancellationToken)

Section titled “ CancelAsync(string, Guid, CancellationToken)”

Tries to cancel a job. Only a job in the JobStatus.Pending, JobStatus.Leased, or JobStatus.Running state can be cancelled.

ValueTask<bool> CancelAsync(string tenantId, Guid jobId, CancellationToken cancellationToken = default)

tenantId string

The tenant identifier.

jobId Guid

The job identifier.

cancellationToken CancellationToken

The cancellation token.

ValueTask<bool>

true if the cancellation happened.

CompleteAsync(JobCompletion, CancellationToken)

Section titled “ CompleteAsync(JobCompletion, CancellationToken)”

Finalizes a job.

ValueTask CompleteAsync(JobCompletion completion, CancellationToken cancellationToken = default)

completion JobCompletion

The finalization information.

cancellationToken CancellationToken

The cancellation token.

ValueTask

The completion task.

EnqueueAsync(JobRecord, IReadOnlyList<string>, CancellationToken)

Section titled “ EnqueueAsync(JobRecord, IReadOnlyList<string>, CancellationToken)”

Enqueues a new job and creates its items.

ValueTask<JobRecord> EnqueueAsync(JobRecord job, IReadOnlyList<string> items, CancellationToken cancellationToken = default)

job JobRecord

The job record. JobRecord.Status is ignored; the store always starts it with JobStatus.Pending.

items IReadOnlyList<string>

The job’s input list. Sequence numbers are assigned by list order.

cancellationToken CancellationToken

The cancellation token.

ValueTask<JobRecord>

The created job record.

GetAsync(string, Guid, CancellationToken)

Section titled “ GetAsync(string, Guid, CancellationToken)”

Fetches a single job record.

ValueTask<JobRecord?> GetAsync(string tenantId, Guid jobId, CancellationToken cancellationToken = default)

tenantId string

The tenant identifier.

jobId Guid

The job identifier.

cancellationToken CancellationToken

The cancellation token.

ValueTask<JobRecord?>

The record; null if it does not exist or belongs to another tenant.

Counts the jobs still outstanding, grouped by lane and status.

ValueTask<IReadOnlyList<JobQueueDepth>> GetQueueDepthAsync(CancellationToken cancellationToken = default)

cancellationToken CancellationToken

The cancellation token.

ValueTask<IReadOnlyList<JobQueueDepth>>

One record per lane/status pair that has at least one open job. A pair with no open jobs is omitted rather than reported as zero.

Only the open statuses are counted — JobStatus.Pending, JobStatus.Leased, and JobStatus.Running. The terminal ones are already counted by the tracon.job.executions counter as each job finishes; counting them here would make the query’s cost grow with the queue’s whole history instead of with the work that is actually outstanding.

This is an aggregate query, deliberately placed on this interface rather than split into a separate one — the same layout IRunStore.GetStatisticsAsync already uses. It takes no tenant argument: queue depth is an operator signal about the worker pool, which leases across every tenant (IJobStore.LeaseAsync), so there is no tenant boundary to apply here.

The SQL implementations answer this from the jobs_claim_idx index, whose partial condition covers exactly these three statuses.

LeaseAsync(string, TimeSpan, IReadOnlyList<string>?, CancellationToken)

Section titled “ LeaseAsync(string, TimeSpan, IReadOnlyList<string>?, CancellationToken)”

Leases the oldest job ready to run. Returns null if no such job exists.

ValueTask<JobRecord?> LeaseAsync(string owner, TimeSpan leaseDuration, IReadOnlyList<string>? lanes, CancellationToken cancellationToken = default)

owner string

The leasing worker’s identifier.

leaseDuration TimeSpan

The lease’s validity duration.

lanes IReadOnlyList<string>?

Restricts leasing to these lanes (see JobLanes). null or empty applies no filter — a job from any lane may be leased, the same behavior as before lanes existed.

cancellationToken CancellationToken

The cancellation token.

ValueTask<JobRecord?>

The leased job; null if none exists.

Lists a job’s items, by sequence number.

ValueTask<IReadOnlyList<JobItemRecord>> ListItemsAsync(Guid jobId, CancellationToken cancellationToken = default)

jobId Guid

The job identifier.

cancellationToken CancellationToken

The cancellation token.

ValueTask<IReadOnlyList<JobItemRecord>>

The items.

MarkRunningAsync(Guid, string, CancellationToken)

Section titled “ MarkRunningAsync(Guid, string, CancellationToken)”

Transitions a leased (JobStatus.Leased) job to JobStatus.Running. The worker calls this right after obtaining the lease, before starting execution.

ValueTask<bool> MarkRunningAsync(Guid jobId, string owner, CancellationToken cancellationToken = default)

jobId Guid

The job identifier.

owner string

The identifier of the worker holding the lease. The operation is ignored if it does not match.

cancellationToken CancellationToken

The cancellation token.

ValueTask<bool>

true if the transition happened.

Lists jobs by filter. The newest record is returned first.

ValueTask<IReadOnlyList<JobRecord>> QueryAsync(JobQuery query, CancellationToken cancellationToken = default)

query JobQuery

The filter.

cancellationToken CancellationToken

The cancellation token.

ValueTask<IReadOnlyList<JobRecord>>

The records.

ReleaseForRetryAsync(Guid, string, TimeSpan?, CancellationToken)

Section titled “ ReleaseForRetryAsync(Guid, string, TimeSpan?, CancellationToken)”

Returns a job to the JobStatus.Pending state; releases its lease. JobRecord.Attempt does not change here since it is already incremented at lease time.

ValueTask ReleaseForRetryAsync(Guid jobId, string errorMessage, TimeSpan? retryAfter = null, CancellationToken cancellationToken = default)

jobId Guid

The job identifier.

errorMessage string

The most recent attempt’s error.

retryAfter TimeSpan?

The time to wait before the next attempt. If null or zero, the job may be re-leased immediately (the old behavior).

cancellationToken CancellationToken

The cancellation token.

ValueTask

The completion task.

retryAfter pushes the JobRecord.ScheduledFor field forward; since the lease query already applies scheduled_for <= now, backoff needs no additional mechanism.

Webhook delivery builds its 1 min / 5 min / 30 min / 2 hr / 6 hr ladder with this parameter. No second queue or second lease mechanism is written.

RenewLeaseAsync(Guid, string, TimeSpan, CancellationToken)

Section titled “ RenewLeaseAsync(Guid, string, TimeSpan, CancellationToken)”

Extends an in-progress job’s lease. Does not change the job’s status.

ValueTask RenewLeaseAsync(Guid jobId, string owner, TimeSpan leaseDuration, CancellationToken cancellationToken = default)

jobId Guid

The job identifier.

owner string

The identifier of the worker holding the lease. The operation is ignored if it does not match.

leaseDuration TimeSpan

The new lease duration.

cancellationToken CancellationToken

The cancellation token.

ValueTask

The completion task.

ReportItemAsync(JobItemResult, CancellationToken)

Section titled “ ReportItemAsync(JobItemResult, CancellationToken)”

Reports an item’s processing result and updates the job’s JobRecord.DoneItems/JobRecord.FailedItems counters.

ValueTask ReportItemAsync(JobItemResult item, CancellationToken cancellationToken = default)

item JobItemResult

The item result.

cancellationToken CancellationToken

The cancellation token.

ValueTask

The completion task.