@temporalio/core-bridge 1.8.6 → 1.9.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 (213) hide show
  1. package/Cargo.lock +670 -594
  2. package/Cargo.toml +2 -1
  3. package/lib/errors.js +6 -6
  4. package/lib/errors.js.map +1 -1
  5. package/lib/index.d.ts +17 -44
  6. package/lib/index.js.map +1 -1
  7. package/package.json +5 -6
  8. package/releases/aarch64-apple-darwin/index.node +0 -0
  9. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  10. package/releases/x86_64-apple-darwin/index.node +0 -0
  11. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  12. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  13. package/sdk-core/.github/workflows/heavy.yml +4 -0
  14. package/sdk-core/.github/workflows/per-pr.yml +96 -0
  15. package/sdk-core/ARCHITECTURE.md +1 -1
  16. package/sdk-core/Cargo.toml +10 -0
  17. package/sdk-core/LICENSE.txt +0 -2
  18. package/sdk-core/README.md +37 -21
  19. package/sdk-core/client/Cargo.toml +7 -4
  20. package/sdk-core/client/src/lib.rs +274 -142
  21. package/sdk-core/client/src/metrics.rs +68 -57
  22. package/sdk-core/client/src/raw.rs +191 -45
  23. package/sdk-core/client/src/retry.rs +20 -0
  24. package/sdk-core/client/src/worker_registry/mod.rs +264 -0
  25. package/sdk-core/client/src/workflow_handle/mod.rs +2 -1
  26. package/sdk-core/core/Cargo.toml +17 -19
  27. package/sdk-core/core/src/core_tests/activity_tasks.rs +4 -2
  28. package/sdk-core/core/src/core_tests/child_workflows.rs +7 -7
  29. package/sdk-core/core/src/core_tests/mod.rs +1 -0
  30. package/sdk-core/core/src/core_tests/queries.rs +42 -1
  31. package/sdk-core/core/src/core_tests/replay_flag.rs +29 -39
  32. package/sdk-core/core/src/core_tests/updates.rs +73 -0
  33. package/sdk-core/core/src/core_tests/workflow_tasks.rs +52 -1
  34. package/sdk-core/core/src/ephemeral_server/mod.rs +34 -11
  35. package/sdk-core/core/src/internal_flags.rs +7 -1
  36. package/sdk-core/core/src/lib.rs +19 -36
  37. package/sdk-core/core/src/protosext/mod.rs +12 -4
  38. package/sdk-core/core/src/protosext/protocol_messages.rs +102 -0
  39. package/sdk-core/core/src/replay/mod.rs +99 -48
  40. package/sdk-core/core/src/telemetry/log_export.rs +161 -28
  41. package/sdk-core/core/src/telemetry/metrics.rs +869 -248
  42. package/sdk-core/core/src/telemetry/mod.rs +153 -257
  43. package/sdk-core/core/src/telemetry/prometheus_server.rs +36 -31
  44. package/sdk-core/core/src/test_help/mod.rs +64 -5
  45. package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +12 -2
  46. package/sdk-core/core/src/worker/activities.rs +276 -10
  47. package/sdk-core/core/src/worker/client/mocks.rs +18 -0
  48. package/sdk-core/core/src/worker/client.rs +16 -3
  49. package/sdk-core/core/src/worker/mod.rs +45 -28
  50. package/sdk-core/core/src/worker/slot_provider.rs +175 -0
  51. package/sdk-core/core/src/worker/workflow/driven_workflow.rs +27 -34
  52. package/sdk-core/core/src/worker/workflow/history_update.rs +5 -2
  53. package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +71 -95
  54. package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +34 -22
  55. package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +50 -34
  56. package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +106 -92
  57. package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +22 -21
  58. package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +386 -499
  59. package/sdk-core/core/src/worker/workflow/machines/mod.rs +12 -2
  60. package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +33 -26
  61. package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +198 -215
  62. package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +67 -63
  63. package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +88 -119
  64. package/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +3 -1
  65. package/sdk-core/core/src/worker/workflow/machines/update_state_machine.rs +411 -0
  66. package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +27 -26
  67. package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +319 -94
  68. package/sdk-core/core/src/worker/workflow/managed_run.rs +179 -132
  69. package/sdk-core/core/src/worker/workflow/mod.rs +129 -58
  70. package/sdk-core/core/src/worker/workflow/run_cache.rs +16 -26
  71. package/sdk-core/core/src/worker/workflow/workflow_stream/saved_wf_inputs.rs +2 -2
  72. package/sdk-core/core/src/worker/workflow/workflow_stream.rs +48 -43
  73. package/sdk-core/core-api/Cargo.toml +8 -7
  74. package/sdk-core/core-api/src/lib.rs +4 -12
  75. package/sdk-core/core-api/src/telemetry/metrics.rs +334 -0
  76. package/sdk-core/core-api/src/telemetry.rs +53 -42
  77. package/sdk-core/core-api/src/worker.rs +7 -0
  78. package/sdk-core/{.buildkite/docker → docker}/docker-compose.yaml +1 -1
  79. package/sdk-core/etc/dynamic-config.yaml +11 -1
  80. package/sdk-core/fsm/LICENSE.txt +0 -2
  81. package/sdk-core/fsm/rustfsm_procmacro/Cargo.toml +1 -1
  82. package/sdk-core/fsm/rustfsm_procmacro/LICENSE.txt +0 -2
  83. package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +1 -3
  84. package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +2 -2
  85. package/sdk-core/fsm/rustfsm_trait/LICENSE.txt +0 -2
  86. package/sdk-core/sdk/Cargo.toml +2 -2
  87. package/sdk-core/sdk/src/lib.rs +85 -7
  88. package/sdk-core/sdk/src/workflow_context/options.rs +4 -0
  89. package/sdk-core/sdk/src/workflow_context.rs +43 -15
  90. package/sdk-core/sdk/src/workflow_future.rs +334 -204
  91. package/sdk-core/sdk-core-protos/Cargo.toml +3 -3
  92. package/sdk-core/sdk-core-protos/build.rs +14 -14
  93. package/sdk-core/sdk-core-protos/protos/api_upstream/.buildkite/Dockerfile +2 -0
  94. package/sdk-core/sdk-core-protos/protos/api_upstream/Makefile +99 -0
  95. package/sdk-core/sdk-core-protos/protos/api_upstream/api-linter.yaml +56 -0
  96. package/sdk-core/sdk-core-protos/protos/api_upstream/buf.gen.yaml +20 -0
  97. package/sdk-core/sdk-core-protos/protos/api_upstream/buf.lock +11 -0
  98. package/sdk-core/sdk-core-protos/protos/api_upstream/buf.yaml +18 -0
  99. package/sdk-core/sdk-core-protos/protos/api_upstream/google/api/annotations.proto +31 -0
  100. package/sdk-core/sdk-core-protos/protos/api_upstream/google/api/http.proto +379 -0
  101. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/any.proto +162 -0
  102. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/descriptor.proto +1212 -0
  103. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/duration.proto +115 -0
  104. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/empty.proto +51 -0
  105. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/timestamp.proto +144 -0
  106. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/wrappers.proto +123 -0
  107. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/batch/v1/message.proto +12 -9
  108. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/command/v1/message.proto +11 -13
  109. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/common/v1/message.proto +33 -4
  110. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/failed_cause.proto +2 -0
  111. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/reset.proto +4 -4
  112. package/sdk-core/{protos/api_upstream/build/tools.go → sdk-core-protos/protos/api_upstream/temporal/api/export/v1/message.proto} +22 -6
  113. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/filter/v1/message.proto +2 -4
  114. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/history/v1/message.proto +21 -23
  115. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/namespace/v1/message.proto +2 -4
  116. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/operatorservice/v1/request_response.proto +2 -0
  117. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/operatorservice/v1/service.proto +4 -0
  118. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/replication/v1/message.proto +1 -3
  119. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/schedule/v1/message.proto +36 -20
  120. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +13 -0
  121. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/sdk/v1/workflow_metadata.proto +66 -0
  122. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/taskqueue/v1/message.proto +2 -4
  123. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/update/v1/message.proto +1 -1
  124. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/version/v1/message.proto +2 -3
  125. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/workflow/v1/message.proto +24 -22
  126. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/workflowservice/v1/request_response.proto +84 -32
  127. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/workflowservice/v1/service.proto +205 -47
  128. package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +57 -0
  129. package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +27 -0
  130. package/sdk-core/sdk-core-protos/src/history_builder.rs +67 -2
  131. package/sdk-core/sdk-core-protos/src/history_info.rs +1 -1
  132. package/sdk-core/sdk-core-protos/src/lib.rs +76 -3
  133. package/sdk-core/sdk-core-protos/src/utilities.rs +14 -0
  134. package/sdk-core/test-utils/Cargo.toml +6 -1
  135. package/sdk-core/test-utils/src/canned_histories.rs +3 -57
  136. package/sdk-core/test-utils/src/interceptors.rs +46 -0
  137. package/sdk-core/test-utils/src/lib.rs +106 -38
  138. package/sdk-core/tests/integ_tests/metrics_tests.rs +110 -15
  139. package/sdk-core/tests/integ_tests/queries_tests.rs +174 -3
  140. package/sdk-core/tests/integ_tests/update_tests.rs +908 -0
  141. package/sdk-core/tests/integ_tests/visibility_tests.rs +4 -4
  142. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +44 -1
  143. package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +1 -1
  144. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +1 -1
  145. package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +4 -4
  146. package/sdk-core/tests/integ_tests/workflow_tests/eager.rs +61 -0
  147. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +27 -2
  148. package/sdk-core/tests/integ_tests/workflow_tests.rs +142 -3
  149. package/sdk-core/tests/main.rs +2 -1
  150. package/sdk-core/tests/runner.rs +15 -2
  151. package/src/conversions.rs +107 -96
  152. package/src/helpers.rs +74 -0
  153. package/src/runtime.rs +29 -15
  154. package/src/worker.rs +14 -61
  155. package/ts/index.ts +23 -54
  156. package/sdk-core/.buildkite/docker/Dockerfile +0 -9
  157. package/sdk-core/.buildkite/docker/build.sh +0 -5
  158. package/sdk-core/.buildkite/docker/docker-compose-ci.yaml +0 -27
  159. package/sdk-core/.buildkite/pipeline.yml +0 -57
  160. package/sdk-core/.github/workflows/semgrep.yml +0 -25
  161. package/sdk-core/client/LICENSE.txt +0 -23
  162. package/sdk-core/core/LICENSE.txt +0 -23
  163. package/sdk-core/core/src/worker/workflow/bridge.rs +0 -35
  164. package/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +0 -215
  165. package/sdk-core/core-api/LICENSE.txt +0 -23
  166. package/sdk-core/protos/api_upstream/.buildkite/Dockerfile +0 -2
  167. package/sdk-core/protos/api_upstream/Makefile +0 -80
  168. package/sdk-core/protos/api_upstream/api-linter.yaml +0 -40
  169. package/sdk-core/protos/api_upstream/buf.yaml +0 -9
  170. package/sdk-core/protos/api_upstream/build/go.mod +0 -7
  171. package/sdk-core/protos/api_upstream/build/go.sum +0 -5
  172. package/sdk-core/protos/api_upstream/go.mod +0 -6
  173. package/sdk-core/protos/testsrv_upstream/dependencies/gogoproto/gogo.proto +0 -141
  174. package/sdk-core/sdk/LICENSE.txt +0 -23
  175. package/sdk-core/sdk-core-protos/LICENSE.txt +0 -23
  176. /package/sdk-core/{.buildkite/docker → docker}/docker-compose-telem.yaml +0 -0
  177. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.buildkite/docker-compose.yml +0 -0
  178. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.buildkite/pipeline.yml +0 -0
  179. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.github/CODEOWNERS +0 -0
  180. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  181. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.github/workflows/publish-docs.yml +0 -0
  182. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.github/workflows/trigger-api-go-update.yml +0 -0
  183. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/LICENSE +0 -0
  184. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/README.md +0 -0
  185. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/batch_operation.proto +0 -0
  186. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/command_type.proto +0 -0
  187. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/common.proto +0 -0
  188. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/event_type.proto +0 -0
  189. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/namespace.proto +0 -0
  190. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/query.proto +0 -0
  191. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/schedule.proto +0 -0
  192. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/task_queue.proto +0 -0
  193. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/update.proto +0 -0
  194. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/workflow.proto +0 -0
  195. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/errordetails/v1/message.proto +0 -0
  196. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/failure/v1/message.proto +0 -0
  197. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/protocol/v1/message.proto +0 -0
  198. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/query/v1/message.proto +0 -0
  199. /package/sdk-core/{protos → sdk-core-protos/protos}/google/rpc/status.proto +0 -0
  200. /package/sdk-core/{protos → sdk-core-protos/protos}/grpc/health/v1/health.proto +0 -0
  201. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/activity_result/activity_result.proto +0 -0
  202. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/activity_task/activity_task.proto +0 -0
  203. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/child_workflow/child_workflow.proto +0 -0
  204. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/common/common.proto +0 -0
  205. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/core_interface.proto +0 -0
  206. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/external_data/external_data.proto +0 -0
  207. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +0 -0
  208. /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/Makefile +0 -0
  209. /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/api-linter.yaml +0 -0
  210. /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/buf.yaml +0 -0
  211. /package/sdk-core/{protos/api_upstream → sdk-core-protos/protos/testsrv_upstream}/dependencies/gogoproto/gogo.proto +0 -0
  212. /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +0 -0
  213. /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/temporal/api/testservice/v1/service.proto +0 -0
