From 0be4bcad40677d8ed27964dd5b4d86fd87d8a07a Mon Sep 17 00:00:00 2001 From: John Weldon Date: Fri, 25 Jul 2025 11:06:11 -0700 Subject: [PATCH 1/3] Add RequestTimeout option to NatsJSOpts for request operations --- src/NATS.Client.JetStream/NatsJSContext.cs | 10 +++++----- src/NATS.Client.JetStream/NatsJSOpts.cs | 8 +++++++- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/NATS.Client.JetStream/NatsJSContext.cs b/src/NATS.Client.JetStream/NatsJSContext.cs index dbb4eddef..bf9dc16a7 100644 --- a/src/NATS.Client.JetStream/NatsJSContext.cs +++ b/src/NATS.Client.JetStream/NatsJSContext.cs @@ -181,7 +181,7 @@ public async ValueTask> TryPublishAsync( requestSerializer: serializer, replySerializer: NatsJSJsonSerializer.Default, requestOpts: opts, - replyOpts: new NatsSubOpts { Timeout = Connection.Opts.RequestTimeout }, + replyOpts: new NatsSubOpts { Timeout = Opts.RequestTimeout ?? Connection.Opts.RequestTimeout }, cancellationToken).ConfigureAwait(false); } catch (NatsNoReplyException) @@ -223,7 +223,7 @@ public async ValueTask> TryPublishAsync( // is a reconnect to the cluster between the request and waiting for a response, // without the timeout the publish call will hang forever since the server // which received the request won't be there to respond anymore. - Timeout = Connection.Opts.RequestTimeout, + Timeout = Opts.RequestTimeout ?? Connection.Opts.RequestTimeout, }, cancellationToken) .ConfigureAwait(false); @@ -314,7 +314,7 @@ public async ValueTask PublishConcurrentAsync( // is a reconnect to the cluster between the request and waiting for a response, // without the timeout the publish call will hang forever since the server // which received the request won't be there to respond anymore. - Timeout = Connection.Opts.RequestTimeout, + Timeout = Opts.RequestTimeout ?? Connection.Opts.RequestTimeout, // If JetStream is disabled, a no responders error will be returned // No responders error might also happen when reconnecting to cluster @@ -403,7 +403,7 @@ internal async ValueTask>> TryJSRequestAsyn subject: subject, data: request, headers: null, - replyOpts: new NatsSubOpts { Timeout = Connection.Opts.RequestTimeout }, + replyOpts: new NatsSubOpts { Timeout = Opts.RequestTimeout ?? Connection.Opts.RequestTimeout }, requestSerializer: NatsJSJsonSerializer.Default, replySerializer: NatsJSJsonDocumentSerializer.Default, cancellationToken: cancellationToken).ConfigureAwait(false); @@ -444,7 +444,7 @@ internal async ValueTask>> TryJSRequestAsyn subject: subject, data: request, headers: default, - replyOpts: new NatsSubOpts { Timeout = Connection.Opts.RequestTimeout }, + replyOpts: new NatsSubOpts { Timeout = Opts.RequestTimeout ?? Connection.Opts.RequestTimeout }, requestSerializer: NatsJSJsonSerializer.Default, replySerializer: NatsJSJsonDocumentSerializer.Default, cancellationToken: cancellationToken) diff --git a/src/NATS.Client.JetStream/NatsJSOpts.cs b/src/NATS.Client.JetStream/NatsJSOpts.cs index cf8995f58..aad72e258 100644 --- a/src/NATS.Client.JetStream/NatsJSOpts.cs +++ b/src/NATS.Client.JetStream/NatsJSOpts.cs @@ -8,7 +8,7 @@ namespace NATS.Client.JetStream; /// public record NatsJSOpts { - public NatsJSOpts(NatsOpts opts, string? apiPrefix = default, string? domain = default, AckOpts? ackOpts = default) + public NatsJSOpts(NatsOpts opts, string? apiPrefix = default, string? domain = default, AckOpts? ackOpts = default, TimeSpan? requestTimeout = default) { if (apiPrefix != null && domain != null) { @@ -17,6 +17,7 @@ public NatsJSOpts(NatsOpts opts, string? apiPrefix = default, string? domain = d ApiPrefix = apiPrefix ?? "$JS.API"; Domain = domain; + RequestTimeout = requestTimeout ?? opts.RequestTimeout; } /// @@ -34,6 +35,11 @@ public NatsJSOpts(NatsOpts opts, string? apiPrefix = default, string? domain = d /// public string? Domain { get; } + /// + /// Timeout for JetStream API calls. + /// + public TimeSpan? RequestTimeout { get; init; } + /// /// Ask server for an acknowledgment. /// From a329dbe2b80d14245938ad3cb7a07c086e102aec Mon Sep 17 00:00:00 2001 From: John Weldon Date: Fri, 25 Jul 2025 14:07:23 -0700 Subject: [PATCH 2/3] Add case-insensitive grep option for workflow check on signatures --- .github/workflows/signoffs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/signoffs.yml b/.github/workflows/signoffs.yml index 6e0d14ea4..e6e5db74d 100644 --- a/.github/workflows/signoffs.yml +++ b/.github/workflows/signoffs.yml @@ -16,7 +16,7 @@ jobs: if: github.event_name == 'pull_request' run: | for commit in $(git rev-list "origin/${{ github.base_ref }}".."${{ github.event.pull_request.head.sha }}"); do - if ! git verify-commit --raw $commit 2>&1 | grep -q SIG; then + if ! git verify-commit --raw $commit 2>&1 | grep -iq SIG; then echo "--------------------------------------------------------------" echo "Error: Commit $commit is not signed using GPG, SSH, or S/MIME" echo "https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits" From 6f6fc3a81c9c7df06b89a6557533917f553e9944 Mon Sep 17 00:00:00 2001 From: John Weldon Date: Fri, 25 Jul 2025 17:33:45 -0700 Subject: [PATCH 3/3] NatsJSOpts RequestTimeout is now non-nullable, defaulting to the connection NatsOpts value --- src/NATS.Client.JetStream/NatsJSContext.cs | 10 +++++----- src/NATS.Client.JetStream/NatsJSOpts.cs | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/NATS.Client.JetStream/NatsJSContext.cs b/src/NATS.Client.JetStream/NatsJSContext.cs index bf9dc16a7..30f8004d5 100644 --- a/src/NATS.Client.JetStream/NatsJSContext.cs +++ b/src/NATS.Client.JetStream/NatsJSContext.cs @@ -181,7 +181,7 @@ public async ValueTask> TryPublishAsync( requestSerializer: serializer, replySerializer: NatsJSJsonSerializer.Default, requestOpts: opts, - replyOpts: new NatsSubOpts { Timeout = Opts.RequestTimeout ?? Connection.Opts.RequestTimeout }, + replyOpts: new NatsSubOpts { Timeout = Opts.RequestTimeout }, cancellationToken).ConfigureAwait(false); } catch (NatsNoReplyException) @@ -223,7 +223,7 @@ public async ValueTask> TryPublishAsync( // is a reconnect to the cluster between the request and waiting for a response, // without the timeout the publish call will hang forever since the server // which received the request won't be there to respond anymore. - Timeout = Opts.RequestTimeout ?? Connection.Opts.RequestTimeout, + Timeout = Opts.RequestTimeout, }, cancellationToken) .ConfigureAwait(false); @@ -314,7 +314,7 @@ public async ValueTask PublishConcurrentAsync( // is a reconnect to the cluster between the request and waiting for a response, // without the timeout the publish call will hang forever since the server // which received the request won't be there to respond anymore. - Timeout = Opts.RequestTimeout ?? Connection.Opts.RequestTimeout, + Timeout = Opts.RequestTimeout, // If JetStream is disabled, a no responders error will be returned // No responders error might also happen when reconnecting to cluster @@ -403,7 +403,7 @@ internal async ValueTask>> TryJSRequestAsyn subject: subject, data: request, headers: null, - replyOpts: new NatsSubOpts { Timeout = Opts.RequestTimeout ?? Connection.Opts.RequestTimeout }, + replyOpts: new NatsSubOpts { Timeout = Opts.RequestTimeout }, requestSerializer: NatsJSJsonSerializer.Default, replySerializer: NatsJSJsonDocumentSerializer.Default, cancellationToken: cancellationToken).ConfigureAwait(false); @@ -444,7 +444,7 @@ internal async ValueTask>> TryJSRequestAsyn subject: subject, data: request, headers: default, - replyOpts: new NatsSubOpts { Timeout = Opts.RequestTimeout ?? Connection.Opts.RequestTimeout }, + replyOpts: new NatsSubOpts { Timeout = Opts.RequestTimeout }, requestSerializer: NatsJSJsonSerializer.Default, replySerializer: NatsJSJsonDocumentSerializer.Default, cancellationToken: cancellationToken) diff --git a/src/NATS.Client.JetStream/NatsJSOpts.cs b/src/NATS.Client.JetStream/NatsJSOpts.cs index aad72e258..0611e2c3d 100644 --- a/src/NATS.Client.JetStream/NatsJSOpts.cs +++ b/src/NATS.Client.JetStream/NatsJSOpts.cs @@ -38,7 +38,7 @@ public NatsJSOpts(NatsOpts opts, string? apiPrefix = default, string? domain = d /// /// Timeout for JetStream API calls. /// - public TimeSpan? RequestTimeout { get; init; } + public TimeSpan RequestTimeout { get; } /// /// Ask server for an acknowledgment.