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

Information
Class: AsyncResponse.WorkerJobScope
Assembly: AsyncResponse.Core
File(s): /_/src/AsyncResponse.Core/WorkerJobScope.cs
Line coverage
90%
Covered lines: 10
Uncovered lines: 1
Coverable lines: 11
Total lines: 50
Line coverage: 90.9%
Branch coverage
50%
Covered branches: 1
Total branches: 2
Branch coverage: 50%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
get_Current()100%11100%
Enter(...)100%11100%
.ctor(...)100%11100%
Dispose()50%2280%

File(s)

/_/src/AsyncResponse.Core/WorkerJobScope.cs

#LineLine coverage
 1namespace AsyncResponse;
 2
 3/// <summary>
 4/// The worker job executing on the current async flow, published by <c>WorkerJobExecutor</c> for
 5/// the duration of the invocation.
 6/// <para>
 7/// The durable-flow executor needs the job's identity (<see cref="WorkerJobEnvelope.JobId"/>), and
 8/// the envelope itself, to handle one case the invoked method cannot see from its arguments: the
 9/// broker redelivering the very job whose handler is still running, because an in-flight ceiling
 10/// lapsed under it. That delivery finds the execution lease held by its own first delivery; it is
 11/// the only copy of the run's wake-up the broker still has, so it must be recognised (the lease
 12/// records the job) and, where the transport can delay, re-published as the SAME job.
 13/// </para>
 14/// <para>
 15/// Entered by the frame that awaits the invocation, and entered for EVERY job — including one
 16/// that carries no id. An <see cref="AsyncLocal{T}"/> value written inside an async callee never
 17/// flows back to its caller, so the executor cannot delegate this to a helper; and the in-memory
 18/// transport runs a job under its ENQUEUER's captured execution context, so a follow-up job would
 19/// otherwise inherit the ambient job of whichever handler published it.
 20/// </para>
 21/// </summary>
 22internal static class WorkerJobScope
 23{
 1524    private static readonly AsyncLocal<WorkerJobEnvelope?> _current = new();
 25
 26    /// <summary>The job executing on this async flow, or <c>null</c> outside a worker job.</summary>
 203327    public static WorkerJobEnvelope? Current => _current.Value;
 28
 29    /// <summary>Publishes <paramref name="job"/> as the executing job until the returned scope is disposed.</summary>
 30    public static IDisposable Enter(WorkerJobEnvelope job)
 31    {
 628832        var previous = _current.Value;
 628833        _current.Value = job;
 628834        return new Scope(previous);
 35    }
 36
 628837    private sealed class Scope(WorkerJobEnvelope? _previous) : IDisposable
 38    {
 39        private bool _disposed;
 40
 41        public void Dispose()
 42        {
 627443            if (_disposed)
 044                return;
 45
 627446            _disposed = true;
 627447            _current.Value = _previous;
 627448        }
 49    }
 50}