@@ -10,6 +10,7 @@ option ruby_package = "Temporalio::Bridge::Api::WorkflowCommands";
10
10
 
11
11
  import "google/protobuf/duration.proto";
12
12
  import "google/protobuf/timestamp.proto";
13
+ import "google/protobuf/empty.proto";
13
14
  import "temporal/api/common/v1/message.proto";
14
15
  import "temporal/api/enums/v1/workflow.proto";
15
16
  import "temporal/api/failure/v1/message.proto";
@@ -37,6 +38,7 @@ message WorkflowCommand {
37
38
  RequestCancelLocalActivity request_cancel_local_activity = 17;
38
39
  UpsertWorkflowSearchAttributes upsert_workflow_search_attributes = 18;
39
40
  ModifyWorkflowProperties modify_workflow_properties = 19;
41
+ UpdateResponse update_response = 20;
40
42
  }
41
43
  }
42
44
 
@@ -309,3 +311,28 @@ message ModifyWorkflowProperties {
309
311
  // used as the value for the key being deleted.
310
312
  temporal.api.common.v1.Memo upserted_memo = 1;
311
313
  }
314
+
315
+ // A reply to a `DoUpdate` job - lang must run the update's validator if told to, and then
316
+ // immediately run the handler, if the update was accepted.
317
+ //
318
+ // There must always be an accepted or rejected response immediately, in the same activation as
319
+ // this job, to indicate the result of the validator. Accepted for ran and accepted or skipped, or
320
+ // rejected for rejected.
321
+ //
322
+ // Then, in the same or any subsequent activation, after the update handler has completed, respond
323
+ // with completed or rejected as appropriate for the result of the handler.
324
+ message UpdateResponse {
325
+ // The protocol message instance ID
326
+ string protocol_instance_id = 1;
327
+ oneof response {
328
+ // Must be sent if the update's validator has passed (or lang was not asked to run it, and
329
+ // thus should be considered already-accepted, allowing lang to always send the same
330
+ // sequence on replay).
331
+ google.protobuf.Empty accepted = 2;
332
+ // Must be sent if the update's validator does not pass, or after acceptance if the update
333
+ // handler fails.
334
+ temporal.api.failure.v1.Failure rejected = 3;
335
+ // Must be sent once the update handler completes successfully.
336
+ temporal.api.common.v1.Payload completed = 4;
337
+ }
338
+ }
@@ -17,6 +17,8 @@ use crate::{
17
17
  failure::v1::{failure, CanceledFailureInfo, Failure},
18
18
  history::v1::{history_event::Attributes, *},
19
19
  taskqueue::v1::TaskQueue,
20
+ update,
21
+ update::v1::outcome,
20
22
  },
