Skip to content

Commit 06828ea

Browse files
authored
Update SDK core and minor updates (#221)
Fixes #218 Fixes #214 Fixes #212
1 parent cc679b9 commit 06828ea

File tree

90 files changed

+212
-876
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

90 files changed

+212
-876
lines changed

README.md

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,19 +1013,35 @@ affect calls activity code might make to functions on the `temporalio.activity`
10131013
### Workflow Replay
10141014

10151015
Given a workflow's history, it can be replayed locally to check for things like non-determinism errors. For example,
1016-
assuming `history_json_str` is populated with a JSON string history either exported from the web UI or from `tctl`, the
1016+
assuming `history_str` is populated with a JSON string history either exported from the web UI or from `tctl`, the
10171017
following function will replay it:
10181018

10191019
```python
1020+
from temporalio.client import WorkflowHistory
10201021
from temporalio.worker import Replayer
10211022

1022-
async def run_replayer(history_json_str: str):
1023+
async def run_replayer(history_str: str):
10231024
replayer = Replayer(workflows=[SayHello])
1024-
await replayer.replay_workflow(history_json_str)
1025+
await replayer.replay_workflow(WorkflowHistory.from_json(history_str))
10251026
```
10261027

10271028
This will throw an error if any non-determinism is detected.
10281029

1030+
Replaying from workflow history is a powerful concept that many use to test that workflow alterations won't cause
1031+
non-determinisms with past-complete workflows. The following code will make sure that all workflow histories for a
1032+
certain workflow type (i.e. workflow class) are safe with the current code.
1033+
1034+
```python
1035+
from temporalio.client import Client, WorkflowHistory
1036+
from temporalio.worker import Replayer
1037+
1038+
async def check_past_histories(my_client: Client):
1039+
replayer = Replayer(workflows=[SayHello])
1040+
await replayer.replay_workflows(
1041+
await my_client.list_workflows("WorkflowType = 'SayHello'").map_histories(),
1042+
)
1043+
```
1044+
10291045
### OpenTelemetry Support
10301046

10311047
OpenTelemetry support requires the optional `opentelemetry` dependencies which are part of the `opentelemetry` extra.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
syntax = "proto3";
2+
3+
package temporal.api.common.v1;
4+
5+
import "google/protobuf/any.proto";
6+
7+
// From https://github.com/grpc/grpc/blob/master/src/proto/grpc/status/status.proto
8+
// since we don't import grpc but still need the status info
9+
message GrpcStatus {
10+
int32 code = 1;
11+
string message = 2;
12+
repeated google.protobuf.Any details = 3;
13+
}

scripts/gen_protos.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
health_proto_dir = proto_dir / "grpc"
1616
testsrv_proto_dir = proto_dir / "testsrv_upstream"
1717
test_proto_dir = base_dir / "tests"
18+
additional_proto_dir = base_dir / "scripts" / "_proto"
1819

1920
# Exclude testsrv dependencies protos
2021
proto_paths = [
@@ -23,6 +24,7 @@
2324
if not str(v).startswith(str(testsrv_proto_dir / "dependencies"))
2425
]
2526
proto_paths.extend(test_proto_dir.glob("**/*.proto"))
27+
proto_paths.extend(additional_proto_dir.glob("**/*.proto"))
2628

2729
api_out_dir = base_dir / "temporalio" / "api"
2830
sdk_out_dir = base_dir / "temporalio" / "bridge" / "proto"
@@ -150,16 +152,22 @@ def fix_generated_output(base_path: Path):
150152
f"--proto_path={testsrv_proto_dir}",
151153
f"--proto_path={health_proto_dir}",
152154
f"--proto_path={test_proto_dir}",
155+
f"--proto_path={additional_proto_dir}",
153156
f"--python_out={temp_dir}",
154157
f"--grpc_python_out={temp_dir}",
155158
f"--mypy_out={temp_dir}",
156159
f"--mypy_grpc_out={temp_dir}",
157160
*map(str, proto_paths),
158161
]
159162
)
160-
# Remove health gRPC parts
161-
(temp_dir / "health" / "v1" / "health_pb2_grpc.py").unlink()
162-
(temp_dir / "health" / "v1" / "health_pb2_grpc.pyi").unlink()
163+
# Remove every _grpc.py file that isn't part of a Temporal "service"
164+
for grpc_file in temp_dir.glob("**/*_grpc.py*"):
165+
if (
166+
len(grpc_file.parents) < 2
167+
or grpc_file.parents[0].name != "v1"
168+
or not grpc_file.parents[1].name.endswith("service")
169+
):
170+
grpc_file.unlink()
163171
# Apply fixes before moving code
164172
fix_generated_output(temp_dir)
165173
# Move protos

temporalio/api/batch/v1/message_pb2_grpc.py

Lines changed: 0 additions & 3 deletions
This file was deleted.

temporalio/api/batch/v1/message_pb2_grpc.pyi

Lines changed: 0 additions & 25 deletions
This file was deleted.

temporalio/api/command/v1/message_pb2_grpc.py

Lines changed: 0 additions & 3 deletions
This file was deleted.

temporalio/api/command/v1/message_pb2_grpc.pyi

Lines changed: 0 additions & 25 deletions
This file was deleted.

temporalio/api/common/v1/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from .grpc_status_pb2 import GrpcStatus
12
from .message_pb2 import (
23
ActivityType,
34
DataBlob,
@@ -14,6 +15,7 @@
1415
__all__ = [
1516
"ActivityType",
1617
"DataBlob",
18+
"GrpcStatus",
1719
"Header",
1820
"Memo",
1921
"Payload",

temporalio/api/common/v1/grpc_status_pb2.py

Lines changed: 40 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
"""
2+
@generated by mypy-protobuf. Do not edit manually!
3+
isort:skip_file
4+
"""
5+
import builtins
6+
import collections.abc
7+
import google.protobuf.any_pb2
8+
import google.protobuf.descriptor
9+
import google.protobuf.internal.containers
10+
import google.protobuf.message
11+
import sys
12+
13+
if sys.version_info >= (3, 8):
14+
import typing as typing_extensions
15+
else:
16+
import typing_extensions
17+
18+
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
19+
20+
class GrpcStatus(google.protobuf.message.Message):
21+
"""From https://github.com/grpc/grpc/blob/master/src/proto/grpc/status/status.proto
22+
since we don't import grpc but still need the status info
23+
"""
24+
25+
DESCRIPTOR: google.protobuf.descriptor.Descriptor
26+
27+
CODE_FIELD_NUMBER: builtins.int
28+
MESSAGE_FIELD_NUMBER: builtins.int
29+
DETAILS_FIELD_NUMBER: builtins.int
30+
code: builtins.int
31+
message: builtins.str
32+
@property
33+
def details(
34+
self,
35+
) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[
36+
google.protobuf.any_pb2.Any
37+
]: ...
38+
def __init__(
39+
self,
40+
*,
41+
code: builtins.int = ...,
42+
message: builtins.str = ...,
43+
details: collections.abc.Iterable[google.protobuf.any_pb2.Any] | None = ...,
44+
) -> None: ...
45+
def ClearField(
46+
self,
47+
field_name: typing_extensions.Literal[
48+
"code", b"code", "details", b"details", "message", b"message"
49+
],
50+
) -> None: ...
51+
52+
global___GrpcStatus = GrpcStatus

0 commit comments

Comments
 (0)