Repository navigation
Support opt-in unary client deadlines - #826
Open
wangbill (YunchuWang) wants to merge 3 commits into
Open
wangbill (YunchuWang) wants to merge 3 commits into
wangbill (YunchuWang) wants to merge 3 commits into
Conversation
Apply optional per-call gRPC deadlines without changing default timeouts, long polls or streams. Preserve caller cancellation without erasing prior transport failures and verify shared-channel recovery over loopback HTTP/2. Fixes #824 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1e2ddb82-9306-4e21-8e6c-1c753d09f684
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
No blocking issues were identified in the opt-in deadline behavior, compatibility, or recovery integration, and the changes include focused regression coverage.
No open issues 🎉
What changed in this PR
Adds opt-in unary RPC deadlines to the Durable Task SDK’s gRPC and scheduler clients, addressing stalled management calls without changing the default timeout behavior.
Changes:
- Adds
DefaultUnaryCallTimeout, preserves earlier deadlines, and excludes long-poll waits and streams. - Makes cancellation neutral in channel recovery so it no longer clears prior transport failures.
- Adds unit and loopback integration coverage, plus configuration and mutation-timeout guidance.
| File | Description |
|---|---|
test/Grpc.IntegrationTests/ClientDeadlineTests.cs |
Tests stalled-call recovery, shared channels, and payload interception. |
test/Client/Grpc.Tests/GrpcDurableTaskClientInterceptorsTests.cs |
Tests deadline application, exclusions, validation, and option preservation. |
test/Client/Grpc.Tests/GrpcDurableTaskClientChannelRecreationTests.cs |
Tests cancellation preserving transport-failure counts. |
test/Client/AzureManaged.Tests/DurableTaskSchedulerClientExtensionsTests.cs |
Tests named timeout settings and channel-cache reuse. |
src/Client/Grpc/README.md |
Documents timeout configuration and ambiguous mutation outcomes. |
src/Client/Grpc/GrpcDurableTaskClientOptions.cs |
Exposes the optional gRPC timeout setting. |
src/Client/Grpc/GrpcDurableTaskClient.cs |
Integrates timeout enforcement into the interceptor chain. |
src/Client/Grpc/DefaultUnaryCallTimeoutInterceptor.cs |
Applies bounded unary deadlines while preserving earlier deadlines. |
src/Client/Grpc/ChannelRecreatingCallInvoker.cs |
Makes cancellation neutral and shares long-poll classification. |
src/Client/AzureManaged/DurableTaskSchedulerClientOptions.cs |
Exposes the optional scheduler timeout setting. |
src/Client/AzureManaged/DurableTaskSchedulerClientExtensions.cs |
Transfers named scheduler timeout settings to gRPC options. |
Review effort: Balanced
Rename the unreleased option to GrpcCallTimeout, distinguish cancelled caller tokens from server Cancelled responses, and share long-poll classification independently of timeout interception. Join and dispose failed test-host startup and assert the actual 500 ms RPC budget. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1e2ddb82-9306-4e21-8e6c-1c753d09f684
Explain why the shared long-poll classifier excludes both default call deadlines and expected deadline failures. Keep one concise client configuration example and the essential timeout contract. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1e2ddb82-9306-4e21-8e6c-1c753d09f684
Varshitha Bachu (bachuv)
approved these changes
Oct 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
What changed?
GrpcCallTimeoutto gRPC and scheduler client options. It sets a deadline on each unary RPC, not the whole operation, preserves earlier interceptor deadlines, and excludesWaitForInstanceStart,WaitForInstanceCompletion, and streams.Cancelledas neutral in channel recovery only when the caller's token is cancelled; otherwise retain application-response reset semantics. Keep named scheduler configuration, shared-channel recovery, and payload interceptors intact.Why is this change needed?
DeadlineExceededto the existing recovery mechanism without imposing a new default timeout.Issues / work items
Project checklist
release_notes.mdnull.AI-assisted code disclosure (required)
Was an AI tool used? (select one)
If AI was used:
GrpcCallTimeoutname, and a neutral shared long-poll classifier. Human verification checkboxes below remain for the reviewer.AI verification (required if AI was used):
Testing
Automated tests
Cancelledreset controls failed on both unary paths; genuine caller-token cancellation controls passed. The revised tests distinguish both cases and retain real HTTP/2 recovery coverage.dotnet test test\Client\Grpc.Tests\Client.Grpc.Tests.csproj --configuration Release --no-restore --verbosity quietdotnet test test\Client\AzureManaged.Tests\Client.AzureManaged.Tests.csproj --configuration Release --no-restore --verbosity quietdotnet test test\Grpc.IntegrationTests\Grpc.IntegrationTests.csproj --configuration Release --no-restore --filter FullyQualifiedName~ClientDeadlineTests --verbosity quietdotnet build src\Client\Grpc\Client.Grpc.csproj --configuration Release --no-restore --verbosity quietdotnet build src\Client\AzureManaged\Client.AzureManaged.csproj --configuration Release --no-restore --verbosity quietChanged-test formatting checks passed:
git -c core.whitespace=cr-at-eol diff --check origin/main...HEADpassed; the base version ofGrpcDurableTaskClient.csstores CRLF line endings. Builds retain existing nullability, analyzer, and obsolete-API warnings; no diagnostics were reported on the timeout interceptor. Full-solution, emulator, and cloud checks were not run locally; local results do not imply hosted CI passed.The previous-head hosted build failed when
PurgeActivityDeadlineTests.ReportLargePayloadPurgeResults_WhenDeadlineExpires_CancelsRequestAsynctimed out after 5 seconds. That test was not changed or rerun as part of this focused revision; no cause or flaky/pre-existing classification is claimed.Manual validation (only if runtime/behavior changed)
grpc-timeouthas millisecond units (m) and a value from 1 to 500; expiration returnsDeadlineExceeded, while interleaved caller cancellation remainsCancelled.ClientDeadlineTests.StalledReads_WithInterleavedCancellation_RecreateOnceAndRecoverSharedChannelAsync.Notes for reviewers
GrpcCallTimeoutis a new opt-in option and defaults tonull; existing released signatures, serialization, and orchestration replay are unchanged. Its earlier name existed only in this unmerged PR, so no obsolete alias is retained.Cancelledand does not erase prior transport failures. ACancelledresponse with no cancelled caller token resets the count like other application responses; gRPC cannot prove its network origin when caller/server cancellation race.