21
23
  HistoryInfo,
22
24
  };
@@ -433,7 +435,55 @@ impl TestHistoryBuilder {
433
435
  workflow_task_completed_event_id: self.previous_task_completed_id,
434
436
  search_attributes: Some(SearchAttributes { indexed_fields }),
435
437
  };
436
- self.build_and_push_event(EventType::UpsertWorkflowSearchAttributes, attrs.into())
438
+ self.build_and_push_event(EventType::UpsertWorkflowSearchAttributes, attrs.into());
439
+ }
440
+
441
+ pub fn add_update_accepted(
442
+ &mut self,
443
+ instance_id: impl Into<String>,
444
+ update_name: impl Into<String>,
445
+ ) -> i64 {
446
+ let protocol_instance_id = instance_id.into();
447
+ let last_wft_started_id = self
448
+ .events
449
+ .iter()
450
+ .rev()
451
+ .find_map(|e| {
452
+ if e.event_type() == EventType::WorkflowTaskScheduled {
453
+ Some(e.event_id)
454
+ } else {
455
+ None
456
+ }
457
+ })
458
+ .expect("Must have wft scheduled event");
459
+ let attrs = WorkflowExecutionUpdateAcceptedEventAttributes {
460
+ accepted_request_message_id: format!("{}/request", &protocol_instance_id),
461
+ accepted_request_sequencing_event_id: last_wft_started_id,
462
+ accepted_request: Some(update::v1::Request {
463
+ meta: Some(update::v1::Meta {
464
+ update_id: protocol_instance_id.clone(),
465
+ identity: "fake".to_string(),
466
+ }),
467
+ input: Some(update::v1::Input {
468
+ header: None,
469
+ name: update_name.into(),
470
+ args: None,
471
+ }),
472
+ }),
473
+ protocol_instance_id,
474
+ };
475
+ self.build_and_push_event(EventType::WorkflowExecutionUpdateAccepted, attrs.into())
476
+ }
477
+
478
+ pub fn add_update_completed(&mut self, accepted_event_id: i64) {
479
+ let attrs = WorkflowExecutionUpdateCompletedEventAttributes {
480
+ meta: None,
481
+ accepted_event_id,
482
+ outcome: Some(update::v1::Outcome {
483
+ value: Some(outcome::Value::Success(Payloads::default())),
484
+ }),
485
+ };
486
+ self.build_and_push_event(EventType::WorkflowExecutionUpdateCompleted, attrs.into());
437
487
  }
