3131- Modify: ` durabletask/grpc_options.py `
3232- Create: ` tests/durabletask/test_grpc_resiliency.py `
3333
34- - [ ] ** Step 1: Write the failing option tests**
34+ - [x ] ** Step 1: Write the failing option tests**
3535
3636``` python
3737import pytest
@@ -81,13 +81,13 @@ def test_client_resiliency_rejects_negative_cooldown():
8181 GrpcClientResiliencyOptions(min_recreate_interval_seconds = - 1.0 )
8282```
8383
84- - [ ] ** Step 2: Run the test to verify it fails**
84+ - [x ] ** Step 2: Run the test to verify it fails**
8585
8686Run: ` python -m pytest tests/durabletask/test_grpc_resiliency.py -v `
8787
8888Expected: FAIL with ` ImportError ` or ` AttributeError ` because the new option classes do not exist yet.
8989
90- - [ ] ** Step 3: Write the minimal implementation**
90+ - [x ] ** Step 3: Write the minimal implementation**
9191
9292``` python
9393from dataclasses import dataclass, field
@@ -131,13 +131,13 @@ class GrpcClientResiliencyOptions:
131131 raise ValueError (" min_recreate_interval_seconds must be >= 0" )
132132```
133133
134- - [ ] ** Step 4: Run the tests to verify they pass**
134+ - [x ] ** Step 4: Run the tests to verify they pass**
135135
136136Run: ` python -m pytest tests/durabletask/test_grpc_resiliency.py -v `
137137
138138Expected: PASS for the new option validation tests.
139139
140- - [ ] ** Step 5: Commit**
140+ - [x ] ** Step 5: Commit**
141141
142142``` bash
143143git add durabletask/grpc_options.py tests/durabletask/test_grpc_resiliency.py
@@ -154,7 +154,7 @@ git commit -m "Add gRPC resiliency option types"
154154- Modify: ` tests/durabletask/test_client.py `
155155- Create: ` tests/durabletask-azuremanaged/test_grpc_resiliency.py `
156156
157- - [ ] ** Step 1: Write the failing constructor and wrapper tests**
157+ - [x ] ** Step 1: Write the failing constructor and wrapper tests**
158158
159159``` python
160160from unittest.mock import MagicMock, patch
@@ -225,13 +225,13 @@ def test_dts_worker_passes_resiliency_options_to_base_worker():
225225 assert mock_init.call_args.kwargs[" resiliency_options" ] is resiliency
226226```
227227
228- - [ ] ** Step 2: Run the tests to verify they fail**
228+ - [x ] ** Step 2: Run the tests to verify they fail**
229229
230230Run: ` python -m pytest tests/durabletask/test_client.py tests/durabletask-azuremanaged/test_grpc_resiliency.py -v `
231231
232232Expected: FAIL because the constructors do not accept ` resiliency_options ` yet and do not retain enough transport state for later recreation.
233233
234- - [ ] ** Step 3: Write the minimal implementation**
234+ - [x ] ** Step 3: Write the minimal implementation**
235235
236236``` python
237237self ._host_address = host_address if host_address else shared.get_default_host_address()
@@ -279,13 +279,13 @@ super().__init__(
279279)
280280```
281281
282- - [ ] ** Step 4: Run the tests to verify they pass**
282+ - [x ] ** Step 4: Run the tests to verify they pass**
283283
284284Run: ` python -m pytest tests/durabletask/test_client.py tests/durabletask-azuremanaged/test_grpc_resiliency.py -v `
285285
286286Expected: PASS for the new constructor and wrapper pass-through tests.
287287
288- - [ ] ** Step 5: Commit**
288+ - [x ] ** Step 5: Commit**
289289
290290``` bash
291291git add durabletask/client.py durabletask/worker.py durabletask-azuremanaged/durabletask/azuremanaged/client.py durabletask-azuremanaged/durabletask/azuremanaged/worker.py tests/durabletask/test_client.py tests/durabletask-azuremanaged/test_grpc_resiliency.py
@@ -298,7 +298,7 @@ git commit -m "Thread gRPC resiliency options through constructors"
298298- Create: ` durabletask/internal/grpc_resiliency.py `
299299- Modify: ` tests/durabletask/test_grpc_resiliency.py `
300300
301- - [ ] ** Step 1: Write the failing helper tests**
301+ - [x ] ** Step 1: Write the failing helper tests**
302302
303303``` python
304304import grpc
@@ -340,13 +340,13 @@ def test_worker_transport_failure_filters_application_errors():
340340 assert is_worker_transport_failure(grpc.StatusCode.NOT_FOUND ) is False
341341```
342342
343- - [ ] ** Step 2: Run the tests to verify they fail**
343+ - [x ] ** Step 2: Run the tests to verify they fail**
344344
345345Run: ` python -m pytest tests/durabletask/test_grpc_resiliency.py -k "jitter or tracker or transport_failure" -v `
346346
347347Expected: FAIL because the shared helper module and helper functions do not exist yet.
348348
349- - [ ] ** Step 3: Write the minimal implementation**
349+ - [x ] ** Step 3: Write the minimal implementation**
350350
351351``` python
352352import random
@@ -399,13 +399,13 @@ def is_worker_transport_failure(status_code: grpc.StatusCode) -> bool:
399399 }
400400```
401401
402- - [ ] ** Step 4: Run the tests to verify they pass**
402+ - [x ] ** Step 4: Run the tests to verify they pass**
403403
404404Run: ` python -m pytest tests/durabletask/test_grpc_resiliency.py -v `
405405
406406Expected: PASS for the helper and option tests together.
407407
408- - [ ] ** Step 5: Commit**
408+ - [x ] ** Step 5: Commit**
409409
410410``` bash
411411git add durabletask/internal/grpc_resiliency.py tests/durabletask/test_grpc_resiliency.py
@@ -418,7 +418,7 @@ git commit -m "Add shared gRPC resiliency helpers"
418418- Modify: ` durabletask/worker.py `
419419- Create: ` tests/durabletask/test_worker_resiliency.py `
420420
421- - [ ] ** Step 1: Write the failing worker resiliency tests**
421+ - [x ] ** Step 1: Write the failing worker resiliency tests**
422422
423423``` python
424424import grpc
@@ -461,13 +461,13 @@ def test_worker_does_not_recreate_caller_owned_channel():
461461 assert worker._can_recreate_channel() is False
462462```
463463
464- - [ ] ** Step 2: Run the tests to verify they fail**
464+ - [x ] ** Step 2: Run the tests to verify they fail**
465465
466466Run: ` python -m pytest tests/durabletask/test_worker_resiliency.py -v `
467467
468468Expected: FAIL because the worker does not expose explicit stream-outcome helpers yet and still uses ad hoc reconnect bookkeeping.
469469
470- - [ ] ** Step 3: Write the minimal implementation**
470+ - [x ] ** Step 3: Write the minimal implementation**
471471
472472``` python
473473class _WorkItemStreamOutcome (Enum ):
@@ -513,13 +513,13 @@ if work_item.HasField("healthPing"):
513513 continue
514514```
515515
516- - [ ] ** Step 4: Run the worker tests**
516+ - [x ] ** Step 4: Run the worker tests**
517517
518518Run: ` python -m pytest tests/durabletask/test_worker_resiliency.py -v `
519519
520520Expected: PASS for the worker classification and ownership tests.
521521
522- - [ ] ** Step 5: Commit**
522+ - [x ] ** Step 5: Commit**
523523
524524``` bash
525525git add durabletask/worker.py tests/durabletask/test_worker_resiliency.py
@@ -532,7 +532,7 @@ git commit -m "Harden worker gRPC stream reconnect behavior"
532532- Modify: ` durabletask/client.py `
533533- Modify: ` tests/durabletask/test_client.py `
534534
535- - [ ] ** Step 1: Write the failing sync client recreation tests**
535+ - [x ] ** Step 1: Write the failing sync client recreation tests**
536536
537537``` python
538538import grpc
@@ -589,13 +589,13 @@ def test_sync_client_does_not_count_long_poll_deadline():
589589 assert client._client_failure_tracker.consecutive_failures == 0
590590```
591591
592- - [ ] ** Step 2: Run the tests to verify they fail**
592+ - [x ] ** Step 2: Run the tests to verify they fail**
593593
594594Run: ` python -m pytest tests/durabletask/test_client.py -k "recreates_sdk_owned_channel or long_poll_deadline" -v `
595595
596596Expected: FAIL because client calls still go directly through the stub and the client has no failure tracker or channel recreation path.
597597
598- - [ ] ** Step 3: Write the minimal implementation**
598+ - [x ] ** Step 3: Write the minimal implementation**
599599
600600``` python
601601self ._client_failure_tracker = FailureTracker(
@@ -643,13 +643,13 @@ def _maybe_recreate_channel(self) -> None:
643643 threading.Timer(30.0 , old_channel.close).start()
644644```
645645
646- - [ ] ** Step 4: Run the tests to verify they pass**
646+ - [x ] ** Step 4: Run the tests to verify they pass**
647647
648648Run: ` python -m pytest tests/durabletask/test_client.py -k "recreates_sdk_owned_channel or long_poll_deadline" -v `
649649
650650Expected: PASS for both new sync client tests and no regressions in the existing client construction tests.
651651
652- - [ ] ** Step 5: Commit**
652+ - [x ] ** Step 5: Commit**
653653
654654``` bash
655655git add durabletask/client.py tests/durabletask/test_client.py
@@ -662,7 +662,7 @@ git commit -m "Add sync client gRPC channel recreation"
662662- Modify: ` durabletask/client.py `
663663- Modify: ` tests/durabletask/test_client.py `
664664
665- - [ ] ** Step 1: Write the failing async client recreation tests**
665+ - [x ] ** Step 1: Write the failing async client recreation tests**
666666
667667``` python
668668import grpc
@@ -716,13 +716,13 @@ async def test_async_client_does_not_count_wait_for_orchestration_deadline():
716716 assert client._client_failure_tracker.consecutive_failures == 0
717717```
718718
719- - [ ] ** Step 2: Run the tests to verify they fail**
719+ - [x ] ** Step 2: Run the tests to verify they fail**
720720
721721Run: ` python -m pytest tests/durabletask/test_client.py -k "async_client_recreates_sdk_owned_channel or async_client_does_not_count" -v `
722722
723723Expected: FAIL because the async client still awaits stub methods directly and has no async-safe recreation path.
724724
725- - [ ] ** Step 3: Write the minimal implementation**
725+ - [x ] ** Step 3: Write the minimal implementation**
726726
727727``` python
728728self ._client_failure_tracker = FailureTracker(
@@ -775,13 +775,13 @@ async def _close_retired_channel(self, channel: grpc.aio.Channel) -> None:
775775 await channel.close()
776776```
777777
778- - [ ] ** Step 4: Run the tests to verify they pass**
778+ - [x ] ** Step 4: Run the tests to verify they pass**
779779
780780Run: ` python -m pytest tests/durabletask/test_client.py -k "async_client_recreates_sdk_owned_channel or async_client_does_not_count" -v `
781781
782782Expected: PASS for the async recreation tests and no regressions in the existing async client construction tests.
783783
784- - [ ] ** Step 5: Commit**
784+ - [x ] ** Step 5: Commit**
785785
786786``` bash
787787git add durabletask/client.py tests/durabletask/test_client.py
@@ -796,7 +796,7 @@ git commit -m "Add async client gRPC channel recreation"
796796- Modify: ` docs/superpowers/specs/2026-04-23-grpc-resiliency-design.md ` (only if the implementation changed the agreed design)
797797- Modify: ` docs/superpowers/plans/2026-04-23-grpc-resiliency.md ` (check off completed steps only after execution)
798798
799- - [ ] ** Step 1: Add the changelog entries**
799+ - [x ] ** Step 1: Add the changelog entries**
800800
801801``` markdown
802802## Unreleased
@@ -814,7 +814,7 @@ git commit -m "Add async client gRPC channel recreation"
814814- Added pass-through support for the new gRPC resiliency option types on Azure Managed clients and workers.
815815```
816816
817- - [ ] ** Step 2: Run the focused tests**
817+ - [x ] ** Step 2: Run the focused tests**
818818
819819Run:
820820
@@ -824,7 +824,7 @@ python -m pytest tests/durabletask/test_grpc_resiliency.py tests/durabletask/tes
824824
825825Expected: PASS for all new and touched unit tests.
826826
827- - [ ] ** Step 3: Run lint on the changed Python files**
827+ - [x ] ** Step 3: Run lint on the changed Python files**
828828
829829Run:
830830
@@ -834,7 +834,7 @@ python -m flake8 durabletask/grpc_options.py durabletask/internal/grpc_resilienc
834834
835835Expected: no output
836836
837- - [ ] ** Step 4: Run the full test suite**
837+ - [x ] ** Step 4: Run the full test suite**
838838
839839Run:
840840
@@ -844,7 +844,7 @@ python -m pytest
844844
845845Expected: PASS across the repository, including the existing orchestration and Azure Managed test suites.
846846
847- - [ ] ** Step 5: Commit**
847+ - [x ] ** Step 5: Commit**
848848
849849``` bash
850850git add CHANGELOG.md durabletask-azuremanaged/CHANGELOG.md durabletask/grpc_options.py durabletask/internal/grpc_resiliency.py durabletask/client.py durabletask/worker.py durabletask-azuremanaged/durabletask/azuremanaged/client.py durabletask-azuremanaged/durabletask/azuremanaged/worker.py tests/durabletask/test_grpc_resiliency.py tests/durabletask/test_worker_resiliency.py tests/durabletask/test_client.py tests/durabletask-azuremanaged/test_grpc_resiliency.py
0 commit comments