@temporalio/core-bridge 1.15.0 → 1.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/Cargo.lock +172 -70
  2. package/lib/native.d.ts +1 -1
  3. package/package.json +2 -2
  4. package/releases/aarch64-apple-darwin/index.node +0 -0
  5. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  6. package/releases/x86_64-apple-darwin/index.node +0 -0
  7. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  8. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  9. package/sdk-core/.github/workflows/per-pr.yml +6 -6
  10. package/sdk-core/AGENTS.md +41 -30
  11. package/sdk-core/Cargo.toml +3 -0
  12. package/sdk-core/README.md +15 -9
  13. package/sdk-core/crates/client/Cargo.toml +4 -0
  14. package/sdk-core/crates/client/README.md +139 -0
  15. package/sdk-core/crates/client/src/async_activity_handle.rs +297 -0
  16. package/sdk-core/crates/client/src/callback_based.rs +7 -0
  17. package/sdk-core/crates/client/src/errors.rs +294 -0
  18. package/sdk-core/crates/client/src/{raw.rs → grpc.rs} +280 -159
  19. package/sdk-core/crates/client/src/lib.rs +920 -1326
  20. package/sdk-core/crates/client/src/metrics.rs +24 -33
  21. package/sdk-core/crates/client/src/options_structs.rs +457 -0
  22. package/sdk-core/crates/client/src/replaceable.rs +5 -4
  23. package/sdk-core/crates/client/src/request_extensions.rs +8 -9
  24. package/sdk-core/crates/client/src/retry.rs +99 -54
  25. package/sdk-core/crates/client/src/{worker/mod.rs → worker.rs} +1 -1
  26. package/sdk-core/crates/client/src/workflow_handle.rs +826 -0
  27. package/sdk-core/crates/common/Cargo.toml +61 -2
  28. package/sdk-core/crates/common/build.rs +742 -12
  29. package/sdk-core/crates/common/protos/api_upstream/.github/workflows/ci.yml +2 -0
  30. package/sdk-core/crates/common/protos/api_upstream/Makefile +2 -1
  31. package/sdk-core/crates/common/protos/api_upstream/buf.yaml +0 -3
  32. package/sdk-core/crates/common/protos/api_upstream/cmd/check-path-conflicts/main.go +137 -0
  33. package/sdk-core/crates/common/protos/api_upstream/openapi/openapiv2.json +1166 -770
  34. package/sdk-core/crates/common/protos/api_upstream/openapi/openapiv3.yaml +1243 -750
  35. package/sdk-core/crates/common/protos/api_upstream/temporal/api/deployment/v1/message.proto +2 -2
  36. package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/workflow.proto +4 -3
  37. package/sdk-core/crates/common/protos/api_upstream/temporal/api/failure/v1/message.proto +1 -0
  38. package/sdk-core/crates/common/protos/api_upstream/temporal/api/history/v1/message.proto +4 -0
  39. package/sdk-core/crates/common/protos/api_upstream/temporal/api/namespace/v1/message.proto +6 -0
  40. package/sdk-core/crates/common/protos/api_upstream/temporal/api/nexus/v1/message.proto +16 -1
  41. package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +64 -6
  42. package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +88 -33
  43. package/sdk-core/crates/common/protos/local/temporal/sdk/core/nexus/nexus.proto +4 -2
  44. package/sdk-core/crates/common/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +4 -0
  45. package/sdk-core/crates/common/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +5 -5
  46. package/sdk-core/crates/common/src/activity_definition.rs +20 -0
  47. package/sdk-core/crates/common/src/data_converters.rs +770 -0
  48. package/sdk-core/crates/common/src/envconfig.rs +5 -0
  49. package/sdk-core/crates/common/src/lib.rs +15 -211
  50. package/sdk-core/crates/common/src/payload_visitor.rs +648 -0
  51. package/sdk-core/crates/common/src/priority.rs +110 -0
  52. package/sdk-core/crates/common/src/protos/canned_histories.rs +3 -0
  53. package/sdk-core/crates/common/src/protos/history_builder.rs +45 -0
  54. package/sdk-core/crates/common/src/protos/history_info.rs +2 -0
  55. package/sdk-core/crates/common/src/protos/mod.rs +122 -27
  56. package/sdk-core/crates/common/src/protos/task_token.rs +3 -3
  57. package/sdk-core/crates/common/src/protos/utilities.rs +11 -0
  58. package/sdk-core/crates/{sdk-core → common}/src/telemetry/log_export.rs +5 -7
  59. package/sdk-core/crates/common/src/telemetry/metrics/core.rs +125 -0
  60. package/sdk-core/crates/common/src/telemetry/metrics.rs +268 -223
  61. package/sdk-core/crates/{sdk-core → common}/src/telemetry/otel.rs +8 -13
  62. package/sdk-core/crates/{sdk-core → common}/src/telemetry/prometheus_meter.rs +49 -50
  63. package/sdk-core/crates/{sdk-core → common}/src/telemetry/prometheus_server.rs +2 -3
  64. package/sdk-core/crates/common/src/telemetry.rs +264 -4
  65. package/sdk-core/crates/common/src/worker.rs +68 -603
  66. package/sdk-core/crates/common/src/workflow_definition.rs +60 -0
  67. package/sdk-core/crates/macros/Cargo.toml +5 -1
  68. package/sdk-core/crates/macros/src/activities_definitions.rs +585 -0
  69. package/sdk-core/crates/macros/src/fsm_impl.rs +507 -0
  70. package/sdk-core/crates/macros/src/lib.rs +138 -512
  71. package/sdk-core/crates/macros/src/macro_utils.rs +106 -0
  72. package/sdk-core/crates/macros/src/workflow_definitions.rs +1224 -0
  73. package/sdk-core/crates/sdk/Cargo.toml +19 -6
  74. package/sdk-core/crates/sdk/README.md +415 -0
  75. package/sdk-core/crates/sdk/src/activities.rs +417 -0
  76. package/sdk-core/crates/sdk/src/interceptors.rs +1 -1
  77. package/sdk-core/crates/sdk/src/lib.rs +757 -442
  78. package/sdk-core/crates/sdk/src/workflow_context/options.rs +45 -35
  79. package/sdk-core/crates/sdk/src/workflow_context.rs +1033 -289
  80. package/sdk-core/crates/sdk/src/workflow_future.rs +277 -213
  81. package/sdk-core/crates/sdk/src/workflows.rs +711 -0
  82. package/sdk-core/crates/sdk-core/Cargo.toml +57 -64
  83. package/sdk-core/crates/sdk-core/benches/workflow_replay_bench.rs +41 -35
  84. package/sdk-core/crates/sdk-core/machine_coverage/ActivityMachine_Coverage.puml +1 -1
  85. package/sdk-core/crates/sdk-core/src/abstractions.rs +6 -10
  86. package/sdk-core/crates/sdk-core/src/core_tests/activity_tasks.rs +6 -5
  87. package/sdk-core/crates/sdk-core/src/core_tests/mod.rs +13 -15
  88. package/sdk-core/crates/sdk-core/src/core_tests/queries.rs +21 -25
  89. package/sdk-core/crates/sdk-core/src/core_tests/replay_flag.rs +7 -10
  90. package/sdk-core/crates/sdk-core/src/core_tests/updates.rs +14 -17
  91. package/sdk-core/crates/sdk-core/src/core_tests/workers.rs +493 -26
  92. package/sdk-core/crates/sdk-core/src/core_tests/workflow_tasks.rs +4 -8
  93. package/sdk-core/crates/sdk-core/src/ephemeral_server/mod.rs +7 -7
  94. package/sdk-core/crates/sdk-core/src/histfetch.rs +20 -10
  95. package/sdk-core/crates/sdk-core/src/lib.rs +41 -111
  96. package/sdk-core/crates/sdk-core/src/pollers/mod.rs +4 -9
  97. package/sdk-core/crates/sdk-core/src/pollers/poll_buffer.rs +118 -19
  98. package/sdk-core/crates/sdk-core/src/protosext/mod.rs +2 -2
  99. package/sdk-core/crates/sdk-core/src/replay/mod.rs +14 -5
  100. package/sdk-core/crates/sdk-core/src/telemetry/metrics.rs +179 -196
  101. package/sdk-core/crates/sdk-core/src/telemetry/mod.rs +3 -280
  102. package/sdk-core/crates/sdk-core/src/test_help/integ_helpers.rs +6 -9
  103. package/sdk-core/crates/sdk-core/src/test_help/unit_helpers.rs +3 -6
  104. package/sdk-core/crates/sdk-core/src/worker/activities/local_activities.rs +11 -14
  105. package/sdk-core/crates/sdk-core/src/worker/activities.rs +16 -19
  106. package/sdk-core/crates/sdk-core/src/worker/client/mocks.rs +9 -5
  107. package/sdk-core/crates/sdk-core/src/worker/client.rs +103 -81
  108. package/sdk-core/crates/sdk-core/src/worker/heartbeat.rs +7 -11
  109. package/sdk-core/crates/sdk-core/src/worker/mod.rs +1124 -229
  110. package/sdk-core/crates/sdk-core/src/worker/nexus.rs +145 -23
  111. package/sdk-core/crates/sdk-core/src/worker/slot_provider.rs +2 -2
  112. package/sdk-core/crates/sdk-core/src/worker/tuner/fixed_size.rs +2 -2
  113. package/sdk-core/crates/sdk-core/src/worker/tuner/resource_based.rs +13 -13
  114. package/sdk-core/crates/sdk-core/src/worker/tuner.rs +28 -8
  115. package/sdk-core/crates/sdk-core/src/worker/workflow/driven_workflow.rs +9 -3
  116. package/sdk-core/crates/sdk-core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +21 -22
  117. package/sdk-core/crates/sdk-core/src/worker/workflow/machines/workflow_machines.rs +19 -4
  118. package/sdk-core/crates/sdk-core/src/worker/workflow/managed_run.rs +14 -18
  119. package/sdk-core/crates/sdk-core/src/worker/workflow/mod.rs +4 -6
  120. package/sdk-core/crates/sdk-core/src/worker/workflow/run_cache.rs +4 -7
  121. package/sdk-core/crates/sdk-core/src/worker/workflow/wft_extraction.rs +2 -4
  122. package/sdk-core/crates/sdk-core/src/worker/workflow/wft_poller.rs +8 -9
  123. package/sdk-core/crates/sdk-core/src/worker/workflow/workflow_stream.rs +1 -3
  124. package/sdk-core/crates/sdk-core/tests/activities_procmacro.rs +6 -0
  125. package/sdk-core/crates/sdk-core/tests/activities_trybuild/basic_pass.rs +54 -0
  126. package/sdk-core/crates/sdk-core/tests/activities_trybuild/invalid_self_type_fail.rs +18 -0
  127. package/sdk-core/crates/sdk-core/tests/activities_trybuild/invalid_self_type_fail.stderr +5 -0
  128. package/sdk-core/crates/sdk-core/tests/activities_trybuild/missing_context_fail.rs +14 -0
  129. package/sdk-core/crates/sdk-core/tests/activities_trybuild/missing_context_fail.stderr +5 -0
  130. package/sdk-core/crates/sdk-core/tests/activities_trybuild/multi_arg_pass.rs +48 -0
  131. package/sdk-core/crates/sdk-core/tests/activities_trybuild/no_input_pass.rs +14 -0
  132. package/sdk-core/crates/sdk-core/tests/activities_trybuild/no_return_type_pass.rs +19 -0
  133. package/sdk-core/crates/sdk-core/tests/cloud_tests.rs +14 -5
  134. package/sdk-core/crates/sdk-core/tests/common/activity_functions.rs +55 -0
  135. package/sdk-core/crates/sdk-core/tests/common/mod.rs +241 -196
  136. package/sdk-core/crates/sdk-core/tests/common/workflows.rs +41 -28
  137. package/sdk-core/crates/sdk-core/tests/global_metric_tests.rs +3 -5
  138. package/sdk-core/crates/sdk-core/tests/heavy_tests/fuzzy_workflow.rs +73 -64
  139. package/sdk-core/crates/sdk-core/tests/heavy_tests.rs +298 -252
  140. package/sdk-core/crates/sdk-core/tests/integ_tests/async_activity_client_tests.rs +230 -0
  141. package/sdk-core/crates/sdk-core/tests/integ_tests/client_tests.rs +94 -57
  142. package/sdk-core/crates/sdk-core/tests/integ_tests/data_converter_tests.rs +381 -0
  143. package/sdk-core/crates/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +16 -12
  144. package/sdk-core/crates/sdk-core/tests/integ_tests/heartbeat_tests.rs +48 -40
  145. package/sdk-core/crates/sdk-core/tests/integ_tests/metrics_tests.rs +327 -255
  146. package/sdk-core/crates/sdk-core/tests/integ_tests/pagination_tests.rs +50 -45
  147. package/sdk-core/crates/sdk-core/tests/integ_tests/polling_tests.rs +147 -126
  148. package/sdk-core/crates/sdk-core/tests/integ_tests/queries_tests.rs +103 -89
  149. package/sdk-core/crates/sdk-core/tests/integ_tests/update_tests.rs +609 -453
  150. package/sdk-core/crates/sdk-core/tests/integ_tests/visibility_tests.rs +80 -62
  151. package/sdk-core/crates/sdk-core/tests/integ_tests/worker_heartbeat_tests.rs +360 -231
  152. package/sdk-core/crates/sdk-core/tests/integ_tests/worker_tests.rs +248 -185
  153. package/sdk-core/crates/sdk-core/tests/integ_tests/worker_versioning_tests.rs +52 -43
  154. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_client_tests.rs +180 -0
  155. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/activities.rs +428 -315
  156. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +82 -56
  157. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +56 -28
  158. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +364 -243
  159. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/client_interactions.rs +552 -0
  160. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +101 -42
  161. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +243 -147
  162. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/eager.rs +98 -28
  163. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +1475 -1036
  164. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +73 -41
  165. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/nexus.rs +397 -238
  166. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/patches.rs +414 -189
  167. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/queries.rs +415 -0
  168. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/replay.rs +96 -36
  169. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/resets.rs +154 -137
  170. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/signals.rs +183 -105
  171. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +85 -38
  172. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/timers.rs +142 -40
  173. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +73 -54
  174. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests.rs +363 -226
  175. package/sdk-core/crates/sdk-core/tests/main.rs +17 -15
  176. package/sdk-core/crates/sdk-core/tests/manual_tests.rs +207 -152
  177. package/sdk-core/crates/sdk-core/tests/shared_tests/mod.rs +65 -34
  178. package/sdk-core/crates/sdk-core/tests/shared_tests/priority.rs +107 -84
  179. package/sdk-core/crates/sdk-core/tests/workflows_procmacro.rs +6 -0
  180. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/async_query_fail.rs +26 -0
  181. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/async_query_fail.stderr +5 -0
  182. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/basic_pass.rs +49 -0
  183. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/minimal_pass.rs +21 -0
  184. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/mut_query_fail.rs +26 -0
  185. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/mut_query_fail.stderr +5 -0
  186. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/sync_run_fail.rs +21 -0
  187. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/sync_run_fail.stderr +5 -0
  188. package/sdk-core/crates/sdk-core-c-bridge/Cargo.toml +7 -1
  189. package/sdk-core/crates/sdk-core-c-bridge/include/temporal-sdk-core-c-bridge.h +14 -14
  190. package/sdk-core/crates/sdk-core-c-bridge/src/client.rs +83 -74
  191. package/sdk-core/crates/sdk-core-c-bridge/src/metric.rs +9 -14
  192. package/sdk-core/crates/sdk-core-c-bridge/src/runtime.rs +1 -2
  193. package/sdk-core/crates/sdk-core-c-bridge/src/tests/context.rs +13 -13
  194. package/sdk-core/crates/sdk-core-c-bridge/src/tests/mod.rs +6 -6
  195. package/sdk-core/crates/sdk-core-c-bridge/src/tests/utils.rs +3 -4
  196. package/sdk-core/crates/sdk-core-c-bridge/src/worker.rs +62 -75
  197. package/sdk-core/rustfmt.toml +2 -1
  198. package/src/client.rs +205 -318
  199. package/src/metrics.rs +22 -30
  200. package/src/runtime.rs +4 -5
  201. package/src/worker.rs +16 -19
  202. package/ts/native.ts +1 -1
  203. package/sdk-core/crates/client/src/workflow_handle/mod.rs +0 -212
  204. package/sdk-core/crates/common/src/errors.rs +0 -85
  205. package/sdk-core/crates/common/tests/worker_task_types_test.rs +0 -129
  206. package/sdk-core/crates/sdk/src/activity_context.rs +0 -238
  207. package/sdk-core/crates/sdk/src/app_data.rs +0 -37
  208. package/sdk-core/crates/sdk-core/tests/integ_tests/activity_functions.rs +0 -5
  209. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/appdata_propagation.rs +0 -61
