@temporalio/core-bridge 1.11.8 → 1.12.0

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 (205) hide show
  1. package/Cargo.lock +219 -193
  2. package/Cargo.toml +27 -8
  3. package/README.md +5 -0
  4. package/index.js +72 -12
  5. package/lib/errors.d.ts +25 -0
  6. package/lib/errors.js +76 -1
  7. package/lib/errors.js.map +1 -1
  8. package/lib/index.d.ts +11 -478
  9. package/lib/index.js +28 -5
  10. package/lib/index.js.map +1 -1
  11. package/lib/native.d.ts +330 -0
  12. package/lib/{worker-tuner.js → native.js} +1 -1
  13. package/lib/native.js.map +1 -0
  14. package/package.json +7 -3
  15. package/releases/aarch64-apple-darwin/index.node +0 -0
  16. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  17. package/releases/x86_64-apple-darwin/index.node +0 -0
  18. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  19. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  20. package/sdk-core/.cargo/config.toml +8 -2
  21. package/sdk-core/.cargo/multi-worker-manual-test +15 -0
  22. package/sdk-core/.github/workflows/per-pr.yml +40 -11
  23. package/sdk-core/AGENTS.md +73 -0
  24. package/sdk-core/ARCHITECTURE.md +71 -23
  25. package/sdk-core/Cargo.toml +1 -1
  26. package/sdk-core/README.md +4 -4
  27. package/sdk-core/arch_docs/workflow_task_chunking.md +51 -0
  28. package/sdk-core/client/Cargo.toml +1 -1
  29. package/sdk-core/client/src/lib.rs +49 -13
  30. package/sdk-core/client/src/metrics.rs +15 -16
  31. package/sdk-core/client/src/proxy.rs +2 -2
  32. package/sdk-core/client/src/raw.rs +54 -8
  33. package/sdk-core/client/src/retry.rs +109 -13
  34. package/sdk-core/client/src/worker_registry/mod.rs +4 -4
  35. package/sdk-core/client/src/workflow_handle/mod.rs +1 -1
  36. package/sdk-core/core/Cargo.toml +28 -8
  37. package/sdk-core/core/src/abstractions.rs +62 -10
  38. package/sdk-core/core/src/core_tests/activity_tasks.rs +180 -8
  39. package/sdk-core/core/src/core_tests/mod.rs +4 -4
  40. package/sdk-core/core/src/core_tests/queries.rs +18 -4
  41. package/sdk-core/core/src/core_tests/workers.rs +3 -3
  42. package/sdk-core/core/src/core_tests/workflow_tasks.rs +191 -25
  43. package/sdk-core/core/src/ephemeral_server/mod.rs +10 -3
  44. package/sdk-core/core/src/internal_flags.rs +14 -14
  45. package/sdk-core/core/src/lib.rs +5 -2
  46. package/sdk-core/core/src/pollers/mod.rs +1 -1
  47. package/sdk-core/core/src/pollers/poll_buffer.rs +495 -164
  48. package/sdk-core/core/src/protosext/mod.rs +3 -3
  49. package/sdk-core/core/src/replay/mod.rs +3 -3
  50. package/sdk-core/core/src/telemetry/metrics.rs +13 -4
  51. package/sdk-core/core/src/telemetry/mod.rs +72 -70
  52. package/sdk-core/core/src/telemetry/otel.rs +51 -54
  53. package/sdk-core/core/src/test_help/mod.rs +9 -3
  54. package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +31 -11
  55. package/sdk-core/core/src/worker/activities/local_activities.rs +35 -28
  56. package/sdk-core/core/src/worker/activities.rs +58 -30
  57. package/sdk-core/core/src/worker/client/mocks.rs +3 -3
  58. package/sdk-core/core/src/worker/client.rs +155 -53
  59. package/sdk-core/core/src/worker/mod.rs +103 -95
  60. package/sdk-core/core/src/worker/nexus.rs +100 -73
  61. package/sdk-core/core/src/worker/tuner/resource_based.rs +14 -6
  62. package/sdk-core/core/src/worker/tuner.rs +4 -13
  63. package/sdk-core/core/src/worker/workflow/history_update.rs +47 -51
  64. package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +1 -4
  65. package/sdk-core/core/src/worker/workflow/machines/nexus_operation_state_machine.rs +127 -32
  66. package/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +1 -2
  67. package/sdk-core/core/src/worker/workflow/machines/update_state_machine.rs +1 -1
  68. package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +55 -42
  69. package/sdk-core/core/src/worker/workflow/managed_run.rs +45 -35
  70. package/sdk-core/core/src/worker/workflow/mod.rs +200 -97
  71. package/sdk-core/core/src/worker/workflow/wft_poller.rs +175 -4
  72. package/sdk-core/core/src/worker/workflow/workflow_stream.rs +38 -36
  73. package/sdk-core/core-api/Cargo.toml +8 -0
  74. package/sdk-core/core-api/src/envconfig.rs +1544 -0
  75. package/sdk-core/core-api/src/lib.rs +2 -0
  76. package/sdk-core/core-api/src/telemetry/metrics.rs +8 -0
  77. package/sdk-core/core-api/src/telemetry.rs +36 -3
  78. package/sdk-core/core-api/src/worker.rs +301 -75
  79. package/sdk-core/docker/docker-compose-telem.yaml +1 -0
  80. package/sdk-core/etc/prometheus.yaml +6 -2
  81. package/sdk-core/histories/long_local_activity_with_update-0_history.bin +0 -0
  82. package/sdk-core/histories/long_local_activity_with_update-1_history.bin +0 -0
  83. package/sdk-core/histories/long_local_activity_with_update-2_history.bin +0 -0
  84. package/sdk-core/histories/long_local_activity_with_update-3_history.bin +0 -0
  85. package/sdk-core/sdk/src/activity_context.rs +5 -0
  86. package/sdk-core/sdk/src/interceptors.rs +73 -3
  87. package/sdk-core/sdk/src/lib.rs +15 -16
  88. package/sdk-core/sdk/src/workflow_context/options.rs +10 -0
  89. package/sdk-core/sdk/src/workflow_context.rs +48 -29
  90. package/sdk-core/sdk/src/workflow_future.rs +5 -6
  91. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/.github/workflows/push-to-buf.yml +20 -0
  92. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/CODEOWNERS +6 -0
  93. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/README.md +17 -6
  94. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/VERSION +1 -1
  95. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/buf.lock +7 -2
  96. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/buf.yaml +2 -0
  97. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/request_response.proto +78 -0
  98. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/service.proto +29 -0
  99. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/identity/v1/message.proto +74 -32
  100. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/namespace/v1/message.proto +45 -15
  101. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/nexus/v1/message.proto +7 -1
  102. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/operation/v1/message.proto +3 -3
  103. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/region/v1/message.proto +3 -3
  104. package/sdk-core/sdk-core-protos/protos/api_upstream/LICENSE +1 -1
  105. package/sdk-core/sdk-core-protos/protos/api_upstream/buf.yaml +2 -0
  106. package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv2.json +1103 -88
  107. package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv3.yaml +1233 -151
  108. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/activity/v1/message.proto +0 -22
  109. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/batch/v1/message.proto +19 -24
  110. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/command/v1/message.proto +0 -22
  111. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/common/v1/message.proto +12 -22
  112. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/deployment/v1/message.proto +45 -45
  113. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +0 -22
  114. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/command_type.proto +0 -22
  115. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/common.proto +15 -22
  116. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/deployment.proto +0 -22
  117. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/event_type.proto +4 -22
  118. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +0 -22
  119. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/namespace.proto +0 -22
  120. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/nexus.proto +0 -20
  121. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/query.proto +0 -22
  122. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/reset.proto +0 -22
  123. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/schedule.proto +0 -22
  124. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +0 -22
  125. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/update.proto +0 -22
  126. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/workflow.proto +4 -22
  127. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/errordetails/v1/message.proto +0 -22
  128. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/export/v1/message.proto +0 -22
  129. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/failure/v1/message.proto +2 -22
  130. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/filter/v1/message.proto +0 -22
  131. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/history/v1/message.proto +75 -49
  132. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/namespace/v1/message.proto +0 -22
  133. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/nexus/v1/message.proto +0 -20
  134. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +0 -22
  135. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +0 -22
  136. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/protocol/v1/message.proto +0 -22
  137. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/query/v1/message.proto +0 -22
  138. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/replication/v1/message.proto +0 -22
  139. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/rules/v1/message.proto +90 -0
  140. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/schedule/v1/message.proto +0 -22
  141. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/sdk/v1/enhanced_stack_trace.proto +0 -22
  142. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +0 -22
  143. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/sdk/v1/user_metadata.proto +0 -22
  144. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/sdk/v1/workflow_metadata.proto +0 -22
  145. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +17 -38
  146. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/update/v1/message.proto +0 -22
  147. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/version/v1/message.proto +0 -22
  148. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflow/v1/message.proto +151 -44
  149. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +172 -65
  150. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +69 -28
  151. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/activity_task/activity_task.proto +18 -0
  152. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/common/common.proto +5 -0
  153. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/nexus/nexus.proto +16 -1
  154. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +21 -15
  155. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +3 -0
  156. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +3 -0
  157. package/sdk-core/sdk-core-protos/src/lib.rs +60 -16
  158. package/sdk-core/test-utils/src/lib.rs +157 -39
  159. package/sdk-core/tests/cloud_tests.rs +86 -0
  160. package/sdk-core/tests/fuzzy_workflow.rs +23 -26
  161. package/sdk-core/tests/global_metric_tests.rs +116 -0
  162. package/sdk-core/tests/heavy_tests.rs +127 -7
  163. package/sdk-core/tests/integ_tests/client_tests.rs +2 -8
  164. package/sdk-core/tests/integ_tests/metrics_tests.rs +100 -106
  165. package/sdk-core/tests/integ_tests/polling_tests.rs +94 -8
  166. package/sdk-core/tests/integ_tests/update_tests.rs +75 -6
  167. package/sdk-core/tests/integ_tests/worker_tests.rs +54 -5
  168. package/sdk-core/tests/integ_tests/worker_versioning_tests.rs +240 -0
  169. package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +41 -3
  170. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +168 -8
  171. package/sdk-core/tests/integ_tests/workflow_tests/nexus.rs +285 -15
  172. package/sdk-core/tests/integ_tests/workflow_tests/priority.rs +12 -4
  173. package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +3 -2
  174. package/sdk-core/tests/integ_tests/workflow_tests.rs +124 -74
  175. package/sdk-core/tests/main.rs +3 -51
  176. package/sdk-core/tests/manual_tests.rs +430 -0
  177. package/sdk-core/tests/runner.rs +28 -2
  178. package/src/client.rs +565 -0
  179. package/src/helpers/abort_controller.rs +204 -0
  180. package/src/helpers/callbacks.rs +299 -0
  181. package/src/helpers/errors.rs +302 -0
  182. package/src/helpers/future.rs +44 -0
  183. package/src/helpers/handles.rs +191 -0
  184. package/src/helpers/inspect.rs +18 -0
  185. package/src/helpers/json_string.rs +58 -0
  186. package/src/helpers/mod.rs +20 -0
  187. package/src/helpers/properties.rs +71 -0
  188. package/src/helpers/try_from_js.rs +213 -0
  189. package/src/helpers/try_into_js.rs +129 -0
  190. package/src/lib.rs +28 -40
  191. package/src/logs.rs +111 -0
  192. package/src/metrics.rs +325 -0
  193. package/src/runtime.rs +409 -498
  194. package/src/testing.rs +315 -57
  195. package/src/worker.rs +907 -378
  196. package/ts/errors.ts +57 -0
  197. package/ts/index.ts +10 -596
  198. package/ts/native.ts +496 -0
  199. package/lib/worker-tuner.d.ts +0 -167
  200. package/lib/worker-tuner.js.map +0 -1
  201. package/src/conversions/slot_supplier_bridge.rs +0 -291
  202. package/src/conversions.rs +0 -618
  203. package/src/errors.rs +0 -38
  204. package/src/helpers.rs +0 -297
  205. package/ts/worker-tuner.ts +0 -193
