@temporalio/core-bridge 1.8.5 → 1.9.0-rc.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 (196) hide show
  1. package/Cargo.lock +189 -152
  2. package/Cargo.toml +1 -0
  3. package/lib/index.d.ts +17 -44
  4. package/lib/index.js.map +1 -1
  5. package/package.json +3 -4
  6. package/releases/aarch64-apple-darwin/index.node +0 -0
  7. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  8. package/releases/x86_64-apple-darwin/index.node +0 -0
  9. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  10. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  11. package/sdk-core/.github/workflows/heavy.yml +4 -0
  12. package/sdk-core/.github/workflows/per-pr.yml +96 -0
  13. package/sdk-core/ARCHITECTURE.md +1 -1
  14. package/sdk-core/Cargo.toml +6 -0
  15. package/sdk-core/README.md +37 -21
  16. package/sdk-core/client/Cargo.toml +6 -3
  17. package/sdk-core/client/src/lib.rs +272 -138
  18. package/sdk-core/client/src/metrics.rs +68 -57
  19. package/sdk-core/client/src/raw.rs +191 -45
  20. package/sdk-core/client/src/retry.rs +20 -0
  21. package/sdk-core/client/src/worker_registry/mod.rs +264 -0
  22. package/sdk-core/client/src/workflow_handle/mod.rs +2 -1
  23. package/sdk-core/core/Cargo.toml +16 -18
  24. package/sdk-core/core/src/core_tests/child_workflows.rs +7 -7
  25. package/sdk-core/core/src/core_tests/mod.rs +1 -0
  26. package/sdk-core/core/src/core_tests/replay_flag.rs +29 -39
  27. package/sdk-core/core/src/core_tests/updates.rs +73 -0
  28. package/sdk-core/core/src/core_tests/workflow_tasks.rs +52 -1
  29. package/sdk-core/core/src/ephemeral_server/mod.rs +34 -11
  30. package/sdk-core/core/src/internal_flags.rs +7 -1
  31. package/sdk-core/core/src/lib.rs +19 -36
  32. package/sdk-core/core/src/protosext/mod.rs +11 -3
  33. package/sdk-core/core/src/protosext/protocol_messages.rs +102 -0
  34. package/sdk-core/core/src/replay/mod.rs +100 -48
  35. package/sdk-core/core/src/telemetry/log_export.rs +161 -28
  36. package/sdk-core/core/src/telemetry/metrics.rs +869 -248
  37. package/sdk-core/core/src/telemetry/mod.rs +135 -239
  38. package/sdk-core/core/src/telemetry/prometheus_server.rs +36 -31
  39. package/sdk-core/core/src/test_help/mod.rs +63 -4
  40. package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +12 -2
  41. package/sdk-core/core/src/worker/activities.rs +276 -10
  42. package/sdk-core/core/src/worker/client/mocks.rs +18 -0
  43. package/sdk-core/core/src/worker/client.rs +16 -3
  44. package/sdk-core/core/src/worker/mod.rs +50 -19
  45. package/sdk-core/core/src/worker/slot_provider.rs +175 -0
  46. package/sdk-core/core/src/worker/workflow/driven_workflow.rs +27 -34
  47. package/sdk-core/core/src/worker/workflow/history_update.rs +4 -1
  48. package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +36 -94
  49. package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +34 -22
  50. package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +50 -34
  51. package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +106 -92
  52. package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +22 -21
  53. package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +386 -499
  54. package/sdk-core/core/src/worker/workflow/machines/mod.rs +12 -2
  55. package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +33 -26
  56. package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +198 -215
  57. package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +66 -62
  58. package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +88 -119
  59. package/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +3 -1
  60. package/sdk-core/core/src/worker/workflow/machines/update_state_machine.rs +411 -0
  61. package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +26 -25
  62. package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +302 -85
  63. package/sdk-core/core/src/worker/workflow/managed_run.rs +179 -132
  64. package/sdk-core/core/src/worker/workflow/mod.rs +121 -46
  65. package/sdk-core/core/src/worker/workflow/run_cache.rs +8 -12
  66. package/sdk-core/core/src/worker/workflow/workflow_stream.rs +45 -38
  67. package/sdk-core/core-api/Cargo.toml +7 -6
  68. package/sdk-core/core-api/src/lib.rs +4 -12
  69. package/sdk-core/core-api/src/telemetry/metrics.rs +334 -0
  70. package/sdk-core/core-api/src/telemetry.rs +53 -42
  71. package/sdk-core/core-api/src/worker.rs +7 -0
  72. package/sdk-core/{.buildkite/docker → docker}/docker-compose.yaml +1 -1
  73. package/sdk-core/etc/dynamic-config.yaml +11 -1
  74. package/sdk-core/fsm/rustfsm_procmacro/Cargo.toml +1 -1
  75. package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +1 -3
  76. package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +2 -2
  77. package/sdk-core/sdk/Cargo.toml +1 -1
  78. package/sdk-core/sdk/src/lib.rs +85 -7
  79. package/sdk-core/sdk/src/workflow_context/options.rs +4 -0
  80. package/sdk-core/sdk/src/workflow_context.rs +43 -15
  81. package/sdk-core/sdk/src/workflow_future.rs +334 -204
  82. package/sdk-core/sdk-core-protos/Cargo.toml +2 -2
  83. package/sdk-core/sdk-core-protos/build.rs +14 -14
  84. package/sdk-core/sdk-core-protos/protos/api_upstream/.buildkite/Dockerfile +2 -0
  85. package/sdk-core/sdk-core-protos/protos/api_upstream/Makefile +99 -0
  86. package/sdk-core/sdk-core-protos/protos/api_upstream/api-linter.yaml +56 -0
  87. package/sdk-core/sdk-core-protos/protos/api_upstream/buf.gen.yaml +20 -0
  88. package/sdk-core/sdk-core-protos/protos/api_upstream/buf.lock +11 -0
  89. package/sdk-core/sdk-core-protos/protos/api_upstream/buf.yaml +18 -0
  90. package/sdk-core/sdk-core-protos/protos/api_upstream/google/api/annotations.proto +31 -0
  91. package/sdk-core/sdk-core-protos/protos/api_upstream/google/api/http.proto +379 -0
  92. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/any.proto +162 -0
  93. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/descriptor.proto +1212 -0
  94. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/duration.proto +115 -0
  95. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/empty.proto +51 -0
  96. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/timestamp.proto +144 -0
  97. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/wrappers.proto +123 -0
  98. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/batch/v1/message.proto +3 -5
  99. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/command/v1/message.proto +11 -13
  100. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/common/v1/message.proto +2 -4
  101. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/failed_cause.proto +2 -0
  102. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/reset.proto +1 -1
  103. package/sdk-core/{protos/api_upstream/build/tools.go → sdk-core-protos/protos/api_upstream/temporal/api/export/v1/message.proto} +22 -6
  104. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/filter/v1/message.proto +2 -4
  105. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/history/v1/message.proto +21 -23
  106. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/namespace/v1/message.proto +2 -4
  107. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/operatorservice/v1/request_response.proto +2 -0
  108. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/operatorservice/v1/service.proto +4 -0
  109. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/replication/v1/message.proto +1 -3
  110. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/schedule/v1/message.proto +36 -20
  111. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +13 -0
  112. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/taskqueue/v1/message.proto +2 -4
  113. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/update/v1/message.proto +1 -1
  114. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/version/v1/message.proto +2 -3
  115. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/workflow/v1/message.proto +18 -20
  116. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/workflowservice/v1/request_response.proto +84 -32
  117. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/workflowservice/v1/service.proto +205 -47
  118. package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +57 -0
  119. package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +27 -0
  120. package/sdk-core/sdk-core-protos/src/history_builder.rs +67 -2
  121. package/sdk-core/sdk-core-protos/src/lib.rs +75 -2
  122. package/sdk-core/sdk-core-protos/src/utilities.rs +14 -0
  123. package/sdk-core/test-utils/Cargo.toml +5 -1
  124. package/sdk-core/test-utils/src/canned_histories.rs +3 -57
  125. package/sdk-core/test-utils/src/interceptors.rs +46 -0
  126. package/sdk-core/test-utils/src/lib.rs +106 -38
  127. package/sdk-core/tests/integ_tests/metrics_tests.rs +110 -15
  128. package/sdk-core/tests/integ_tests/queries_tests.rs +174 -3
  129. package/sdk-core/tests/integ_tests/update_tests.rs +908 -0
  130. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +44 -1
  131. package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +1 -1
  132. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +1 -1
  133. package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +4 -4
  134. package/sdk-core/tests/integ_tests/workflow_tests/eager.rs +61 -0
  135. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +27 -2
  136. package/sdk-core/tests/integ_tests/workflow_tests.rs +1 -0
  137. package/sdk-core/tests/main.rs +2 -1
  138. package/sdk-core/tests/runner.rs +15 -2
  139. package/src/conversions.rs +75 -89
  140. package/src/helpers.rs +74 -0
  141. package/src/runtime.rs +17 -6
  142. package/src/worker.rs +14 -61
  143. package/ts/index.ts +21 -52
  144. package/sdk-core/.buildkite/docker/Dockerfile +0 -9
  145. package/sdk-core/.buildkite/docker/build.sh +0 -5
  146. package/sdk-core/.buildkite/docker/docker-compose-ci.yaml +0 -27
  147. package/sdk-core/.buildkite/pipeline.yml +0 -57
  148. package/sdk-core/.github/workflows/semgrep.yml +0 -25
  149. package/sdk-core/core/src/worker/workflow/bridge.rs +0 -35
  150. package/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +0 -215
  151. package/sdk-core/protos/api_upstream/.buildkite/Dockerfile +0 -2
  152. package/sdk-core/protos/api_upstream/Makefile +0 -80
  153. package/sdk-core/protos/api_upstream/api-linter.yaml +0 -40
  154. package/sdk-core/protos/api_upstream/buf.yaml +0 -9
  155. package/sdk-core/protos/api_upstream/build/go.mod +0 -7
  156. package/sdk-core/protos/api_upstream/build/go.sum +0 -5
  157. package/sdk-core/protos/api_upstream/go.mod +0 -6
  158. package/sdk-core/protos/testsrv_upstream/dependencies/gogoproto/gogo.proto +0 -141
  159. /package/sdk-core/{.buildkite/docker → docker}/docker-compose-telem.yaml +0 -0
  160. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.buildkite/docker-compose.yml +0 -0
  161. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.buildkite/pipeline.yml +0 -0
  162. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.github/CODEOWNERS +0 -0
  163. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  164. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.github/workflows/publish-docs.yml +0 -0
  165. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.github/workflows/trigger-api-go-update.yml +0 -0
  166. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/LICENSE +0 -0
  167. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/README.md +0 -0
  168. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/batch_operation.proto +0 -0
  169. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/command_type.proto +0 -0
  170. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/common.proto +0 -0
  171. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/event_type.proto +0 -0
  172. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/namespace.proto +0 -0
  173. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/query.proto +0 -0
  174. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/schedule.proto +0 -0
  175. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/task_queue.proto +0 -0
  176. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/update.proto +0 -0
  177. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/workflow.proto +0 -0
  178. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/errordetails/v1/message.proto +0 -0
  179. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/failure/v1/message.proto +0 -0
  180. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/protocol/v1/message.proto +0 -0
  181. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/query/v1/message.proto +0 -0
  182. /package/sdk-core/{protos → sdk-core-protos/protos}/google/rpc/status.proto +0 -0
  183. /package/sdk-core/{protos → sdk-core-protos/protos}/grpc/health/v1/health.proto +0 -0
  184. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/activity_result/activity_result.proto +0 -0
  185. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/activity_task/activity_task.proto +0 -0
  186. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/child_workflow/child_workflow.proto +0 -0
  187. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/common/common.proto +0 -0
  188. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/core_interface.proto +0 -0
  189. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/external_data/external_data.proto +0 -0
  190. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +0 -0
  191. /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/Makefile +0 -0
  192. /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/api-linter.yaml +0 -0
  193. /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/buf.yaml +0 -0
  194. /package/sdk-core/{protos/api_upstream → sdk-core-protos/protos/testsrv_upstream}/dependencies/gogoproto/gogo.proto +0 -0
  195. /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +0 -0
  196. /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/temporal/api/testservice/v1/service.proto +0 -0