@@ -9,25 +9,30 @@ homepage = "https://temporal.io/"
9
9
  repository = "https://github.com/temporalio/sdk-core"
10
10
  keywords = ["temporal", "workflow"]
11
11
  categories = ["development-tools"]
12
+ readme = "README.md"
12
13
 
13
14
  [dependencies]
14
15
  async-trait = "0.1"
15
16
  anyhow = "1.0"
17
+ bon = { workspace = true }
16
18
  derive_more = { workspace = true }
17
- futures-util = { version = "0.3", default-features = false }
19
+ futures-util = { version = "0.3", default-features = false, features = ["async-await-macro"] }
20
+ gethostname = "1.0.2"
18
21
  parking_lot = { version = "0.12", features = ["send_guard"] }
19
22
  prost-types = { workspace = true }
20
23
  serde = "1.0"
24
+ thiserror = "2"
21
25
  tokio = { version = "1.47", features = [
22
- "rt",
23
- "rt-multi-thread",
24
- "parking_lot",
25
- "time",
26
- "fs",
26
+ "rt",
27
+ "rt-multi-thread",
28
+ "parking_lot",
29
+ "time",
30
+ "fs",
27
31
  ] }
28
32
  tokio-util = { version = "0.7" }
29
33
  tokio-stream = "0.1"