@@ -37,15 +37,15 @@ import "temporal/sdk/core/nexus/nexus.proto";
37
37
  // This is because:
38
38
  // * Patches are expected to apply to the entire activation
39
39
  // * Signal and update handlers should be invoked before workflow routines are iterated. That is to
40
- // say before the users' main workflow function and anything spawned by it is allowed to continue.
40
+ // say before the users' main workflow function and anything spawned by it is allowed to continue.
41
41
  // * Local activities resolutions go after other normal jobs because while *not* replaying, they
42
- // will always take longer than anything else that produces an immediate job (which is
43
- // effectively instant). When *replaying* we need to scan ahead for LA markers so that we can
44
- // resolve them in the same activation that they completed in when not replaying. However, doing
45
- // so would, by default, put those resolutions *before* any other immediate jobs that happened
46
- // in that same activation (prime example: cancelling not-wait-for-cancel activities). So, we do
47
- // this to ensure the LA resolution happens after that cancel (or whatever else it may be) as it
48
- // normally would have when executing.
42
+ // will always take longer than anything else that produces an immediate job (which is
43
+ // effectively instant). When *replaying* we need to scan ahead for LA markers so that we can
44
+ // resolve them in the same activation that they completed in when not replaying. However, doing
45
+ // so would, by default, put those resolutions *before* any other immediate jobs that happened
46
+ // in that same activation (prime example: cancelling not-wait-for-cancel activities). So, we do
47
+ // this to ensure the LA resolution happens after that cancel (or whatever else it may be) as it
48
+ // normally would have when executing.
49
49
  // * Queries always go last (and, in fact, always come in their own activation)