438
488
 
439
489
  pub fn get_orig_run_id(&self) -> &str {
@@ -478,6 +528,15 @@ impl TestHistoryBuilder {
478
528
  }
479
529
  }
480
530
 
531
+ /// Alter the input to the workflow
532
+ pub fn set_wf_input(&mut self, input: impl Into<Payloads>) {
533
+ if let Some(Attributes::WorkflowExecutionStartedEventAttributes(wes)) =
534
+ self.events.get_mut(0).and_then(|e| e.attributes.as_mut())
535
+ {
536
+ wes.input = Some(input.into());
537
+ }
538
+ }
539
+
481
540
  /// Alter some specific event. You can easily craft nonsense histories this way, use carefully.
482
541
  pub fn modify_event(&mut self, event_id: i64, modifier: impl FnOnce(&mut HistoryEvent)) {
483
542
  let he = self
@@ -497,6 +556,11 @@ impl TestHistoryBuilder {
497
556
  Self::set_flags(self.events.iter_mut().rev(), core, lang)
498
557
  }
499
558
 
559
+ /// Get the event ID of the most recently added event
560
+ pub fn current_event_id(&self) -> i64 {
561
+ self.current_event_id
562
+ }
563
+
500
564
  fn set_flags<'a>(
501
565
  mut events: impl Iterator<Item = &'a mut HistoryEvent>,
502
566
  core: &[u32],
@@ -518,7 +582,7 @@ impl TestHistoryBuilder {
518
582
  }
519
583
  }