@@ -0,0 +1,264 @@
1
+ //! This module enables the tracking of workers that are associated with a client instance.
2
+ //! This is needed to implement Eager Workflow Start, a latency optimization in which the client,
3
+ //! after reserving a slot, directly forwards a WFT to a local worker.
4
+
5
+ use parking_lot::RwLock;
6
+ use slotmap::SlotMap;
7
+ use std::collections::{hash_map::Entry::Vacant, HashMap};
8
+
9
+ use temporal_sdk_core_protos::temporal::api::workflowservice::v1::PollWorkflowTaskQueueResponse;
10
+
11
+ slotmap::new_key_type! {
12
+ /// Registration key for a worker
13
+ pub struct WorkerKey;
14
+ }
15
+
16
+ /// This trait is implemented by an object associated with a worker, which provides WFT processing slots.
17
+ #[cfg_attr(test, mockall::automock)]
18
+ pub trait SlotProvider: std::fmt::Debug {
19
+ /// The namespace for the WFTs that it can process.
20
+ fn namespace(&self) -> &str;
21
+ /// The task queue this provider listens to.
22
+ fn task_queue(&self) -> &str;
23
+ /// Try to reserve a slot on this worker.
24
+ fn try_reserve_wft_slot(&self) -> Option<Box<dyn Slot + Send>>;
25
+ }
26
+
27
+ /// This trait represents a slot reserved for processing a WFT by a worker.
28
+ #[cfg_attr(test, mockall::automock)]
29
+ pub trait Slot {
30
+ /// Consumes this slot by dispatching a WFT to its worker. This can only be called once.
31
+ fn schedule_wft(
32
+ self: Box<Self>,
33
+ task: PollWorkflowTaskQueueResponse,
34
+ ) -> Result<(), anyhow::Error>;
35
+ }
36
+
37
+ #[derive(PartialEq, Eq, Hash, Debug, Clone)]
38
+ struct SlotKey {
39
+ namespace: String,
40
+ task_queue: String,
41
+ }
42
+
43
+ impl SlotKey {
44
+ fn new(namespace: String, task_queue: String) -> SlotKey {
45
+ SlotKey {
46
+ namespace,
47
+ task_queue,
48
+ }
49
+ }
50
+ }
51
+
52
+ /// This is an inner class for [SlotManager] needed to hide the mutex.
53
+ #[derive(Default, Debug)]
54
+ struct SlotManagerImpl {
55
+ /// Maps keys, i.e., namespace#task_queue, to provider.
56
+ providers: HashMap<SlotKey, Box<dyn SlotProvider + Send + Sync>>,
57
+ /// Maps ids to keys in `providers`.
58
+ index: SlotMap<WorkerKey, SlotKey>,
59
+ }
60
+
61
+ impl SlotManagerImpl {
62
+ /// Factory method.
63
+ fn new() -> Self {
64
+ Self {
65
+ index: Default::default(),
66
+ providers: Default::default(),
67
+ }
68
+ }
69
+
70
+ fn try_reserve_wft_slot(
71
+ &self,
72
+ namespace: String,
73
+ task_queue: String,
74
+ ) -> Option<Box<dyn Slot + Send>> {
75
+ let key = SlotKey::new(namespace, task_queue);
76
+ if let Some(p) = self.providers.get(&key) {
77
+ if let Some(slot) = p.try_reserve_wft_slot() {
78
+ return Some(slot);
79
+ }
80
+ }
81
+ None
82
+ }
83
+
84
+ fn register(&mut self, provider: Box<dyn SlotProvider + Send + Sync>) -> Option<WorkerKey> {
85
+ let key = SlotKey::new(
86
+ provider.namespace().to_string(),
87
+ provider.task_queue().to_string(),
88
+ );
89
+ if let Vacant(p) = self.providers.entry(key.clone()) {
90
+ p.insert(provider);
91
+ Some(self.index.insert(key))
92
+ } else {
93
+ warn!("Ignoring registration for worker: {key:?}.");
94
+ None
95
+ }
96
+ }
97
+
98
+ fn unregister(&mut self, id: WorkerKey) {
99
+ if let Some(key) = self.index.remove(id) {
100
+ self.providers.remove(&key);
101
+ }
102
+ }
103
+
104
+ #[cfg(test)]
105
+ fn num_providers(&self) -> (usize, usize) {
106
+ (self.index.len(), self.providers.len())
107
+ }
108
+ }
109
+
110
+ /// Enables local workers to made themselves visible to a shared client instance.
111
+ /// There can only be one worker registered per namespace+queue_name+client, others will get ignored.
112
+ /// It also provides a convenient method to find compatible slots within the collection.
113
+ #[derive(Default, Debug)]
114
+ pub struct SlotManager {
115
+ manager: RwLock<SlotManagerImpl>,
116
+ }
117
+
118
+ impl SlotManager {
119
+ /// Factory method.
120
+ pub fn new() -> Self {
121
+ Self {
122
+ manager: RwLock::new(SlotManagerImpl::new()),
123
+ }
124
+ }
125
+
126
+ /// Try to reserve a compatible processing slot in any of the registered workers.
127
+ pub(crate) fn try_reserve_wft_slot(
128
+ &self,
129
+ namespace: String,
130
+ task_queue: String,
131
+ ) -> Option<Box<dyn Slot + Send>> {
132
+ self.manager
133
+ .read()
134
+ .try_reserve_wft_slot(namespace, task_queue)
135
+ }
136
+
137
+ /// Register a local worker that can provide WFT processing slots.
138
+ pub fn register(&self, provider: Box<dyn SlotProvider + Send + Sync>) -> Option<WorkerKey> {
139
+ self.manager.write().register(provider)
140
+ }
141
+
142
+ /// Unregister a provider, typically when its worker starts shutdown.
143
+ pub fn unregister(&self, id: WorkerKey) {
144
+ self.manager.write().unregister(id)
145
+ }
146
+
147
+ #[cfg(test)]
148
+ /// Returns (num_providers, num_buckets), where a bucket key is namespace+task_queue.
149
+ /// There is only one provider per bucket so `num_providers` should be equal to `num_buckets`.
150
+ pub fn num_providers(&self) -> (usize, usize) {
151
+ self.manager.read().num_providers()
152
+ }
153
+ }
154
+
155
+ #[cfg(test)]
156
+ mod tests {
157
+ use super::*;
158
+
159
+ fn new_mock_slot(with_error: bool) -> Box<MockSlot> {
160
+ let mut mock_slot = MockSlot::new();
161
+ if with_error {
162
+ mock_slot
163
+ .expect_schedule_wft()
164
+ .returning(|_| Err(anyhow::anyhow!("Changed my mind")));
165
+ } else {
166
+ mock_slot.expect_schedule_wft().returning(|_| Ok(()));
167
+ }
168
+ Box::new(mock_slot)
169
+ }
170
+
171
+ fn new_mock_provider(
172
+ namespace: String,
173
+ task_queue: String,
174
+ with_error: bool,
175
+ no_slots: bool,
176
+ ) -> MockSlotProvider {
177
+ let mut mock_provider = MockSlotProvider::new();
178
+ mock_provider
179
+ .expect_try_reserve_wft_slot()
180
+ .returning(move || {
181
+ if no_slots {
182
+ None
183
+ } else {
184
+ Some(new_mock_slot(with_error))
185
+ }
186
+ });
187
+ mock_provider.expect_namespace().return_const(namespace);
188
+ mock_provider.expect_task_queue().return_const(task_queue);
189
+ mock_provider
190
+ }
191
+
192
+ #[test]
193
+ fn registry_respects_registration_order() {
194
+ let mock_provider1 =
195
+ new_mock_provider("foo".to_string(), "bar_q".to_string(), false, false);
196
+ let mock_provider2 = new_mock_provider("foo".to_string(), "bar_q".to_string(), false, true);
197
+
198
+ let manager = SlotManager::new();
199
+ let some_slots = manager.register(Box::new(mock_provider1));
200
+ let no_slots = manager.register(Box::new(mock_provider2));
201
+ assert!(no_slots.is_none());
202
+
203
+ let mut found = 0;
204
+ for _ in 0..10 {
205
+ if manager
206
+ .try_reserve_wft_slot("foo".to_string(), "bar_q".to_string())
207
+ .is_some()
208
+ {
209
+ found += 1;
210
+ }
211
+ }
212
+ assert_eq!(found, 10);
213
+ assert_eq!((1, 1), manager.num_providers());
214
+
215
+ manager.unregister(some_slots.unwrap());
216
+ assert_eq!((0, 0), manager.num_providers());
217
+
218
+ let mock_provider1 =
219
+ new_mock_provider("foo".to_string(), "bar_q".to_string(), false, false);
220
+ let mock_provider2 = new_mock_provider("foo".to_string(), "bar_q".to_string(), false, true);
221
+
222
+ let no_slots = manager.register(Box::new(mock_provider2));
223
+ let some_slots = manager.register(Box::new(mock_provider1));
224
+ assert!(some_slots.is_none());
225
+
226
+ let mut not_found = 0;
227
+ for _ in 0..10 {
228
+ if manager
229
+ .try_reserve_wft_slot("foo".to_string(), "bar_q".to_string())
230
+ .is_none()
231
+ {
232
+ not_found += 1;
233
+ }
234
+ }
235
+ assert_eq!(not_found, 10);
236
+ assert_eq!((1, 1), manager.num_providers());
237
+ manager.unregister(no_slots.unwrap());
238
+ assert_eq!((0, 0), manager.num_providers());
239
+ }
240
+
241
+ #[test]
242
+ fn registry_keeps_one_provider_per_namespace() {
243
+ let manager = SlotManager::new();
244
+ let mut worker_keys = vec![];
245
+ for i in 0..10 {
246
+ let namespace = format!("myId{}", i % 3);
247
+ let mock_provider = new_mock_provider(namespace, "bar_q".to_string(), false, false);
248
+ worker_keys.push(manager.register(Box::new(mock_provider)));
249
+ }
250
+ assert_eq!((3, 3), manager.num_providers());
251
+
252
+ let count = worker_keys
253
+ .iter()
254
+ .filter(|key| key.is_some())
255
+ .fold(0, |count, key| {
256
+ manager.unregister(key.unwrap());
257
+ // Should be idempotent
258
+ manager.unregister(key.unwrap());
259
+ count + 1
260
+ });
261
+ assert_eq!(3, count);
262
+ assert_eq!((0, 0), manager.num_providers());
263
+ }
264
+ }
@@ -54,6 +54,7 @@ pub struct WorkflowHandle<ClientT, ResultT> {
54
54
  }