50
50
  // * Evictions also always come in their own activation
51
51
  //
@@ -84,10 +84,14 @@ message WorkflowActivation {
84
84
  uint64 history_size_bytes = 7;
85
85
  // Set true if the most recent WFT started event had this suggestion
86
86
  bool continue_as_new_suggested = 8;
87
- // Set to the Build ID of the worker that processed this task, which may be empty. During replay
88
- // this id may not equal the id of the replaying worker. If not replaying and this worker has
89
- // a defined Build ID, it will equal that ID. It will also be empty for evict-only activations.
90
- string build_id_for_current_task = 9;
87
+ // Set to the deployment version of the worker that processed this task,
88
+ // which may be empty. During replay this version may not equal the version
89
+ // of the replaying worker. If not replaying and this worker has a defined
90
+ // Deployment Version, it will equal that. It will also be empty for
91
+ // evict-only activations. The deployment name may be empty, but not the
92
+ // build id, if this worker was using the deprecated Build ID-only
93
+ // feature(s).
94
+ common.WorkerDeploymentVersion deployment_version_for_current_task = 9;
91
95
  }
92
96
 
93
97
  message WorkflowActivationJob {
@@ -195,6 +199,8 @@ message InitializeWorkflow {
195
199
  //
196
200
  // See field in WorkflowExecutionStarted for more detail.
197
201
  temporal.api.common.v1.WorkflowExecution root_workflow = 24;
202
+ // Priority of this workflow execution
203
+ temporal.api.common.v1.Priority priority = 25;
198
204
  }
199
205
 
200
206
  // Notify a workflow that a timer has fired
@@ -337,10 +343,10 @@ message ResolveNexusOperationStart {
337
343
  // Sequence number as provided by lang in the corresponding ScheduleNexusOperation command
338
344
  uint32 seq = 1;
339
345
  oneof status {
340
- // The operation started asynchronously. Contains an ID that can be used to perform
346
+ // The operation started asynchronously. Contains a token that can be used to perform
341
347
  // operations on the started operation by, ex, clients. A `ResolveNexusOperation` job will
342
348
  // follow at some point.
343
- string operation_id = 2;
349
+ string operation_token = 2;
344
350
  // If true the operation "started" but only because it's also already resolved. A
345
351
  // `ResolveNexusOperation` job will be in the same activation.
346
352
  bool started_sync = 3;
@@ -389,4 +395,4 @@ message RemoveFromCache {
389
395
  WORKFLOW_EXECUTION_ENDING = 10;
390
396
  }
391
397
  EvictionReason reason = 2;
392
- }
398
+ }
@@ -16,6 +16,7 @@ import "temporal/api/enums/v1/workflow.proto";
16
16
  import "temporal/api/failure/v1/message.proto";
17
17
  import "temporal/api/sdk/v1/user_metadata.proto";
18
18
  import "temporal/sdk/core/child_workflow/child_workflow.proto";
19
+ import "temporal/sdk/core/nexus/nexus.proto";
19
20
  import "temporal/sdk/core/common/common.proto";
20
21
 
21
22
  message WorkflowCommand {
@@ -375,6 +376,8 @@ message ScheduleNexusOperation {
375
376
  // activities and child workflows, these are transmitted to Nexus operations that may be
376
377
  // external and are not traditional payloads.
377
378
  map<string, string> nexus_header = 7;
379
+ // Defines behaviour of the underlying nexus operation when operation cancellation has been requested.
380
+ nexus.NexusOperationCancellationType cancellation_type = 8;
378
381
  }
379
382
 
380
383
  // Request cancellation of a nexus operation started via `ScheduleNexusOperation`
@@ -5,6 +5,7 @@ option ruby_package = "Temporalio::Internal::Bridge::Api::WorkflowCompletion";
5
5
 
6
6
  import "temporal/api/failure/v1/message.proto";
7
7
  import "temporal/api/enums/v1/failed_cause.proto";
8
+ import "temporal/api/enums/v1/workflow.proto";
8
9
  import "temporal/sdk/core/common/common.proto";
9
10
  import "temporal/sdk/core/workflow_commands/workflow_commands.proto";
10
11
 
@@ -24,6 +25,8 @@ message Success {
24
25
  repeated workflow_commands.WorkflowCommand commands = 1;
25
26
  // Any internal flags which the lang SDK used in the processing of this activation
26
27
  repeated uint32 used_internal_flags = 6;
28
+ // The versioning behavior this workflow is currently using
29
+ temporal.api.enums.v1.VersioningBehavior versioning_behavior = 7;
27
30
  }
28
31
 
29
32
  // Failure to activate or execute a workflow
@@ -40,7 +40,9 @@ pub mod coresdk {
40
40
  ENCODING_PAYLOAD_KEY, JSON_ENCODING_VAL,
41
41
  temporal::api::{
42
42
  common::v1::{Payload, Payloads, WorkflowExecution},
43
- enums::v1::{TimeoutType, WorkflowTaskFailedCause},
43
+ enums::v1::{
44
+ ApplicationErrorCategory, TimeoutType, VersioningBehavior, WorkflowTaskFailedCause,
45
+ },
44
46
  failure::v1::{
45
47
  ActivityFailureInfo, ApplicationFailureInfo, Failure, TimeoutFailureInfo,
46
48
  failure::FailureInfo,
@@ -67,23 +69,43 @@ pub mod coresdk {
67
69
  tonic::include_proto!("coresdk.activity_task");
68
70
 
69
71
  impl ActivityTask {
70
- pub fn cancel_from_ids(task_token: Vec<u8>, reason: ActivityCancelReason) -> Self {
72
+ pub fn cancel_from_ids(
73
+ task_token: Vec<u8>,
74
+ reason: ActivityCancelReason,
75
+ details: ActivityCancellationDetails,
76
+ ) -> Self {
71
77
  Self {
72
78
  task_token,
73
79
  variant: Some(activity_task::Variant::Cancel(Cancel {
74
80
  reason: reason as i32,
81
+ details: Some(details),
75
82
  })),
76
83
  }
77
84
  }
78
85
 
86
+ // Checks if both the primary reason or details have a timeout cancellation.
79
87
  pub fn is_timeout(&self) -> bool {
80
88
  match &self.variant {
81
- Some(activity_task::Variant::Cancel(Cancel { reason })) => {
89
+ Some(activity_task::Variant::Cancel(Cancel { reason, details })) => {
82
90
  *reason == ActivityCancelReason::TimedOut as i32
91
+ || details.as_ref().is_some_and(|d| d.is_timed_out)
83
92
  }
84
93
  _ => false,
85
94
  }
86
95
  }
96
+
97
+ pub fn primary_reason_to_cancellation_details(
98
+ reason: ActivityCancelReason,
99
+ ) -> ActivityCancellationDetails {
100
+ ActivityCancellationDetails {
101
+ is_not_found: reason == ActivityCancelReason::NotFound,
102
+ is_cancelled: reason == ActivityCancelReason::Cancelled,
103
+ is_paused: reason == ActivityCancelReason::Paused,
104
+ is_timed_out: reason == ActivityCancelReason::TimedOut,
105
+ is_worker_shutdown: reason == ActivityCancelReason::WorkerShutdown,
106
+ is_reset: reason == ActivityCancelReason::Reset,
107
+ }
108
+ }
87
109
  }
88
110
 
89
111
  impl Display for ActivityTaskCompletion {
@@ -489,7 +511,7 @@ pub mod coresdk {
489
511
  available_internal_flags: vec![],
490
512
  history_size_bytes: 0,
491
513
  continue_as_new_suggested: false,
492
- build_id_for_current_task: "".to_string(),
514
+ deployment_version_for_current_task: None,
493
515
  }
494
516
  }
495
517
 
@@ -626,8 +648,8 @@ pub mod coresdk {
626
648
  workflow_activation_job::Variant::ResolveRequestCancelExternalWorkflow(_) => {
627
649
  write!(f, "ResolveRequestCancelExternalWorkflow")
628
650
  }
629
- workflow_activation_job::Variant::DoUpdate(_) => {
630
- write!(f, "DoUpdate")
651
+ workflow_activation_job::Variant::DoUpdate(u) => {
652
+ write!(f, "DoUpdate({})", u.id)
631
653
  }
632
654
  workflow_activation_job::Variant::ResolveNexusOperationStart(_) => {
633
655
  write!(f, "ResolveNexusOperationStart")
@@ -726,6 +748,7 @@ pub mod coresdk {
726
748
  search_attributes: attrs.search_attributes,
727
749
  start_time: Some(start_time),
728
750
  root_workflow: attrs.root_workflow_execution,
751
+ priority: attrs.priority,
729
752
  }
730
753
  }
731
754
  }
@@ -1016,6 +1039,7 @@ pub mod coresdk {
1016
1039
  Self {
1017
1040
  commands: v,
1018
1041
  used_internal_flags: vec![],
1042
+ versioning_behavior: VersioningBehavior::Unspecified.into(),
1019
1043
  }
1020
1044
  }
1021
1045
  }
@@ -1141,18 +1165,22 @@ pub mod coresdk {
1141
1165
 
1142
1166
  /// Returns true if the activation contains a complete workflow execution command
1143
1167
  pub fn has_complete_workflow_execution(&self) -> bool {
1168
+ self.complete_workflow_execution_value().is_some()
1169
+ }
1170
+
1171
+ /// Returns the completed execution result value, if any
1172
+ pub fn complete_workflow_execution_value(&self) -> Option<&Payload> {
1144
1173
  if let Some(workflow_activation_completion::Status::Successful(s)) = &self.status {
1145
- return s.commands.iter().any(|wfc| {
1146
- matches!(
1147
- wfc,
1148
- WorkflowCommand {
1149
- variant: Some(workflow_command::Variant::CompleteWorkflowExecution(_)),
1150
- ..
1151
- },
1152
- )
1153
- });
1174
+ s.commands.iter().find_map(|wfc| match wfc {
1175
+ WorkflowCommand {
1176
+ variant: Some(workflow_command::Variant::CompleteWorkflowExecution(v)),
1177
+ ..
1178
+ } => v.result.as_ref(),
1179
+ _ => None,
1180
+ })
1181
+ } else {
1182
+ None
1154
1183
  }
1155
- false
1156
1184
  }
1157
1185
 
1158
1186
  /// Returns true if the activation completion is a success with no commands
@@ -1265,6 +1293,7 @@ pub mod coresdk {
1265
1293
  start_to_close_timeout: r.start_to_close_timeout,
1266
1294
  heartbeat_timeout: r.heartbeat_timeout,
1267
1295
  retry_policy: r.retry_policy,
1296
+ priority: r.priority,
1268
1297
  is_local: false,
1269
1298
  },
1270
1299
  )),
@@ -1343,6 +1372,12 @@ pub mod coresdk {
1343
1372
  None
1344
1373
  }
1345
1374
  }
1375
+
1376
+ // Checks if a failure is an ApplicationFailure with Benign category.
1377
+ pub fn is_benign_application_failure(&self) -> bool {
1378
+ self.maybe_application_failure()
1379
+ .is_some_and(|app_info| app_info.category() == ApplicationErrorCategory::Benign)
1380
+ }
1346
1381
  }
1347
1382
 
1348
1383
  impl Display for Failure {
@@ -2188,6 +2223,8 @@ pub mod temporal {
2188
2223
  Attributes::NexusOperationTimedOutEventAttributes(a) => Some(a.scheduled_event_id),
2189
2224
  Attributes::NexusOperationCanceledEventAttributes(a) => Some(a.scheduled_event_id),
2190
2225
  Attributes::NexusOperationCancelRequestedEventAttributes(a) => Some(a.scheduled_event_id),
2226
+ Attributes::NexusOperationCancelRequestCompletedEventAttributes(a) => Some(a.scheduled_event_id),
2227
+ Attributes::NexusOperationCancelRequestFailedEventAttributes(a) => Some(a.scheduled_event_id),
2191
2228
  _ => None
2192
2229
  }
2193
2230
  })
@@ -2296,6 +2333,8 @@ pub mod temporal {
2296
2333
  Attributes::NexusOperationTimedOutEventAttributes(_) => { EventType::NexusOperationTimedOut }
2297
2334
  Attributes::NexusOperationCancelRequestedEventAttributes(_) => { EventType::NexusOperationCancelRequested }
2298
2335
  Attributes::WorkflowExecutionOptionsUpdatedEventAttributes(_) => { EventType::WorkflowExecutionOptionsUpdated }
2336
+ Attributes::NexusOperationCancelRequestCompletedEventAttributes(_) => { EventType::NexusOperationCancelRequestCompleted }
2337
+ Attributes::NexusOperationCancelRequestFailedEventAttributes(_) => { EventType::NexusOperationCancelRequestFailed }
2299
2338
  }
2300
2339
  }
2301
2340
  }
@@ -2333,6 +2372,11 @@ pub mod temporal {
2333
2372
  tonic::include_proto!("temporal.api.replication.v1");
2334
2373
  }
2335
2374
  }
2375
+ pub mod rules {
2376
+ pub mod v1 {
2377
+ tonic::include_proto!("temporal.api.rules.v1");
2378
+ }
2379
+ }
2336
2380
  pub mod schedule {
2337
2381
  #[allow(rustdoc::invalid_html_tags)]
2338
2382
  pub mod v1 {
@@ -11,23 +11,32 @@ pub mod workflows;
11
11
  pub use temporal_sdk_core::replay::HistoryForReplay;
12
12
 
13
13
  use crate::stream::{Stream, TryStreamExt};
14
- use anyhow::Context;
14
+ use anyhow::{Context, Error, bail};
15
15
  use assert_matches::assert_matches;
16
16
  use futures_util::{StreamExt, future, stream, stream::FuturesUnordered};
17
17
  use parking_lot::Mutex;
18
18
  use prost::Message;
19
19
  use rand::Rng;
20
20
  use std::{
21
- convert::TryFrom, env, future::Future, net::SocketAddr, path::PathBuf, sync::Arc,
22
- time::Duration,
21
+ convert::TryFrom,
22
+ env,
23
+ future::Future,
24
+ net::SocketAddr,
25
+ path::PathBuf,
26
+ sync::Arc,
27
+ time::{Duration, Instant},
23
28
  };
24
29
  use temporal_client::{
25
- Client, ClientTlsConfig, NamespacedClient, RetryClient, TlsConfig, WfClientExt,
26
- WorkflowClientTrait, WorkflowExecutionInfo, WorkflowHandle, WorkflowOptions,
30
+ Client, ClientTlsConfig, GetWorkflowResultOpts, NamespacedClient, RetryClient, TlsConfig,
31
+ WfClientExt, WorkflowClientTrait, WorkflowExecutionInfo, WorkflowExecutionResult,
32
+ WorkflowHandle, WorkflowOptions,
27
33
  };
28
34
  use temporal_sdk::{
29
35
  IntoActivityFunc, Worker, WorkflowFunction,
30
- interceptors::{FailOnNondeterminismInterceptor, WorkerInterceptor},
36
+ interceptors::{
37
+ FailOnNondeterminismInterceptor, InterceptorWithNext, ReturnWorkflowExitValueInterceptor,
38
+ WorkerInterceptor,
39
+ },
31
40
  };
32
41
  #[cfg(feature = "ephemeral-server")]
33
42
  use temporal_sdk_core::ephemeral_server::{EphemeralExe, EphemeralExeVersion};
@@ -41,9 +50,11 @@ use temporal_sdk_core_api::{
41
50
  Worker as CoreWorker,
42
51
  errors::PollError,
43
52
  telemetry::{
44
- Logger, OtelCollectorOptionsBuilder, PrometheusExporterOptionsBuilder, TelemetryOptions,
45
- TelemetryOptionsBuilder, metrics::CoreMeter,
53
+ Logger, OtelCollectorOptionsBuilder, PrometheusExporterOptions,
54
+ PrometheusExporterOptionsBuilder, TelemetryOptions, TelemetryOptionsBuilder,
55
+ metrics::CoreMeter,
46
56
  },
57
+ worker::WorkerVersioningStrategy,
47
58
  };
48
59
  use temporal_sdk_core_protos::{
49
60
  DEFAULT_ACTIVITY_TYPE,
@@ -61,7 +72,7 @@ use temporal_sdk_core_protos::{
61
72
  workflowservice::v1::StartWorkflowExecutionResponse,
62
73
  },
63
74
  };
64
- use tokio::sync::OnceCell;
75
+ use tokio::{sync::OnceCell, task::AbortHandle};
65
76
  use url::Url;
66
77
 
67
78
  pub const NAMESPACE: &str = "default";
@@ -70,6 +81,7 @@ pub const TEST_Q: &str = "q";
70
81
  pub const INTEG_SERVER_TARGET_ENV_VAR: &str = "TEMPORAL_SERVICE_ADDRESS";
71
82
  pub const INTEG_NAMESPACE_ENV_VAR: &str = "TEMPORAL_NAMESPACE";
72
83
  pub const INTEG_USE_TLS_ENV_VAR: &str = "TEMPORAL_USE_TLS";
84
+ pub const INTEG_API_KEY: &str = "TEMPORAL_API_KEY_PATH";
73
85
  /// This env var is set (to any value) if temporal CLI dev server is in use
74
86
  pub const INTEG_TEMPORAL_DEV_SERVER_USED_ENV_VAR: &str = "INTEG_TEMPORAL_DEV_SERVER_ON";
75
87
  /// This env var is set (to any value) if the test server is in use
@@ -107,7 +119,9 @@ pub fn integ_worker_config(tq: &str) -> WorkerConfigBuilder {
107
119
  .max_outstanding_activities(100_usize)
108
120
  .max_outstanding_local_activities(100_usize)
109
121
  .max_outstanding_workflow_tasks(100_usize)
110
- .worker_build_id("test_build_id");
122
+ .versioning_strategy(WorkerVersioningStrategy::None {
123
+ build_id: "test_build_id".to_owned(),
124
+ });
111
125
  b
112
126
  }
113
127
 
@@ -179,6 +193,7 @@ pub struct CoreWfStarter {
179
193
  pub workflow_options: WorkflowOptions,
180
194
  initted_worker: OnceCell<InitializedWorker>,
181
195
  runtime_override: Option<Arc<CoreRuntime>>,
196
+ client_override: Option<Arc<RetryClient<Client>>>,
182
197
  }
183
198
  struct InitializedWorker {
184
199
  worker: Arc<dyn CoreWorker>,
@@ -188,14 +203,23 @@ struct InitializedWorker {
188
203
  impl CoreWfStarter {
189
204
  pub fn new(test_name: &str) -> Self {
190
205
  init_integ_telem();
191
- Self::_new(test_name, None)
206
+ Self::_new(test_name, None, None)
192
207
  }
193
208
 
194
209
  pub fn new_with_runtime(test_name: &str, runtime: CoreRuntime) -> Self {
195
- Self::_new(test_name, Some(runtime))
210
+ Self::_new(test_name, Some(runtime), None)
211
+ }
212
+
213
+ pub fn new_with_client(test_name: &str, client: RetryClient<Client>) -> Self {
214
+ init_integ_telem();
215
+ Self::_new(test_name, None, Some(client))
196
216
  }
197
217
 
198
- fn _new(test_name: &str, runtime_override: Option<CoreRuntime>) -> Self {
218
+ fn _new(
219
+ test_name: &str,
220
+ runtime_override: Option<CoreRuntime>,
221
+ client_override: Option<RetryClient<Client>>,
222
+ ) -> Self {
199
223
  let task_q_salt = rand_6_chars();
200
224
  let task_queue = format!("{test_name}_{task_q_salt}");
201
225
  let mut worker_config = integ_worker_config(&task_queue);
@@ -208,6 +232,7 @@ impl CoreWfStarter {
208
232
  initted_worker: OnceCell::new(),
209
233
  workflow_options: Default::default(),
210
234
  runtime_override: runtime_override.map(Arc::new),
235
+ client_override: client_override.map(Arc::new),
211
236
  }
212
237
  }
213
238
 
@@ -219,6 +244,7 @@ impl CoreWfStarter {
219
244
  worker_config: self.worker_config.clone(),
220
245
  workflow_options: self.workflow_options.clone(),
221
246
  runtime_override: self.runtime_override.clone(),
247
+ client_override: self.client_override.clone(),
222
248
  initted_worker: Default::default(),
223
249
  }
224
250
  }
@@ -246,7 +272,7 @@ impl CoreWfStarter {
246
272
 
247
273
  /// Start the workflow defined by the builder and return run id
248
274
  pub async fn start_wf(&mut self) -> String {
249
- self.start_wf_with_id(self.task_queue_name.clone()).await
275
+ self.start_wf_with_id(self.get_wf_id().to_owned()).await
250
276
  }
251
277
 
252
278
  /// Starts the workflow using the worker
@@ -315,6 +341,32 @@ impl CoreWfStarter {
315
341
  &self.task_queue_name
316
342
  }
317
343
 
344
+ /// Fetch the history of the default workflow for this starter. IE: The one that would
345
+ /// be started by [CoreWfStarter::start_wf].
346
+ pub async fn get_history(&self) -> History {
347
+ self.initted_worker
348
+ .get()
349
+ .expect("Starter must be initialized")
350
+ .client
351
+ .get_workflow_execution_history(self.get_wf_id().to_string(), None, vec![])
352
+ .await
353
+ .unwrap()
354
+ .history
355
+ .unwrap()
356
+ }
357
+
358
+ pub async fn wait_for_default_wf_finish(
359
+ &self,
360
+ ) -> Result<WorkflowExecutionResult<Vec<Payload>>, Error> {
361
+ self.initted_worker
362
+ .get()
363
+ .unwrap()
364
+ .client
365
+ .get_untyped_workflow_handle(self.get_wf_id().to_string(), "")
366
+ .get_workflow_result(GetWorkflowResultOpts { follow_runs: false })
367
+ .await
368
+ }
369
+
318
370
  async fn get_or_init(&mut self) -> &InitializedWorker {
319
371
  self.initted_worker
320
372
  .get_or_init(|| async {
@@ -327,15 +379,19 @@ impl CoreWfStarter {
327
379
  .worker_config
328
380
  .build()
329
381
  .expect("Worker config must be valid");
330
- let client = Arc::new(
331
- get_integ_server_options()
332
- .connect(
333
- cfg.namespace.clone(),
334
- rt.telemetry().get_temporal_metric_meter(),
335
- )
336
- .await
337
- .expect("Must connect"),
338
- );
382
+ let client = if let Some(client) = self.client_override.take() {
383
+ client
384
+ } else {
385
+ Arc::new(
386
+ get_integ_server_options()
387
+ .connect(
388
+ cfg.namespace.clone(),
389
+ rt.telemetry().get_temporal_metric_meter(),
390
+ )
391
+ .await
392
+ .expect("Must connect"),
393
+ )
394
+ };
339
395
  let worker = init_worker(rt, cfg, client.clone()).expect("Worker inits cleanly");
340
396
  InitializedWorker {
341
397
  worker: Arc::new(worker),
@@ -483,13 +539,13 @@ impl TestWorker {
483
539
  Arc::new(self.inner.shutdown_handle()),
484
540
  );
485
541
  // Automatically use results-based complete detection if we have a client
486
- if self.fetch_results {
487
- if let Some(c) = self.client.clone() {
488
- iceptor.condition = TestWorkerShutdownCond::GetResults(
489
- std::mem::take(&mut self.started_workflows.lock()),
490
- c,
491
- );
492
- }
542
+ if self.fetch_results
543
+ && let Some(c) = self.client.clone()
544
+ {
545
+ iceptor.condition = TestWorkerShutdownCond::GetResults(
546
+ std::mem::take(&mut self.started_workflows.lock()),
547
+ c,
548
+ );
493
549
  }
494
550
  iceptor.next = next_interceptor.map(|i| Box::new(i) as Box<dyn WorkerInterceptor>);
495
551
  let get_results_waiter = iceptor.wait_all_wfs();
@@ -611,16 +667,18 @@ impl WorkerInterceptor for TestWorkerCompletionIceptor {
611
667
 
612
668
  /// Returns the client options used to connect to the server used for integration tests.
613
669
  pub fn get_integ_server_options() -> ClientOptions {
614
- let temporal_server_address = match env::var(INTEG_SERVER_TARGET_ENV_VAR) {
615
- Ok(addr) => addr,
616
- Err(_) => "http://localhost:7233".to_owned(),
617
- };
670
+ let temporal_server_address = env::var(INTEG_SERVER_TARGET_ENV_VAR)
671
+ .unwrap_or_else(|_| "http://localhost:7233".to_owned());
618
672
  let url = Url::try_from(&*temporal_server_address).unwrap();
619
673
  let mut cb = ClientOptionsBuilder::default();
620
674
  cb.identity("integ_tester".to_string())
621
675
  .target_url(url)
622
676
  .client_name("temporal-core".to_string())
623
677
  .client_version("0.1.0".to_string());
678
+ if let Ok(key_file) = env::var(INTEG_API_KEY) {
679
+ let content = std::fs::read_to_string(key_file).unwrap();
680
+ cb.api_key(Some(content));
681
+ }
624
682
  if let Some(tls) = get_integ_tls_config() {
625
683
  cb.tls_cfg(tls);
626
684
  };
@@ -827,7 +885,10 @@ where
827
885
 
828
886
  #[async_trait::async_trait(?Send)]
829
887
  pub trait WorkflowHandleExt {
830
- async fn fetch_history_and_replay(&self, worker: &mut Worker) -> Result<(), anyhow::Error>;
888
+ async fn fetch_history_and_replay(
889
+ &self,
890
+ worker: &mut Worker,
891
+ ) -> Result<Option<Payload>, anyhow::Error>;
831
892
  }
832
893
 
833
894
  #[async_trait::async_trait(?Send)]
@@ -835,7 +896,10 @@ impl<R> WorkflowHandleExt for WorkflowHandle<RetryClient<Client>, R>
835
896
  where
836
897
  R: FromPayloadsExt,
837
898
  {
838
- async fn fetch_history_and_replay(&self, worker: &mut Worker) -> Result<(), anyhow::Error> {
899
+ async fn fetch_history_and_replay(
900
+ &self,
901
+ worker: &mut Worker,
902
+ ) -> Result<Option<Payload>, anyhow::Error> {
839
903
  let wf_id = self.info().workflow_id.clone();
840
904
  let run_id = self.info().run_id.clone();
841
905
  let history = self
@@ -847,9 +911,13 @@ where
847
911
  let with_id = HistoryForReplay::new(history, wf_id);
848
912
  let replay_worker = init_core_replay_preloaded(worker.task_queue(), [with_id]);
849
913
  worker.with_new_core_worker(replay_worker);
850
- worker.set_worker_interceptor(FailOnNondeterminismInterceptor {});
851
- worker.run().await.unwrap();
852
- Ok(())
914
+ let retval_icept = ReturnWorkflowExitValueInterceptor::default();
915
+ let retval_handle = retval_icept.get_result_handle();
916
+ let mut top_icept = InterceptorWithNext::new(Box::new(FailOnNondeterminismInterceptor {}));
917
+ top_icept.set_next(Box::new(retval_icept));
918
+ worker.set_worker_interceptor(top_icept);
919
+ worker.run().await?;
920
+ Ok(retval_handle.get().cloned())
853
921
  }
854
922
  }
855
923
 
@@ -880,3 +948,53 @@ pub fn rand_6_chars() -> String {
880
948
  .map(char::from)
881
949
  .collect()
882
950
  }
951
+
952
+ pub static ANY_PORT: &str = "127.0.0.1:0";
953
+
954
+ pub fn prom_metrics(
955
+ options_override: Option<PrometheusExporterOptions>,
956
+ ) -> (TelemetryOptions, SocketAddr, AbortOnDrop) {
957
+ let prom_exp_opts = options_override.unwrap_or_else(|| {
958
+ PrometheusExporterOptionsBuilder::default()
959
+ .socket_addr(ANY_PORT.parse().unwrap())
960
+ .build()
961
+ .unwrap()
962
+ });
963
+ let mut telemopts = get_integ_telem_options();
964
+ let prom_info = start_prometheus_metric_exporter(prom_exp_opts).unwrap();
965
+ telemopts.metrics = Some(prom_info.meter as Arc<dyn CoreMeter>);
966
+ (
967
+ telemopts,
968
+ prom_info.bound_addr,
969
+ AbortOnDrop {
970
+ ah: prom_info.abort_handle,
971
+ },
972
+ )
973
+ }
974
+
975
+ pub struct AbortOnDrop {
976
+ ah: AbortHandle,
977
+ }
978
+
979
+ impl Drop for AbortOnDrop {
980
+ fn drop(&mut self) {
981
+ self.ah.abort();
982
+ }
983
+ }
984
+
985
+ pub async fn eventually<F, Fut, T, E>(func: F, timeout: Duration) -> Result<T, anyhow::Error>
986
+ where
987
+ F: Fn() -> Fut,
988
+ Fut: Future<Output = Result<T, E>>,
989
+ {
990
+ let start = Instant::now();
991
+ loop {
992
+ if start.elapsed() > timeout {
993
+ bail!("Eventually hit timeout");
994
+ }
995
+ if let Ok(v) = func().await {
996
+ return Ok(v);
997
+ }
998
+ tokio::time::sleep(Duration::from_millis(50)).await;
999
+ }
1000
+ }