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

Information
Class: AsyncResponse.Transports.NATS.NatsAsyncResponseTransportOptions
Assembly: AsyncResponse.Transports.NATS
File(s): /_/src/Transports/AsyncResponse.Transports.NATS/NatsAsyncResponseTransportOptions.cs
Line coverage
100%
Covered lines: 39
Uncovered lines: 0
Coverable lines: 39
Total lines: 170
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

File(s)

/_/src/Transports/AsyncResponse.Transports.NATS/NatsAsyncResponseTransportOptions.cs

#LineLine coverage
 1namespace AsyncResponse.Transports.NATS;
 2
 3/// <summary>
 4/// Options for the NATS JetStream AsyncResponse transport. Requires a NATS server with JetStream
 5/// enabled.
 6/// </summary>
 7public sealed class NatsAsyncResponseTransportOptions
 8{
 9    /// <summary>The transport name reported to reply targets and the startup validator.</summary>
 10    public const string TransportName = "NATS";
 11
 12    /// <summary>
 13    /// Prefix used to derive subject and stream names that are not explicitly configured. The default
 14    /// worker subject is <c>{SubjectPrefix}.transport.worker</c>, the response subject is
 15    /// <c>{SubjectPrefix}.transport.response</c>, and the dead-letter subject is
 16    /// <c>{SubjectPrefix}.transport.deadletter</c>. Stream names replace the dots with underscores
 17    /// (NATS stream names cannot contain dots). Use a unique prefix per app/environment when several
 18    /// deployments share one NATS system.
 19    /// </summary>
 1984620    public string SubjectPrefix { get; set; } = "asyncresponse";
 21
 22    /// <summary>NATS subject worker jobs are published to. When null, <see cref="SubjectPrefix"/> determines it.</summa
 834423    public string? WorkerSubject { get; set; }
 24
 25    /// <summary>JetStream stream that captures the worker subject. When null, <see cref="SubjectPrefix"/> determines it
 454526    public string? WorkerStream { get; set; }
 27
 28    /// <summary>Durable JetStream consumer used by the hosted worker subscriber.</summary>
 365829    public string WorkerConsumer { get; set; } = "asyncresponse-workers";
 30
 31    /// <summary>Worker subject handling options.</summary>
 148332    public NatsSubscriberOptions WorkerSubscriber { get; } = new();
 33
 34    /// <summary>
 35    /// NATS subject remote systems publish response payloads to. The hosted response-ingress
 36    /// subscriber consumes it and forwards payloads into <see cref="IAsyncResponseIngress"/>. When
 37    /// null, <see cref="SubjectPrefix"/> determines it.
 38    /// </summary>
 673139    public string? ResponseSubject { get; set; }
 40
 41    /// <summary>JetStream stream that captures the response subject. When null, <see cref="SubjectPrefix"/> determines 
 365342    public string? ResponseStream { get; set; }
 43
 44    /// <summary>Durable JetStream consumer used by the hosted response-ingress subscriber.</summary>
 300145    public string ResponseConsumer { get; set; } = "asyncresponse-responses";
 46
 47    /// <summary>Response subject handling options.</summary>
 141948    public NatsSubscriberOptions ResponseSubscriber { get; } = new();
 49
 50    /// <summary>
 51    /// Creates the worker and response JetStream streams (and the dead-letter stream when enabled) on
 52    /// subscriber startup when they do not exist. A stream that already exists is never modified:
 53    /// startup fails when it does not capture the configured subject or (worker/response streams)
 54    /// does not use work-queue retention, and logs a warning when its discard policy or message
 55    /// limit differs from these options — settings tuned on the live stream (replicas, max age,
 56    /// max bytes, …) are left alone. Disable when streams are provisioned out of band.
 57    /// </summary>
 148058    public bool CreateStreams { get; set; } = true;
 59
 60    /// <summary>
 61    /// Maximum message count retained per worker/response stream. Set null to disable the limit.
 62    /// Applied when this library creates the stream; a later change is reported as drift, not
 63    /// applied to the existing stream.
 64    /// </summary>
 173365    public long? StreamMaxMessages { get; set; } = 100_000;
 66
 67    /// <summary>
 68    /// Replica count (JetStream <c>num_replicas</c>) for the streams this library creates: worker,
 69    /// response, and dead-letter. <c>1</c>–<c>5</c>; use an odd number (3 or 5) on a clustered
 70    /// JetStream — an even count tolerates no more failures than the odd count below it. Values
 71    /// above 1 require a JetStream cluster with at least that many servers. Only applied when a
 72    /// stream is created; an existing stream keeps its replica count. Default: <c>1</c>.
 73    /// </summary>
 168274    public int StreamReplicas { get; set; } = 1;
 75
 76    /// <summary>How long the server waits for an ACK before redelivering a message (the JetStream AckWait).</summary>
 239077    public TimeSpan AckWait { get; set; } = TimeSpan.FromSeconds(30);
 78
 79    /// <summary>
 80    /// Enables dead-lettering when a message reaches
 81    /// <see cref="NatsSubscriberOptions.MaxDeliveryAttempts"/> or a background handler fails after an
 82    /// early ACK. When true and <see cref="DeadLetterSubject"/> is null, <see cref="SubjectPrefix"/>
 83    /// determines the subject/stream names.
 84    /// </summary>
 125285    public bool DeadLetterEnabled { get; set; } = true;
 86
 87    /// <summary>NATS subject that receives poison messages and already-ACKed background failures.</summary>
 618388    public string? DeadLetterSubject { get; set; }
 89
 90    /// <summary>JetStream stream that captures the dead-letter subject.</summary>
 306191    public string? DeadLetterStream { get; set; }
 92
 93    /// <summary>Maximum dead-letter stream message count. Set null to disable the limit.</summary>
 149894    public long? DeadLetterStreamMaxMessages { get; set; } = 100_000;
 95
 96    /// <summary>The logical reply target name used by <c>WithReplyTarget()</c>. Default: <c>default</c>.</summary>
 114697    public string DefaultReplyTargetName { get; set; } = "default";
 98
 99    /// <summary>
 100    /// Named reply targets exposed to Core through <see cref="IAsyncResponseReplyTargetProvider"/>.
 101    /// When empty, the resolved <see cref="ResponseSubject"/> becomes the default target.
 102    /// </summary>
 462103    public Dictionary<string, NatsReplyTargetOptions> ReplyTargets { get; } = new(StringComparer.Ordinal);
 104
 105    /// <summary>
 106    /// NATS message header carrying the AsyncResponse correlation id. Response messages may omit it
 107    /// when the id is present in the JSON body via <see cref="CorrelationIdJsonPaths"/>.
 108    /// </summary>
 2285109    public string CorrelationIdHeader { get; set; } = "AR-Correlation-Id";
 110
 111    /// <summary>
 112    /// JSON paths inspected when a response message does not carry the correlation id in
 113    /// <see cref="CorrelationIdHeader"/>. Paths are case-insensitive and support nested JSON strings.
 114    /// </summary>
 530115    public string[] CorrelationIdJsonPaths { get; set; } =
 442116    [
 442117        "CorrelationId",
 442118        "CustomParameters",
 442119        "CustomParameters.CorrelationId",
 442120        "PubSubParams.CustomParameters",
 442121        "PubSubParams.CustomParameters.CorrelationId",
 442122        "DagJsonParameters.CorrelationId"
 442123    ];
 124
 125    /// <summary>Maximum attempts for JetStream publish commands. Set to 1 to disable publish retries.</summary>
 1751126    public int PublishMaxAttempts { get; set; } = 3;
 127
 128    /// <summary>Initial delay before retrying a failed publish command.</summary>
 2405129    public TimeSpan PublishRetryBaseDelay { get; set; } = TimeSpan.FromMilliseconds(50);
 130
 131    /// <summary>Maximum delay between publish retry attempts.</summary>
 2405132    public TimeSpan PublishRetryMaxDelay { get; set; } = TimeSpan.FromSeconds(1);
 133
 134    /// <summary>Initial delay after a subscriber consume-loop failure.</summary>
 1777135    public TimeSpan SubscriberRetryBaseDelay { get; set; } = TimeSpan.FromMilliseconds(100);
 136
 137    /// <summary>Maximum delay after repeated subscriber consume-loop failures.</summary>
 1775138    public TimeSpan SubscriberRetryMaxDelay { get; set; } = TimeSpan.FromSeconds(5);
 139
 140    /// <summary>
 141    /// The hosting shutdown budget that must contain
 142    /// <see cref="NatsSubscriberOptions.BackgroundDrainTimeout"/> when a subscriber uses
 143    /// <see cref="NatsAckMode.AckAfterEnqueue"/>. Defaults to the Generic Host default of
 144    /// 30 seconds. Set to <c>null</c> only when this budget is validated externally.
 145    /// </summary>
 490146    public TimeSpan? HostShutdownTimeout { get; set; } = TimeSpan.FromSeconds(30);
 147
 148    /// <summary>Adds or replaces a named NATS reply target.</summary>
 149    public NatsAsyncResponseTransportOptions AddReplyTarget(string name, string responseSubject)
 150    {
 8151        ArgumentException.ThrowIfNullOrWhiteSpace(name);
 8152        ArgumentException.ThrowIfNullOrWhiteSpace(responseSubject);
 153
 8154        ReplyTargets[name] = new NatsReplyTargetOptions { ResponseSubject = responseSubject };
 8155        return this;
 156    }
 157}
 158
 159/// <summary>Options for one named NATS JetStream async-response reply target.</summary>
 160public sealed class NatsReplyTargetOptions
 161{
 162    /// <summary>NATS subject remote systems should publish response payloads to.</summary>
 163    public string? ResponseSubject { get; set; }
 164
 165    /// <summary>Durable consumer that receives responses for this target. Optional metadata.</summary>
 166    public string? Consumer { get; set; }
 167
 168    /// <summary>Additional values copied to the transport-neutral reply target.</summary>
 169    public Dictionary<string, string> Properties { get; } = new(StringComparer.Ordinal);
 170}