55
55
 
56
56
  /// Holds needed information to refer to a specific workflow run, or workflow execution chain
57
+ #[derive(Debug)]
57
58
  pub struct WorkflowExecutionInfo {
58
59
  /// Namespace the workflow lives in
59
60
  pub namespace: String,
@@ -100,7 +101,7 @@ where
100
101
  let server_res = self
101
102
  .client
102
103
  .clone()
103
- .workflow_client()
104
+ .workflow_client_mut()
104
105
  .get_workflow_execution_history(GetWorkflowExecutionHistoryRequest {
105
106
  namespace: self.info.namespace.to_string(),
106
107
  execution: Some(WorkflowExecution {
@@ -28,7 +28,7 @@ async-trait = "0.1"
28
28
  base64 = "0.21"
29
29
  console-subscriber = { version = "0.1", optional = true }
30
30
  crossbeam = "0.8"
31
- dashmap = "5.0"
31
+ dashmap = "5.5"
32
32
  derive_builder = "0.12"
33
33
  derive_more = "0.99"
34
34
  enum_dispatch = "0.3"
@@ -36,18 +36,19 @@ enum-iterator = "1.4"
36
36
  flate2 = { version = "1.0", optional = true }
37
37
  futures = "0.3"
38
38
  futures-util = "0.3"
39
- governor = "0.5"
39
+ governor = "0.6"
40
40
  http = "0.2"
41
41
  hyper = "0.14"
42
- itertools = "0.10"
42
+ itertools = "0.11"
43
43
  lazy_static = "1.4"
44
- lru = "0.10"
44
+ lru = "0.11"
45
45
  mockall = "0.11"
46
- nix = { version = "0.26", optional = true }
46
+ nix = { version = "0.27", optional = true, features = ["process", "signal"] }
47
47
  once_cell = "1.5"
48
- opentelemetry = { version = "0.18", features = ["rt-tokio"] }
49
- opentelemetry-otlp = { version = "0.11", features = ["tokio", "metrics"] }
50
- opentelemetry-prometheus = "0.11"
48
+ opentelemetry = { workspace = true, features = ["metrics"] }
49
+ opentelemetry_sdk = { version = "0.21", features = ["rt-tokio", "metrics"] }
50
+ opentelemetry-otlp = { version = "0.14", features = ["tokio", "metrics"] }
51
+ opentelemetry-prometheus = "0.14"
51
52
  parking_lot = { version = "0.12", features = ["send_guard"] }
52
53
  pin-project = "1.0"
53
54
  prometheus = "0.13"
@@ -59,51 +60,48 @@ ringbuf = "0.3"
59
60
  rmp-serde = { version = "1.1", optional = true }
60
61
  serde = "1.0"
61
62
  serde_json = "1.0"
62
- siphasher = "0.3"
63
+ siphasher = "1.0"
63
64
  slotmap = "1.0"
64
65
  tar = { version = "0.4", optional = true }
65
66
  thiserror = "1.0"
66
67
  tokio = { version = "1.26", features = ["rt", "rt-multi-thread", "parking_lot", "time", "fs", "process"] }
67
68
  tokio-util = { version = "0.7", features = ["io", "io-util"] }
68
69
  tokio-stream = "0.1"
69
- tonic = { version = "0.8", features = ["tls", "tls-roots"] }
70
+ tonic = { workspace = true, features = ["tls", "tls-roots"] }
70
71
  tracing = "0.1"
71
72
  tracing-futures = "0.2"
72
- tracing-opentelemetry = "0.18"
73
73
  tracing-subscriber = { version = "0.3", features = ["parking_lot", "env-filter", "registry"] }
74
74
  url = "2.2"
75
75
  uuid = { version = "1.1", features = ["v4"] }
76
76
  zip = { version = "0.6.3", optional = true }
77
+ log = "0.4.20"
77
78
 
78
79
  # 1st party local deps
79
80
  [dependencies.temporal-sdk-core-api]
80
81
  path = "../core-api"
81
- version = "0.1"
82
+ features = ["otel_impls"]
82
83
 
83
84
  [dependencies.temporal-sdk-core-protos]
84
85
  path = "../sdk-core-protos"
85
- version = "0.1"
86
86
  features = ["history_builders"]
87
87
 
88
88
  [dependencies.temporal-client]
89
89
  path = "../client"
90
- version = "0.1"
91
90
 
92
91
  [dependencies.rustfsm]
93
92
  path = "../fsm"
94
- version = "0.1"
95
93
 
96
94
  [dev-dependencies]
97
95
  assert_matches = "1.4"
98
96
  bimap = "0.6.1"
99
97
  clap = { version = "4.0", features = ["derive"] }
100
- criterion = "0.4"
101
- rstest = "0.17"
98
+ criterion = "0.5"
99
+ rstest = "0.18"
102
100
  temporal-sdk-core-test-utils = { path = "../test-utils" }
103
101
  temporal-sdk = { path = "../sdk" }
104
102
 
105
103
  [build-dependencies]
106
- tonic-build = "0.8"
104
+ tonic-build = { workspace = true }
107
105
 
108
106
  [[test]]
109
107
  name = "integ_tests"
@@ -1,12 +1,13 @@
1
1
  use crate::{
2
2
  replay::DEFAULT_WORKFLOW_TYPE,
3
3
  test_help::{
4
- canned_histories, mock_sdk, mock_worker, single_hist_mock_sg, MockPollCfg, ResponseType,
4
+ build_fake_sdk, canned_histories, mock_sdk, mock_worker, single_hist_mock_sg, MockPollCfg,
5
+ ResponseType,
5
6
  },
6
- worker::{client::mocks::mock_workflow_client, ManagedWFFunc},
7
+ worker::client::mocks::mock_workflow_client,
7
8
  };
8
9
  use temporal_client::WorkflowOptions;
9
- use temporal_sdk::{ChildWorkflowOptions, Signal, WfContext, WorkflowFunction, WorkflowResult};
10
+ use temporal_sdk::{ChildWorkflowOptions, Signal, WfContext, WorkflowResult};
10
11
  use temporal_sdk_core_api::Worker;
11
12
  use temporal_sdk_core_protos::coresdk::{
12
13
  child_workflow::{child_workflow_result, ChildWorkflowCancellationType},
@@ -100,11 +101,10 @@ async fn parent_cancels_child_wf(ctx: WfContext) -> WorkflowResult<()> {
100
101
 
101
102
  #[tokio::test]
102
103
  async fn cancel_child_workflow() {
103
- let func = WorkflowFunction::new(parent_cancels_child_wf);
104
104
  let t = canned_histories::single_child_workflow_cancelled("child-id-1");
105
- let mut wfm = ManagedWFFunc::new(t, func, vec![]);
106
- wfm.process_all_activations().await.unwrap();
107
- wfm.shutdown().await.unwrap();
105
+ let mut worker = build_fake_sdk(MockPollCfg::from_resps(t, [ResponseType::AllHistory]));
106
+ worker.register_wf(DEFAULT_WORKFLOW_TYPE, parent_cancels_child_wf);
107
+ worker.run().await.unwrap();
108
108
  }
109
109
 
110
110
  #[rstest::rstest]
@@ -4,6 +4,7 @@ mod determinism;
4
4
  mod local_activities;
5
5
  mod queries;
6
6
  mod replay_flag;
7
+ mod updates;
7
8
  mod workers;
8
9
  mod workflow_cancels;
9
10
  mod workflow_tasks;
@@ -1,26 +1,25 @@
1
1
  use crate::{
2
2
  test_help::{
3
- build_mock_pollers, canned_histories, hist_to_poll_resp, mock_worker, MockPollCfg,
4
- ResponseType,
3
+ build_fake_sdk, build_mock_pollers, canned_histories, hist_to_poll_resp, mock_worker,
4
+ MockPollCfg, ResponseType,
5
5
  },
6
- worker::{client::mocks::mock_workflow_client, ManagedWFFunc, LEGACY_QUERY_ID},
6
+ worker::{client::mocks::mock_workflow_client, LEGACY_QUERY_ID},
7
7
  };
8
8
  use rstest::{fixture, rstest};
9
9
  use std::{collections::VecDeque, time::Duration};
10
- use temporal_sdk::{WfContext, WorkflowFunction};
11
- use temporal_sdk_core_api::Worker;
10
+ use temporal_sdk::{WfContext, Worker, WorkflowFunction};
11
+ use temporal_sdk_core_api::Worker as CoreWorker;
12
12
  use temporal_sdk_core_protos::{
13
13
  coresdk::{
14
14
  workflow_activation::{workflow_activation_job, WorkflowActivationJob},
15
15
  workflow_completion::WorkflowActivationCompletion,
16
16
  },
17
- temporal::api::{
18
- enums::v1::{CommandType, EventType},
19
- query::v1::WorkflowQuery,
20
- },
21
- TestHistoryBuilder,
17
+ temporal::api::{enums::v1::EventType, query::v1::WorkflowQuery},
18
+ TestHistoryBuilder, DEFAULT_WORKFLOW_TYPE,
19
+ };
20
+ use temporal_sdk_core_test_utils::{
21
+ interceptors::ActivationAssertionsInterceptor, query_ok, start_timer_cmd,
22
22
  };
23
- use temporal_sdk_core_test_utils::{query_ok, start_timer_cmd};
24
23
 
25
24
  fn timers_wf(num_timers: u32) -> WorkflowFunction {
26
25
  WorkflowFunction::new(move |command_sink: WfContext| async move {
@@ -32,38 +31,31 @@ fn timers_wf(num_timers: u32) -> WorkflowFunction {
32
31
  }
33
32
 
34
33
  #[fixture(num_timers = 1)]
35
- fn fire_happy_hist(num_timers: u32) -> ManagedWFFunc {
34
+ fn fire_happy_hist(num_timers: u32) -> Worker {
36
35
  let func = timers_wf(num_timers);
37
36
  // Add 1 b/c history takes # wf tasks, not timers
38
37
  let t = canned_histories::long_sequential_timers(num_timers as usize);
39
- ManagedWFFunc::new(t, func, vec![])
38
+ let mut worker = build_fake_sdk(MockPollCfg::from_resps(t, [ResponseType::AllHistory]));
39
+ worker.register_wf(DEFAULT_WORKFLOW_TYPE, func);
40
+ worker
40
41
  }
41
42
 
42
43
  #[rstest]
43
44
  #[case::one_timer(fire_happy_hist(1), 1)]
44
45
  #[case::five_timers(fire_happy_hist(5), 5)]
45
46
  #[tokio::test]
46
- async fn replay_flag_is_correct(#[case] mut wfm: ManagedWFFunc, #[case] num_timers: usize) {
47
+ async fn replay_flag_is_correct(#[case] mut worker: Worker, #[case] num_timers: usize) {
47
48
  // Verify replay flag is correct by constructing a workflow manager that already has a complete
48
49
  // history fed into it. It should always be replaying, because history is complete.
49
50
 
50
- for _ in 1..=num_timers {
51
- let act = wfm.get_next_activation().await.unwrap();
52
- assert!(act.is_replaying);
53
- let commands = wfm.get_server_commands().commands;
54
- assert_eq!(commands.len(), 1);
55
- assert_eq!(commands[0].command_type, CommandType::StartTimer as i32);
51
+ let mut aai = ActivationAssertionsInterceptor::default();
52
+
53
+ for _ in 1..=num_timers + 1 {
54
+ aai.then(|a| assert!(a.is_replaying));
56
55
  }
57
56
 
58
- let act = wfm.get_next_activation().await.unwrap();
59
- assert!(act.is_replaying);
60
- let commands = wfm.get_server_commands().commands;
61
- assert_eq!(commands.len(), 1);
62
- assert_eq!(
63
- commands[0].command_type,
64
- CommandType::CompleteWorkflowExecution as i32
65
- );
66
- wfm.shutdown().await.unwrap();
57
+ worker.set_worker_interceptor(aai);
58
+ worker.run().await.unwrap();
67
59
  }
68
60
 
69
61
  #[tokio::test(flavor = "multi_thread")]
@@ -71,15 +63,14 @@ async fn replay_flag_is_correct_partial_history() {
71
63
  let func = timers_wf(1);
72
64
  // Add 1 b/c history takes # wf tasks, not timers
73
65
  let t = canned_histories::long_sequential_timers(2);
74
- let mut wfm =
75
- ManagedWFFunc::new_from_update(t.get_history_info(1).unwrap().into(), func, vec![]);
76
-
77
- let act = wfm.get_next_activation().await.unwrap();
78
- assert!(!act.is_replaying);
79
- let commands = wfm.get_server_commands().commands;
80
- assert_eq!(commands.len(), 1);
81
- assert_eq!(commands[0].command_type, CommandType::StartTimer as i32);
82
- wfm.shutdown().await.unwrap();
66
+ let mut worker = build_fake_sdk(MockPollCfg::from_resps(t, [1]));
67
+ worker.register_wf(DEFAULT_WORKFLOW_TYPE, func);
68
+
69
+ let mut aai = ActivationAssertionsInterceptor::default();
70
+ aai.then(|a| assert!(!a.is_replaying));
71
+
72
+ worker.set_worker_interceptor(aai);
73
+ worker.run().await.unwrap();
83
74
  }
84
75
 
85
76
  #[tokio::test]
@@ -99,7 +90,6 @@ async fn replay_flag_correct_with_query() {
99
90
  let h = pr.history.as_mut().unwrap();
100
91
  h.events.truncate(5);
101
92
  pr.started_event_id = 3;
102
- dbg!(&pr.resp);
103
93
  pr
104
94
  },
105
95
  hist_to_poll_resp(&t, wfid.to_owned(), 2.into()),
@@ -0,0 +1,73 @@
1
+ use crate::test_help::{build_mock_pollers, mock_worker, MockPollCfg, ResponseType};
2
+ use temporal_sdk_core_api::Worker;
3
+ use temporal_sdk_core_protos::{
4
+ coresdk::{
5
+ workflow_activation::{workflow_activation_job, WorkflowActivationJob},
6
+ workflow_commands::{update_response::Response, CompleteWorkflowExecution, UpdateResponse},
7
+ workflow_completion::WorkflowActivationCompletion,
8
+ },
9
+ temporal::api::{common::v1::Payload, enums::v1::EventType},
10
+ TestHistoryBuilder,
11
+ };
12
+
13
+ #[tokio::test]
14
+ async fn replay_with_empty_first_task() {
15
+ let mut t = TestHistoryBuilder::default();
16
+ t.add_by_type(EventType::WorkflowExecutionStarted);
17
+ t.add_full_wf_task();
18
+ t.add_full_wf_task();
19
+ let accept_id = t.add_update_accepted("upd1", "update");
20
+ t.add_we_signaled("hi", vec![]);
21
+ t.add_full_wf_task();
22
+ t.add_update_completed(accept_id);
23
+ t.add_workflow_execution_completed();
24
+
25
+ let mock = MockPollCfg::from_resps(t, [ResponseType::AllHistory]);
26
+ let mut mock = build_mock_pollers(mock);
27
+ mock.worker_cfg(|wc| wc.max_cached_workflows = 1);
28
+ let core = mock_worker(mock);
29
+
30
+ let task = core.poll_workflow_activation().await.unwrap();
31
+ assert_matches!(
32
+ task.jobs.as_slice(),
33
+ [
34
+ WorkflowActivationJob {
35
+ variant: Some(workflow_activation_job::Variant::DoUpdate(_)),
36
+ },
37
+ WorkflowActivationJob {
38
+ variant: Some(workflow_activation_job::Variant::StartWorkflow(_)),
39
+ },
40
+ ]
41
+ );
42
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
43
+ task.run_id,
44
+ UpdateResponse {
45
+ protocol_instance_id: "upd1".to_string(),
46
+ response: Some(Response::Accepted(())),
47
+ }
48
+ .into(),
49
+ ))
50
+ .await
51
+ .unwrap();
52
+
53
+ let task = core.poll_workflow_activation().await.unwrap();
54
+ assert_matches!(
55
+ task.jobs.as_slice(),
56
+ [WorkflowActivationJob {
57
+ variant: Some(workflow_activation_job::Variant::SignalWorkflow(_)),
58
+ }]
59
+ );
60
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
61
+ task.run_id,
62
+ vec![
63
+ UpdateResponse {
64
+ protocol_instance_id: "upd1".to_string(),
65
+ response: Some(Response::Completed(Payload::default())),
66
+ }
67
+ .into(),
68
+ CompleteWorkflowExecution { result: None }.into(),
69
+ ],
70
+ ))
71
+ .await
72
+ .unwrap();
73
+ }
@@ -45,7 +45,7 @@ use temporal_sdk_core_protos::{
45
45
  default_act_sched, default_wes_attribs,
46
46
  temporal::api::{
47
47
  command::v1::command::Attributes,
48
- common::v1::{Payload, RetryPolicy},
48
+ common::v1::{Payload, RetryPolicy, WorkerVersionStamp},
49
49
  enums::v1::{EventType, WorkflowTaskFailedCause},
50
50
  failure::v1::Failure,
51
51
  history::v1::{
@@ -2807,3 +2807,54 @@ async fn use_compatible_version_flag(
2807
2807
  .await
2808
2808
  .unwrap();
2809
2809
  }
2810
+
2811
+ #[tokio::test]
2812
+ async fn sets_build_id_from_wft_complete() {
2813
+ let wfid = "fake_wf_id";
2814
+
2815
+ let mut t = TestHistoryBuilder::default();
2816
+ t.add_by_type(EventType::WorkflowExecutionStarted);
2817
+ t.add_full_wf_task();
2818
+ let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
2819
+ t.add_timer_fired(timer_started_event_id, "1".to_string());
2820
+ t.add_full_wf_task();
2821
+ t.modify_event(t.current_event_id(), |he| {
2822
+ if let history_event::Attributes::WorkflowTaskCompletedEventAttributes(a) =
2823
+ he.attributes.as_mut().unwrap()
2824
+ {
2825
+ a.worker_version = Some(WorkerVersionStamp {
2826
+ build_id: "enchi-cat".to_string(),
2827
+ ..Default::default()
2828
+ });
2829
+ }
2830
+ });
2831
+ let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
2832
+ t.add_timer_fired(timer_started_event_id, "2".to_string());
2833
+ t.add_full_wf_task();
2834
+
2835
+ let mock = mock_workflow_client();
2836
+ let mut worker = mock_sdk_cfg(
2837
+ MockPollCfg::from_resp_batches(wfid, t, [ResponseType::AllHistory], mock),
2838
+ |cfg| {
2839
+ cfg.worker_build_id = "fierce-predator".to_string();
2840
+ cfg.max_cached_workflows = 1;
2841
+ },
2842
+ );
2843
+
2844
+ worker.register_wf(DEFAULT_WORKFLOW_TYPE, |ctx: WfContext| async move {
2845
+ // First task, it should be empty, since replaying and nothing in first WFT completed
2846
+ ctx.timer(Duration::from_secs(1)).await;
2847
+ assert_eq!(ctx.current_build_id(), None);
2848
+ ctx.timer(Duration::from_secs(1)).await;
2849
+ assert_eq!(ctx.current_build_id(), Some("enchi-cat".to_string()));
2850
+ ctx.timer(Duration::from_secs(1)).await;
2851
+ // Not replaying at this point, so we should see the worker's build id
2852
+ assert_eq!(ctx.current_build_id(), Some("fierce-predator".to_string()));
2853
+ Ok(().into())
2854
+ });
2855
+ worker
2856
+ .submit_wf(wfid, DEFAULT_WORKFLOW_TYPE, vec![], Default::default())
2857
+ .await
2858
+ .unwrap();
2859
+ worker.run_until_done().await.unwrap();
2860
+ }