520
584
 
521
- fn build_and_push_event(&mut self, event_type: EventType, attribs: Attributes) {
585
+ fn build_and_push_event(&mut self, event_type: EventType, attribs: Attributes) -> i64 {
522
586
  self.current_event_id += 1;
523
587
  let evt = HistoryEvent {
524
588
  event_type: event_type as i32,
@@ -537,6 +601,7 @@ impl TestHistoryBuilder {
537
601
  self.original_run_id = original_execution_run_id.clone();
538
602
  };
539
603
  self.events.push(evt);
604
+ self.current_event_id
540
605
  }
541
606
  }
542
607
 
@@ -37,7 +37,7 @@ impl HistoryInfo {
37
37
  let mut workflow_task_started_event_id = 0;
38
38
  let mut wf_task_count = 0;
39
39
  let mut history = events.iter().peekable();
40
- let started_attrs = match &events.get(0).unwrap().attributes {
40
+ let started_attrs = match &events.first().unwrap().attributes {
41
41
  Some(history_event::Attributes::WorkflowExecutionStartedEventAttributes(attrs)) => {
42
42
  attrs.clone()
43
43
  }
@@ -24,7 +24,11 @@ pub static ENCODING_PAYLOAD_KEY: &str = "encoding";
24
24
  pub static JSON_ENCODING_VAL: &str = "json/plain";
25
25
  pub static PATCHED_MARKER_DETAILS_KEY: &str = "patch-data";
26
26
 
27
- #[allow(clippy::large_enum_variant, clippy::derive_partial_eq_without_eq)]
27
+ #[allow(
28
+ clippy::large_enum_variant,
29
+ clippy::derive_partial_eq_without_eq,
30
+ clippy::reserve_after_initialization
31
+ )]
28
32
  // I'd prefer not to do this, but there are some generated things that just don't need it.
29
33
  #[allow(missing_docs)]
30
34
  pub mod coresdk {
@@ -68,6 +72,15 @@ pub mod coresdk {
68
72
  })),
69
73
  }
70
74
  }
75
+
76
+ pub fn is_timeout(&self) -> bool {
77
+ match &self.variant {
78
+ Some(activity_task::Variant::Cancel(Cancel { reason })) => {
79
+ *reason == ActivityCancelReason::TimedOut as i32
80
+ }
81
+ _ => false,
82
+ }
83
+ }
71
84
  }
72
85
 
73
86
  impl Display for ActivityTaskCompletion {
@@ -323,7 +336,7 @@ pub mod coresdk {
323
336
  ) -> Option<LocalActivityMarkerData> {
324
337
  details
325
338
  .get("data")
326
- .and_then(|p| p.payloads.get(0))
339
+ .and_then(|p| p.payloads.first())
327
340
  .and_then(|p| std::str::from_utf8(&p.data).ok())
328
341
  .and_then(|s| serde_json::from_str(s).ok())
329
342
  }
@@ -456,6 +469,7 @@ pub mod coresdk {
456
469
  available_internal_flags: vec![],
457
470
  history_size_bytes: 0,
458
471
  continue_as_new_suggested: false,
472
+ build_id_for_current_task: "".to_string(),
459
473
  }
460
474
  }
461
475
 
@@ -603,6 +617,9 @@ pub mod coresdk {
603
617
  workflow_activation_job::Variant::ResolveRequestCancelExternalWorkflow(_) => {
604
618
  write!(f, "ResolveRequestCancelExternalWorkflow")
605
619
  }
620
+ workflow_activation_job::Variant::DoUpdate(_) => {
621
+ write!(f, "DoUpdate")
622
+ }
606
623
  }
607
624
  }
608
625
  }
@@ -854,6 +871,16 @@ pub mod coresdk {
854
871
  }
855
872
  }
856
873
 