30
34
  tracing = "0.1"
35
+ uuid = { version = "1.18", features = ["v4"] }
31
36
 
32
37
  [dependencies.temporalio-sdk-core]
33
38
  path = "../sdk-core"
@@ -42,6 +47,14 @@ version = "0.1"
42
47
  path = "../client"
43
48
  version = "0.1"
44
49
 
50
+ [dependencies.temporalio-macros]
51
+ path = "../macros"
52
+ version = "0.1"
53
+
54
+ [dev-dependencies]
55
+ futures = "0.3"
56
+ rstest = "0.26"
57
+
45
58
  [features]
46
59
  default = []
47
60
  antithesis_assertions = ["temporalio-sdk-core/antithesis_assertions"]
@@ -0,0 +1,415 @@
1
+ # Temporal Rust SDK
2
+
3
+ [![crates.io](https://img.shields.io/crates/v/temporalio-sdk.svg)](https://crates.io/crates/temporalio-sdk)
4
+ [![docs.rs](https://docs.rs/temporalio-sdk/badge.svg)](https://docs.rs/temporalio-sdk)
5
+
6
+ This crate contains a prerelease Rust SDK. The SDK is built on top of
7
+ Core and provides a native Rust experience for writing Temporal workflows and activities.
8
+
9
+ ⚠️ **The SDK is under active development and should be considered prerelease.** The API can and
10
+ will continue to evolve.
11
+
12
+ ## Quick Start
13
+
14
+ ### Activities
15
+
16
+ Activities are defined using the `#[activities]` and `#[activity]` macros:
17
+
18
+ ```rust
19
+ use temporalio_macros::activities;
20
+ use temporalio_sdk::activities::{ActivityContext, ActivityError};
21
+ use std::sync::{Arc, atomic::{AtomicUsize, Ordering}};
22
+
23
+ struct MyActivities {
24
+ counter: AtomicUsize,
25
+ }
26
+
27
+ #[activities]
28
+ impl MyActivities {
29
+ #[activity]
30
+ pub async fn greet(_ctx: ActivityContext, name: String) -> Result<String, ActivityError> {
31
+ Ok(format!("Hello, {}!", name))
32
+ }
33
+
34
+ // Activities can also use shared state via Arc<Self>
35
+ #[activity]
36
+ pub async fn increment(self: Arc<Self>, _ctx: ActivityContext) -> Result<u32, ActivityError> {
37
+ Ok(self.counter.fetch_add(1, Ordering::Relaxed) as u32)
38
+ }
39
+ }
40
+ ```
41
+
42
+ ### Workflows
43
+
44
+ Workflows are defined using the `#[workflow]` and `#[workflow_methods]` macros:
45
+
46
+ ```rust
47
+ use temporalio_macros::{workflow, workflow_methods};
48
+ use temporalio_sdk::{WorkflowContext, WorkflowContextView, WorkflowResult};
49
+ use std::time::Duration;
50
+
51
+ #[workflow]
52
+ pub struct GreetingWorkflow {
53
+ name: String,
54
+ }
55
+
56
+ #[workflow_methods]
57
+ impl GreetingWorkflow {
58
+ #[init]
59
+ fn new(_ctx: &WorkflowContextView, name: String) -> Self {
60
+ Self { name }
61
+ }
62
+
63
+ #[run]
64
+ async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<String> {
65
+ let name = ctx.state(|s| s.name.clone());
66
+
67
+ // Execute an activity
68
+ let greeting = ctx.start_activity(
69
+ MyActivities::greet,
70
+ name,
71
+ ActivityOptions {
72
+ start_to_close_timeout: Some(Duration::from_secs(10)),
73
+ ..Default::default()
74
+ }
75
+ )?.await?;
76
+
77
+ Ok(greeting)
78
+ }
79
+ }
80
+ ```
81
+
82
+ ### Running a Worker
83
+
84
+ ```rust
85
+ use temporalio_client::{Client, ClientOptions, Connection, ConnectionOptions};
86
+ use temporalio_sdk::{Worker, WorkerOptions};
87
+ use temporalio_sdk_core::{CoreRuntime, RuntimeOptions, Url};
88
+ use std::str::FromStr;
89
+
90
+ #[tokio::main]
91
+ async fn main() -> Result<(), Box<dyn std::error::Error>> {
92
+ let runtime = CoreRuntime::new_assume_tokio(RuntimeOptions::builder().build()?)?;
93
+
94
+ let connection = Connection::connect(
95
+ ConnectionOptions::new(Url::from_str("http://localhost:7233")?).build()
96
+ ).await?;
97
+ let client = Client::new(connection, ClientOptions::new("default").build());
98
+
99
+ let worker_options = WorkerOptions::new("my-task-queue")
100
+ .register_activities(MyActivities { counter: Default::default() })
101
+ .register_workflow::<GreetingWorkflow>()
102
+ .build();
103
+
104
+ Worker::new(&runtime, client, worker_options)?.run().await?;
105
+ Ok(())
106
+ }
107
+ ```
108
+
109
+ ## Workflows in detail
110
+
111
+ Workflows are the core abstraction in Temporal. They are defined as structs with associated methods:
112
+
113
+ - **`#[init]`** (optional) - Constructor that receives initial input
114
+ - **`#[run]`** (required) - Main workflow logic, must be async
115
+ - **`#[signal]`** - Handlers for external signals (sync or async)
116
+ - **`#[query]`** - Read-only handlers for querying workflow state (must be sync)
117
+ - **`#[update]`** - Handlers that can mutate state and return a result (sync or async)
118
+
119
+ `#[run]`, `#[signal]`, `#[query]`, and `#[update]` all accept an optional `name` parameter to specify the name of the method. If not specified, the name of the method will be used.
120
+
121
+ Sync signals and updates are able to mutate state directly. Async methods must mutate state through
122
+ the context with `state()` or `state_mut()`.
123
+
124
+ ```rust
125
+ #[workflow]
126
+ pub struct MyWorkflow {
127
+ values: Vec<u32>,
128
+ }
129
+
130
+ #[workflow_methods]
131
+ impl MyWorkflow {
132
+ #[run]
133
+ async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<Vec<u32>> {
134
+ // Wait until we have at least 3 values
135
+ ctx.wait_condition(|s| s.values.len() >= 3).await;
136
+ Ok(ctx.state(|s| s.values.clone()))
137
+ }
138
+
139
+ #[signal(name = "add_value")]
140
+ fn push_value(&mut self, _ctx: &mut WorkflowContext<Self>, value: u32) {
141
+ self.values.push(value);
142
+ }
143
+
144
+ #[query]
145
+ fn get_values(&self, _ctx: &WorkflowContextView) -> Vec<u32> {
146
+ self.values.clone()
147
+ }
148
+
149
+ #[update]
150
+ async fn add_wait_return(ctx: &mut WorkflowContext<Self>, value: u32) -> Vec<u32> {
151
+ ctx.state_mut(|s| s.values.push(value));
152
+ ctx.timer(Duration::from_secs(1)).await;
153
+ ctx.state(|s| s.values.clone())
154
+ }
155
+ }
156
+ ```
157
+
158
+ ### Workflow Logic Constraints
159
+
160
+ Workflow code must be deterministic. This means:
161
+
162
+ - No direct I/O operations (use activities instead)
163
+ - No threading or random number generation
164
+ - No access to system time (use `ctx.workflow_time()` instead)
165
+ - No global mutable state
166
+ - **Do not use `tokio` or `futures` concurrency primitives directly in workflow code.** Many of them
167
+ (e.g. `tokio::select!`, `tokio::spawn`, `futures::select!`) introduce nondeterministic behavior
168
+ that will break workflow replay. Instead, use the deterministic wrappers provided in
169
+ `temporalio_sdk::workflows`:
170
+ - `select!` — deterministic select (polls in declaration order)
171
+ - `join!` — deterministic join for a fixed number of futures
172
+ - `join_all` — deterministic join for a dynamic collection of futures
173
+
174
+ ### Timers
175
+
176
+ ```rust
177
+ // Wait for a duration
178
+ ctx.timer(Duration::from_secs(60)).await;
179
+ ```
180
+
181
+ ### Child Workflows
182
+
183
+ ```rust
184
+ let child_opts = ChildWorkflowOptions {
185
+ workflow_id: "child-1".to_string(),
186
+ workflow_type: "ChildWorkflow".to_string(),
187
+ ..Default::default()
188
+ };
189
+
190
+ let started = ctx.child_workflow(child_opts).start().await.into_started().unwrap();
191
+ let result = started.join().await?;
192
+ ```
193
+
194
+ ### Continue-As-New
195
+
196
+ ```rust
197
+ // To continue as new, return an error with WorkflowTermination::ContinueAsNew
198
+ Err(WorkflowTermination::continue_as_new(ContinueAsNewWorkflowExecution {
199
+ workflow_type: "MyWorkflow".to_string(),
200
+ arguments: vec![new_input.into()],
201
+ ..Default::default()
202
+ }))
203
+ ```
204
+
205
+ ### Patching (Versioning)
206
+
207
+ Use patching to safely evolve workflow logic:
208
+
209
+ ```rust
210
+ if ctx.patched("my-patch-id") {
211
+ // New code path
212
+ } else {
213
+ // Old code path (for existing workflows)
214
+ }
215
+ ```
216
+
217
+ ### Nexus Operations
218
+
219
+ The SDK supports starting Nexus operations from a workflow:
220
+
221
+ ```rust
222
+ let started = ctx.start_nexus_operation(NexusOperationOptions {
223
+ endpoint: "my-endpoint".to_string(),
224
+ service: "my-service".to_string(),
225
+ operation: "my-operation".to_string(),
226
+ input: Some(payload),
227
+ ..Default::default()
228
+ }).await?;
229
+ ```
230
+
231
+ Defining Nexus handlers will be added later.
232
+
233
+ ## Activities in detail
234
+
235
+ Use Activities to perform side effects like I/O operations, API calls, or any non-deterministic
236
+ work.
237
+
238
+ ### Error Handling
239
+
240
+ Activities return `Result<T, ActivityError>` with the following error types:
241
+
242
+ - **`ActivityError::Retryable`** - Transient failure, will be retried
243
+ - **`ActivityError::NonRetryable`** - Permanent failure, will not be retried
244
+ - **`ActivityError::Cancelled`** - Activity was cancelled
245
+ - **`ActivityError::WillCompleteAsync`** - Activity will complete asynchronously
246
+
247
+ ### Local Activities
248
+
249
+ For short-lived activities that you want to run on the same worker as the workflow:
250
+
251
+ ```rust
252
+ ctx.start_local_activity(
253
+ MyActivities::quick_operation,
254
+ input,
255
+ LocalActivityOptions {
256
+ schedule_to_close_timeout: Some(Duration::from_secs(5)),
257
+ ..Default::default()
258
+ }
259
+ )?.await?;
260
+ ```
261
+
262
+ ## Cancellation
263
+
264
+ Workflows and activities support cancellation. Note that in an activity, you must regularly
265
+ heartbeat with `ctx.record_heartbeat(...)` to receive cancellations.
266
+
267
+ ```rust
268
+ use temporalio_sdk::workflows::select;
269
+
270
+ // In a workflow: wait for cancellation
271
+ let reason = ctx.cancelled().await;
272
+
273
+ // Race a timer against cancellation
274
+ select! {
275
+ _ = ctx.timer(Duration::from_secs(60)) => { /* timer fired */ }
276
+ reason = ctx.cancelled() => { /* workflow cancelled */ }
277
+ }
278
+ ```
279
+
280
+ ## Worker Configuration
281
+
282
+ Workers can be configured with various options:
283
+
284
+ ```rust
285
+ let worker_options = WorkerOptions::new("task-queue")
286
+ .max_cached_workflows(1000) // Workflow cache size
287
+ .workflow_task_poller_behavior(...) // Polling configuration
288
+ .activity_task_poller_behavior(...)
289
+ .graceful_shutdown_period(Duration::from_secs(30))
290
+ .register_activities(my_activities)
291
+ .register_workflow::<MyWorkflow>()
292
+ .build();
293
+ ```
294
+
295
+ ## Using the Client
296
+
297
+ The `temporalio_client` crate provides a client for interacting with the Temporal service. You can
298
+ use it to start workflows and communicate with running workflows via signals, queries, and updates,
299
+ among other operations.
300
+
301
+ ### Connecting and Starting Workflows
302
+
303
+ ```rust
304
+ use temporalio_client::{
305
+ Client, ClientOptions, Connection, ConnectionOptions,
306
+ WorkflowOptions, GetWorkflowResultOptions,
307
+ };
308
+ use temporalio_sdk_core::{Url, CoreRuntime, RuntimeOptions};
309
+ use std::str::FromStr;
310
+
311
+ #[tokio::main]
312
+ async fn main() -> Result<(), Box<dyn std::error::Error>> {
313
+ let connection = Connection::connect(
314
+ ConnectionOptions::new(Url::from_str("http://localhost:7233")?)
315
+ .identity("my-client".to_string())
316
+ .build()
317
+ ).await?;
318
+
319
+ // "default" is your namespace
320
+ let client = Client::new(connection, ClientOptions::new("default").build());
321
+
322
+ // Start a workflow
323
+ let handle = client.start_workflow(
324
+ GreetingWorkflow::run,
325
+ "World".to_string(),
326
+ WorkflowOptions::new("my-task-queue", "greeting-workflow-1").build()
327
+ ).await?;
328
+
329
+ // Wait for the result
330
+ let result = handle.get_result(GetWorkflowResultOptions::default()).await?;
331
+
332
+ Ok(())
333
+ }
334
+ ```
335
+
336
+ ### Signals, Queries, and Updates
337
+
338
+ Once you have a workflow handle, you can interact with the running workflow:
339
+
340
+ ```rust
341
+ use temporalio_client::{
342
+ SignalOptions, QueryOptions, UpdateOptions,
343
+ StartUpdateOptions, WorkflowUpdateWaitStage,
344
+ UntypedSignal,
345
+ };
346
+ use temporalio_common::data_converters::{PayloadConverter, RawValue};
347
+
348
+ // Get a handle to an existing workflow (or use one from start_workflow)
349
+ let handle = client.get_workflow_handle::<MyWorkflow>("workflow-id");
350
+
351
+ // --- Signals (fire-and-forget messages) ---
352
+ handle.signal(MyWorkflow::push_value, 42, SignalOptions::default()).await?;
353
+
354
+ // --- Queries (read workflow state) ---
355
+ let values = handle
356
+ .query(MyWorkflow::get_values, (), QueryOptions::default())
357
+ .await?;
358
+
359
+ // --- Updates (modify state and get a result) ---
360
+ let values = handle
361
+ .execute_update(MyWorkflow::add_wait_return, 100, UpdateOptions::default())
362
+ .await?;
363
+
364
+ // Start an update and wait for acceptance only
365
+ let update_handle = handle
366
+ .start_update(
367
+ MyWorkflow::add_wait_return,
368
+ 50,
369
+ StartUpdateOptions::builder()
370
+ .wait_for_stage(WorkflowUpdateWaitStage::Accepted)
371
+ .build()
372
+ )
373
+ .await?;
374
+ update_handle.get_result().await?;
375
+
376
+ // --- Untyped interactions (when types aren't known at compile time) ---
377
+ let pc = PayloadConverter::serde_json();
378
+ handle
379
+ .signal(
380
+ UntypedSignal::new("increment"),
381
+ RawValue::from_value(&25i32, &pc),
382
+ SignalOptions::default(),
383
+ )
384
+ .await?;
385
+ // UntypedQuery and UntypedUpdate work similarly
386
+ ```
387
+
388
+ ### Cancelling and Terminating Workflows
389
+
390
+ ```rust
391
+ use temporalio_client::{CancelWorkflowOptions, TerminateWorkflowOptions};
392
+
393
+ // Request cancellation (workflow can handle this gracefully)
394
+ handle.cancel(CancelWorkflowOptions::builder().reason("No longer needed").build()).await?;
395
+
396
+ // Terminate immediately (workflow cannot intercept this)
397
+ handle.terminate(TerminateWorkflowOptions::builder().reason("Emergency shutdown").build()).await?;
398
+ ```
399
+
400
+ ### Listing Workflows
401
+
402
+ ```rust
403
+ use temporalio_client::ListWorkflowsOptions;
404
+ use futures_util::StreamExt;
405
+
406
+ let mut stream = client.list_workflows(
407
+ "WorkflowType = 'GreetingWorkflow'",
408
+ ListWorkflowsOptions::builder().limit(10).build()
409
+ );
410
+
411
+ while let Some(result) = stream.next().await {
412
+ let execution = result?;
413
+ println!("Workflow: {} ({})", execution.id(), execution.workflow_type());
414
+ }
415
+ ```