Skip to content

Commit afa83e1

Browse files
tconley1428claude
andauthored
Fix RetryPolicy.from_proto() pickle error with non_retryable_error_types (#1354)
* Fix RetryPolicy.from_proto() pickle error with non_retryable_error_types Convert protobuf RepeatedScalarContainer to Python list to make RetryPolicy objects picklable when non_retryable_error_types is set. This fixes crashes in sync activities using ProcessPoolExecutor. Fixes #1350 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * Fix linting errors Fix import formatting and code formatting issues in tests/test_common.py 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * Extend latest deps timeout --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 49d6db8 commit afa83e1

3 files changed

Lines changed: 26 additions & 2 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ jobs:
159159
- run: poe lint
160160
- run: mkdir junit-xml
161161
- run: poe test -s --junit-xml=junit-xml/latest-deps.xml
162-
timeout-minutes: 10
162+
timeout-minutes: 15
163163
- name: "Upload junit-xml artifacts"
164164
uses: actions/upload-artifact@v4
165165
if: always()

temporalio/common.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def from_proto(proto: temporalio.api.common.v1.RetryPolicy) -> RetryPolicy:
6969
if proto.HasField("maximum_interval")
7070
else None,
7171
maximum_attempts=proto.maximum_attempts,
72-
non_retryable_error_types=proto.non_retryable_error_types
72+
non_retryable_error_types=list(proto.non_retryable_error_types)
7373
if proto.non_retryable_error_types
7474
else None,
7575
)

tests/test_common.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import pytest
99

1010
from temporalio.api.common.v1 import Payload
11+
from temporalio.api.common.v1 import RetryPolicy as RetryPolicyProto
1112
from temporalio.common import (
1213
Priority,
1314
RawValue,
@@ -123,3 +124,26 @@ def test_cant_construct_bad_priority():
123124
Priority(priority_key=1.1) # type: ignore
124125
with pytest.raises(ValueError):
125126
Priority(priority_key=-1)
127+
128+
129+
def test_retry_policy_from_proto_pickle():
130+
"""Test that RetryPolicy.from_proto() creates a picklable object when non_retryable_error_types is set."""
131+
# Create a protobuf with non_retryable_error_types
132+
proto = RetryPolicyProto()
133+
proto.initial_interval.seconds = 1
134+
proto.backoff_coefficient = 2.0
135+
proto.maximum_attempts = 3
136+
proto.non_retryable_error_types.extend(["SomeError", "AnotherError"])
137+
138+
# Convert from proto
139+
retry_policy = RetryPolicy.from_proto(proto)
140+
141+
# This should not raise a PickleError
142+
pickled = pickle.dumps(retry_policy)
143+
unpickled = pickle.loads(pickled)
144+
145+
# Verify the data is intact
146+
assert unpickled.initial_interval == timedelta(seconds=1)
147+
assert unpickled.backoff_coefficient == 2.0
148+
assert unpickled.maximum_attempts == 3
149+
assert unpickled.non_retryable_error_types == ["SomeError", "AnotherError"]

0 commit comments

Comments
 (0)