874
+ impl Display for UpdateResponse {
875
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
876
+ write!(
877
+ f,
878
+ "UpdateResponse(protocol_instance_id: {}, response: {:?})",
879
+ self.protocol_instance_id, self.response
880
+ )
881
+ }
882
+ }
883
+
857
884
  impl QueryResult {
858
885
  /// Helper to construct the Temporal API query result types.
859
886
  pub fn into_components(self) -> (String, QueryResultType, Option<Payloads>, String) {
@@ -1452,6 +1479,14 @@ pub mod temporal {
1452
1479
  command_type: CommandType::CancelWorkflowExecution as i32,
1453
1480
  attributes: Some(a),
1454
1481
  },
1482
+ a @ Attributes::RecordMarkerCommandAttributes(_) => Self {
1483
+ command_type: CommandType::RecordMarker as i32,
1484
+ attributes: Some(a),
1485
+ },
1486
+ a @ Attributes::ProtocolMessageCommandAttributes(_) => Self {
1487
+ command_type: CommandType::ProtocolMessage as i32,
1488
+ attributes: Some(a),
1489
+ },
1455
1490
  _ => unimplemented!(),
1456
1491
  }
1457
1492
  }
@@ -1732,6 +1767,14 @@ pub mod temporal {
1732
1767
  at.name
1733
1768
  }
1734
1769
  }
1770
+
1771
+ impl From<&str> for WorkflowType {
1772
+ fn from(v: &str) -> Self {
1773
+ Self {
1774
+ name: v.to_string(),
1775
+ }
1776
+ }
1777
+ }
1735
1778
  }
1736
1779
  }
1737
1780
  pub mod enums {
@@ -1801,7 +1844,10 @@ pub mod temporal {
1801
1844
  | EventType::WorkflowExecutionCanceled
1802
1845
  | EventType::WorkflowExecutionCompleted
1803
1846
  | EventType::WorkflowExecutionContinuedAsNew
1804
- | EventType::WorkflowExecutionFailed => true,
1847
+ | EventType::WorkflowExecutionFailed
1848
+ | EventType::WorkflowExecutionUpdateAccepted
1849
+ | EventType::WorkflowExecutionUpdateRejected
1850
+ | EventType::WorkflowExecutionUpdateCompleted => true,
1805
1851
  _ => false,
1806
1852
  })
1807
1853
  }
@@ -1844,6 +1890,16 @@ pub mod temporal {
1844
1890
  })
1845
1891
  }
1846
1892
 
1893
+ /// Return the event's associated protocol instance, if one exists.
1894
+ pub fn get_protocol_instance_id(&self) -> Option<&str> {
1895
+ self.attributes.as_ref().and_then(|a| match a {
1896
+ Attributes::WorkflowExecutionUpdateAcceptedEventAttributes(a) => {
1897
+ Some(a.protocol_instance_id.as_str())
1898
+ }
1899
+ _ => None,
1900
+ })
1901
+ }
1902
+
1847
1903
  /// Returns true if the event is one which would end a workflow
