fix(r2-02): non-idempotent write arm — cache the no-retry snapshot (01/P-4) and record tracker in-flight accounting (S-8 residual)
This commit is contained in:
@@ -28,6 +28,7 @@ public sealed class CapabilityInvoker : IDriverCapabilityInvoker
|
||||
private readonly string _driverType;
|
||||
private readonly Func<DriverResilienceOptions> _optionsAccessor;
|
||||
private readonly DriverResilienceStatusTracker? _statusTracker;
|
||||
private DriverResilienceOptions? _noRetryWriteOptions;
|
||||
|
||||
/// <summary>
|
||||
/// Construct an invoker for one driver instance.
|
||||
@@ -116,27 +117,44 @@ public sealed class CapabilityInvoker : IDriverCapabilityInvoker
|
||||
|
||||
if (!isIdempotent)
|
||||
{
|
||||
// Snapshot the options exactly once per call — invoking _optionsAccessor twice can
|
||||
// (a) observe two different snapshots if an Admin edit lands between them and
|
||||
// (b) wastes an allocation on the per-write hot path (Phase 6.1 1% pipeline budget).
|
||||
var snapshot = _optionsAccessor();
|
||||
var noRetryOptions = snapshot with
|
||||
{
|
||||
CapabilityPolicies = new Dictionary<DriverCapability, CapabilityPolicy>
|
||||
{
|
||||
[DriverCapability.Write] = snapshot.Resolve(DriverCapability.Write) with { RetryCount = 0 },
|
||||
},
|
||||
};
|
||||
// Build the no-retry options snapshot ONCE per invoker lifetime (01/P-4). The options are
|
||||
// immutable for the invoker's lifetime — a ResilienceConfig change respawns the driver child,
|
||||
// which constructs a fresh invoker (#13 respawn-on-change) — so lazily caching the snapshot is
|
||||
// safe and removes the per-write allocation the previous once-per-call snapshot incurred. The
|
||||
// null-check-assign tolerates a benign first-call race (both threads build an equivalent record).
|
||||
var noRetryOptions = _noRetryWriteOptions ??= BuildNoRetryWriteOptions();
|
||||
var pipeline = _builder.GetOrCreate(_driverInstanceId, $"{hostName}::non-idempotent", DriverCapability.Write, noRetryOptions);
|
||||
using (LogContextEnricher.Push(_driverInstanceId, _driverType, DriverCapability.Write, LogContextEnricher.NewCorrelationId()))
|
||||
// Record in-flight accounting on the CALLER's host (the "::non-idempotent" suffix is a
|
||||
// pipeline-cache key, not an operator-facing host) so Admin /hosts sees write depth too.
|
||||
_statusTracker?.RecordCallStart(_driverInstanceId, hostName);
|
||||
try
|
||||
{
|
||||
return await pipeline.ExecuteAsync(callSite, cancellationToken).ConfigureAwait(false);
|
||||
using (LogContextEnricher.Push(_driverInstanceId, _driverType, DriverCapability.Write, LogContextEnricher.NewCorrelationId()))
|
||||
{
|
||||
return await pipeline.ExecuteAsync(callSite, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_statusTracker?.RecordCallComplete(_driverInstanceId, hostName);
|
||||
}
|
||||
}
|
||||
|
||||
return await ExecuteAsync(DriverCapability.Write, hostName, callSite, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private DriverResilienceOptions BuildNoRetryWriteOptions()
|
||||
{
|
||||
var snapshot = _optionsAccessor();
|
||||
return snapshot with
|
||||
{
|
||||
CapabilityPolicies = new Dictionary<DriverCapability, CapabilityPolicy>
|
||||
{
|
||||
[DriverCapability.Write] = snapshot.Resolve(DriverCapability.Write) with { RetryCount = 0 },
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private ResiliencePipeline ResolvePipeline(DriverCapability capability, string hostName) =>
|
||||
_builder.GetOrCreate(_driverInstanceId, hostName, capability, _optionsAccessor());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user