< Summary - AsyncResponse (Release / net8.0+net10.0 / unit+integration)

Information
Class: AsyncResponse.WorkerJobEnvelopeSchema
Assembly: AsyncResponse.Abstractions
File(s): /_/src/AsyncResponse.Abstractions/IWorkerTransport.cs
Line coverage
100%
Covered lines: 1
Uncovered lines: 0
Coverable lines: 1
Total lines: 121
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
IsReadable(...)100%11100%

File(s)

/_/src/AsyncResponse.Abstractions/IWorkerTransport.cs

#LineLine coverage
 1using System.Text.Json.Serialization;
 2
 3namespace AsyncResponse;
 4
 5/// <summary>
 6/// A worker job offloaded for background execution: a serializable method-call description plus
 7/// the correlation context to restore before executing it.
 8/// </summary>
 9public sealed class WorkerJobEnvelope
 10{
 11    /// <summary>
 12    /// The wire schema version this job was written with. New jobs are always stamped with
 13    /// <see cref="WorkerJobEnvelopeSchema.Current"/>. The property is required on the wire; a missing
 14    /// or unsupported version is rejected so an incompatible producer cannot silently invoke the
 15    /// wrong method shape.
 16    /// </summary>
 17    [JsonRequired]
 18    public int SchemaVersion { get; set; } = WorkerJobEnvelopeSchema.Current;
 19
 20    /// <summary>The service method to execute.</summary>
 21    public required ReflectionCallDto Call { get; set; }
 22
 23    /// <summary>
 24    /// The correlation id captured when the job was enqueued; restored into
 25    /// <see cref="AsyncResponseContext"/> before execution so downstream publishes correlate.
 26    /// </summary>
 27    public string? CorrelationId { get; set; }
 28
 29    /// <summary>
 30    /// The reply target captured when the job was enqueued; restored into
 31    /// <see cref="AsyncResponseContext"/> before execution so downstream remote requests can
 32    /// publish responses to the same generic ingress.
 33    /// </summary>
 34    public AsyncResponseReplyTarget? ReplyTarget { get; set; }
 35
 36    /// <summary>
 37    /// Serialized application ambient context captured when the job was enqueued (see
 38    /// <see cref="IAsyncResponseContextPropagator"/>), restored before the job executes when it is
 39    /// delivered through a broker ingress. <c>null</c> when no context propagators are registered.
 40    /// </summary>
 41    public Dictionary<string, string>? Context { get; set; }
 42
 43    /// <summary>
 44    /// UTC instant before which this job must not execute; <c>null</c> for ordinary immediate jobs.
 45    /// Stamped by delayed publishes (<see cref="IDelayedWorkerTransport"/>). The worker-job
 46    /// executor enforces it: a job delivered early — broker imprecision, or a chunked hop on a
 47    /// transport whose per-publish delay is capped — is re-published for the remaining delay
 48    /// instead of executed, so the due time holds on every transport. Additive wire property:
 49    /// absent on jobs written before it existed.
 50    /// </summary>
 51    public DateTime? NotBeforeUtc { get; set; }
 52
 53    /// <summary>
 54    /// The remaining delay observed the last time the worker-job executor re-published this job
 55    /// for a further hop of the <see cref="NotBeforeUtc"/> chunk chain; <c>null</c> until the
 56    /// first re-publish. Consecutive hops must shrink this value: when the due time was stamped
 57    /// by a different clock than the one gating delivery (client-computed schedule vs the broker
 58    /// clock), a skewed consumer would otherwise re-publish the same remainder forever — and each
 59    /// hop is a fresh message id, so delivery counters reset and the loop could never dead-letter.
 60    /// On a no-progress hop the executor runs the job (early by the skew) instead of re-publishing.
 61    /// Additive wire property: absent on jobs written before it existed.
 62    /// </summary>
 63    public TimeSpan? LastRedelayRemaining { get; set; }
 64
 65    /// <summary>
 66    /// How many consecutive re-publish hops were observed with a non-shrinking remainder (see
 67    /// <see cref="LastRedelayRemaining"/>). A single such hop can be a transient delivery anomaly
 68    /// and is re-published once more; on the second consecutive stall the executor concludes the
 69    /// stamping and delivery-gating clocks persistently disagree and runs the job early by the
 70    /// skew instead of re-publishing forever. Reset to zero whenever a hop makes progress.
 71    /// Additive wire property: absent (zero) on jobs written before it existed.
 72    /// </summary>
 73    public int RedelayStallCount { get; set; }
 74
 75    /// <summary>
 76    /// Identity of this job, minted once when the job is first published and carried unchanged by
 77    /// every copy of it: a broker redelivery, a <see cref="NotBeforeUtc"/> re-publish hop, and a
 78    /// publisher-level retry all keep the id, while two independently enqueued jobs never share
 79    /// one. It lets a consumer tell "the broker redelivered the job a live handler is still
 80    /// executing" (an in-flight ceiling lapsed — see <see cref="IWorkerTransportInFlightLimit"/>)
 81    /// apart from "a second, genuinely redundant job": the durable-flow executor records it with
 82    /// the execution lease and never acknowledges a contending delivery that carries the lease
 83    /// holder's own id, because that delivery is the only copy of the wake-up the broker still
 84    /// has. Opaque; compare ordinally. Additive wire property: absent on jobs written before it
 85    /// existed, which keep the previous evidence-based duplicate handling.
 86    /// </summary>
 87    public string? JobId { get; set; }
 88}
 89
 90/// <summary>
 91/// Publishes worker jobs for background execution. Implement this against your message broker
 92/// of choice for distributed execution (any consumer then feeds the message into
 93/// <see cref="IAsyncResponseIngress.HandleWorkerMessageAsync"/>), or register the built-in
 94/// in-memory queue (<c>AddAsyncResponse().WithInMemoryTransport()</c>) for development and
 95/// single-node deployments. Application hosts should select a full transport package rather than
 96/// raw-registering this interface directly.
 97/// </summary>
 98public interface IWorkerTransport
 99{
 100    /// <summary>Publishes a worker job for asynchronous execution.</summary>
 101    Task PublishAsync(WorkerJobEnvelope job, CancellationToken cancellationToken = default);
 102}
 103
 104/// <summary>
 105/// Wire-schema version stamp for <see cref="WorkerJobEnvelope"/>. New jobs are stamped with
 106/// <see cref="Current"/>. The ingress loader rejects (dead-letters) any job whose version is
 107/// not explicitly supported: an unrecognized producer must never silently invoke an incompatible
 108/// method shape. The JSON property is required.
 109/// </summary>
 110public static class WorkerJobEnvelopeSchema
 111{
 112    /// <summary>The current wire schema version written by this build.</summary>
 113    public const int Current = 1;
 114
 115    /// <summary>
 116    /// Returns <c>true</c> when a job with <paramref name="entryVersion"/> is safe to execute on
 117    /// this build. See <see cref="RecoveryStateSchema.IsReadable"/> for the policy.
 118    /// </summary>
 119    public static bool IsReadable(int entryVersion)
 6324120        => entryVersion == Current;
 121}

Methods/Properties

IsReadable(System.Int32)