1848
1904
  pub fn is_final_wf_execution_event(&self) -> bool {
1849
1905
  match self.event_type() {
@@ -1945,7 +2001,14 @@ pub mod temporal {
1945
2001
  }
1946
2002
  pub mod protocol {
1947
2003
  pub mod v1 {
2004
+ use std::fmt::{Display, Formatter};
1948
2005
  tonic::include_proto!("temporal.api.protocol.v1");
2006
+
2007
+ impl Display for Message {
2008
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
2009
+ write!(f, "ProtocolMessage({})", self.id)
2010
+ }
2011
+ }
1949
2012
  }
1950
2013
  }
1951
2014
  pub mod query {
@@ -1992,7 +2055,17 @@ pub mod temporal {
1992
2055
  }
1993
2056
  pub mod update {
1994
2057
  pub mod v1 {
2058
+ use crate::temporal::api::update::v1::outcome::Value;
1995
2059
  tonic::include_proto!("temporal.api.update.v1");
2060
+
2061
+ impl Outcome {
2062
+ pub fn is_success(&self) -> bool {
2063
+ match self.value {
2064
+ Some(Value::Success(_)) => true,
2065
+ _ => false,
2066
+ }
2067
+ }
2068
+ }
1996
2069
  }
1997
2070
  }
1998
2071
  pub mod version {
@@ -1,3 +1,5 @@
1
+ use prost::{EncodeError, Message};
2
+
1
3
  pub trait TryIntoOrNone<F, T> {
2
4
  /// Turn an option of something into an option of another thing, trying to convert along the way
3
5
  /// and returning `None` if that conversion fails
@@ -12,3 +14,15 @@ where
12
14
  self.map(TryInto::try_into).transpose().ok().flatten()
13
15
  }
14
16
  }
17
+
18
+ /// Use to encode an message into a proto `Any`.
19
+ ///
20
+ /// Delete this once `prost_wkt_types` supports `prost` `0.12.x` which has built-in any packing.
21
+ pub fn pack_any<T: Message>(
22
+ type_url: String,
23
+ msg: &T,
24
+ ) -> Result<prost_wkt_types::Any, EncodeError> {
25
+ let mut value = Vec::new();
26
+ Message::encode(msg, &mut value)?;
27
+ Ok(prost_wkt_types::Any { type_url, value })
28
+ }
@@ -3,11 +3,16 @@ name = "temporal-sdk-core-test-utils"
3
3
  version = "0.1.0"
4
4
  authors = ["Spencer Judge <spencer@temporal.io>"]
5
5
  edition = "2021"
6
+ license-file = { workspace = true }
6
7
 
7
8
  [[bin]]
8
9
  name = "histfetch"
9
10
  path = "src/histfetch.rs"
10
11
 
12
+ [features]
13
+ default = ["ephemeral-server"]
14
+ ephemeral-server = ["temporal-sdk-core/ephemeral-server"]
15
+
11
16
  [dependencies]
12
17
  anyhow = "1.0"
13
18
  async-trait = "0.1"
@@ -24,7 +29,7 @@ rmp-serde = "1.1"
24
29
  serde_json = "1.0"
25
30
  temporal-client = { path = "../client" }
26
31
  temporal-sdk = { path = "../sdk" }
27
- temporal-sdk-core = { path = "../core", features = ["ephemeral-server"] }
32
+ temporal-sdk-core = { path = "../core" }
28
33
  temporal-sdk-core-api = { path = "../core-api" }
29
34
  thiserror = "1.0"
30
35
  tokio = "1.1"
@@ -6,7 +6,7 @@ use temporal_sdk_core_protos::{
6
6
  coresdk::common::NamespacedWorkflowExecution,
7
7
  temporal::api::{
8
8
  common::v1::{Payload, WorkflowExecution},
9
- enums::v1::{EventType, StartChildWorkflowExecutionFailedCause, WorkflowTaskFailedCause},
9
+ enums::v1::{EventType, WorkflowTaskFailedCause},
10
10
  failure::v1::Failure,
11
11
  history::v1::*,
12
12
  },
@@ -1110,6 +1110,7 @@ fn start_child_wf_preamble(child_wf_id: &str) -> (TestHistoryBuilder, i64, i64)
1110
1110
  t.add_full_wf_task();
1111
1111
  let initiated_event_id = t.add(StartChildWorkflowExecutionInitiatedEventAttributes {
1112
1112
  workflow_id: child_wf_id.to_owned(),
1113
+ workflow_type: Some("child".into()),
1113
1114
  ..Default::default()
1114
1115
  });
1115
1116
  let started_event_id = t.add(ChildWorkflowExecutionStartedEventAttributes {
@@ -1145,7 +1146,6 @@ pub fn single_child_workflow(child_wf_id: &str) -> TestHistoryBuilder {
1145
1146
  ChildWorkflowExecutionCompletedEventAttributes {
1146
1147
  initiated_event_id,
1147
1148
  started_event_id,
1148
- // todo add the result payload
1149
1149
  ..Default::default()
1150
1150
  },
1151
1151
  ),
@@ -1299,35 +1299,6 @@ pub fn single_child_workflow_try_cancelled(child_wf_id: &str) -> TestHistoryBuil
1299
1299
  t
1300
1300
  }
1301
1301
 
1302
- /// 1: EVENT_TYPE_WORKFLOW_EXECUTION_STARTED
1303
- /// 2: EVENT_TYPE_WORKFLOW_TASK_SCHEDULED
1304
- /// 3: EVENT_TYPE_WORKFLOW_TASK_STARTED
1305
- /// 4: EVENT_TYPE_WORKFLOW_TASK_COMPLETED
1306
- /// 5: EVENT_TYPE_START_CHILD_WORKFLOW_EXECUTION_INITIATED
1307
- /// 5: EVENT_TYPE_START_CHILD_WORKFLOW_EXECUTION_FAILED
1308
- /// 6: EVENT_TYPE_WORKFLOW_TASK_SCHEDULED
1309
- /// 7: EVENT_TYPE_WORKFLOW_TASK_STARTED
1310
- /// 8: EVENT_TYPE_WORKFLOW_TASK_COMPLETED
1311
- /// 9: EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED
1312
- pub fn single_child_workflow_start_fail(child_wf_id: &str) -> TestHistoryBuilder {
1313
- let mut t = TestHistoryBuilder::default();
1314
- t.add_by_type(EventType::WorkflowExecutionStarted);
1315
- t.add_full_wf_task();
1316
- let initiated_event_id = t.add(StartChildWorkflowExecutionInitiatedEventAttributes {
1317
- workflow_id: child_wf_id.to_owned(),
1318
- ..Default::default()
1319
- });
1320
- t.add(StartChildWorkflowExecutionFailedEventAttributes {
1321
- workflow_id: child_wf_id.to_owned(),
1322
- initiated_event_id,
1323
- cause: StartChildWorkflowExecutionFailedCause::WorkflowAlreadyExists as i32,
1324
- ..Default::default()
1325
- });
1326
- t.add_full_wf_task();
1327
- t.add_workflow_execution_completed();
1328
- t
1329
- }
1330
-
1331
1302
  /// 1: EVENT_TYPE_WORKFLOW_EXECUTION_STARTED
1332
1303
  /// 2: EVENT_TYPE_WORKFLOW_TASK_SCHEDULED
1333
1304
  /// 3: EVENT_TYPE_WORKFLOW_TASK_STARTED
@@ -1346,32 +1317,7 @@ pub fn two_local_activities_one_wft(parallel: bool) -> TestHistoryBuilder {
1346
1317
  start_time.seconds += 1;
1347
1318
  }
1348
1319
  t.add_local_activity_result_marker_with_time(2, "2", b"hi2".into(), start_time);
1349
- t.add_workflow_execution_completed();
1350
- t
1351
- }
1352
-
1353
- /// 1: EVENT_TYPE_WORKFLOW_EXECUTION_STARTED
1354
- /// 2: EVENT_TYPE_WORKFLOW_TASK_SCHEDULED
1355
- /// 3: EVENT_TYPE_WORKFLOW_TASK_STARTED
1356
- /// 4: EVENT_TYPE_WORKFLOW_TASK_COMPLETED
1357
- /// 5: EVENT_TYPE_MARKER_RECORDED (la result)
1358
- /// 6: EVENT_TYPE_TIMER_STARTED
1359
- /// 7: EVENT_TYPE_TIMER_FIRED
1360
- /// 8: EVENT_TYPE_WORKFLOW_TASK_SCHEDULED
1361
- /// 9: EVENT_TYPE_WORKFLOW_TASK_STARTED
1362
- /// 10: EVENT_TYPE_WORKFLOW_TASK_COMPLETED
1363
- /// 11: EVENT_TYPE_MARKER_RECORDED (la result)
1364
- /// 12: EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED
1365
- pub fn two_local_activities_separated_by_timer() -> TestHistoryBuilder {
1366
- let mut t = TestHistoryBuilder::default();
1367
- t.add_by_type(EventType::WorkflowExecutionStarted);
1368
- t.add_full_wf_task();
1369
- t.add_local_activity_result_marker(1, "1", b"hi".into());
1370
- let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
1371
- t.add_timer_fired(timer_started_event_id, "1".to_string());
1372
- t.add_full_wf_task();
1373
- t.add_local_activity_result_marker(2, "2", b"hi2".into());
1374
- t.add_workflow_execution_completed();
1320
+ t.add_workflow_task_scheduled_and_started();
1375
1321
  t
1376
1322
  }
1377
1323
 
@@ -0,0 +1,46 @@
1
+ use anyhow::Error;
2
+ use parking_lot::Mutex;
3
+ use std::{
4
+ collections::VecDeque,
5
+ sync::atomic::{AtomicBool, Ordering},
6
+ };
7
+ use temporal_sdk::interceptors::WorkerInterceptor;
8
+ use temporal_sdk_core_protos::coresdk::workflow_activation::WorkflowActivation;
9
+
10
+ #[derive(Default)]
11
+ pub struct ActivationAssertionsInterceptor {
12
+ #[allow(clippy::type_complexity)]
13
+ assertions: Mutex<VecDeque<Box<dyn FnOnce(&WorkflowActivation)>>>,
14
+ used: AtomicBool,
15
+ }
16
+
17
+ impl ActivationAssertionsInterceptor {
18
+ pub fn skip_one(&mut self) -> &mut Self {
19
+ self.assertions.lock().push_back(Box::new(|_| {}));
20
+ self
21
+ }
22
+
23
+ pub fn then(&mut self, assert: impl FnOnce(&WorkflowActivation) + 'static) -> &mut Self {
24
+ self.assertions.lock().push_back(Box::new(assert));
25
+ self
26
+ }
27
+ }
28
+
29
+ #[async_trait::async_trait(?Send)]
30
+ impl WorkerInterceptor for ActivationAssertionsInterceptor {
31
+ async fn on_workflow_activation(&self, act: &WorkflowActivation) -> Result<(), Error> {
32
+ self.used.store(true, Ordering::Relaxed);
33
+ if let Some(fun) = self.assertions.lock().pop_front() {
34
+ fun(act);
35
+ }
36
+ Ok(())
37
+ }
38
+ }
39
+
40
+ impl Drop for ActivationAssertionsInterceptor {
41
+ fn drop(&mut self) {
42
+ if !self.used.load(Ordering::Relaxed) {
43
+ panic!("Activation assertions interceptor was never used!")
44
+ }
45
+ }
46
+ }