@temporalio/core-bridge 0.16.4 → 0.18.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 (170) hide show
  1. package/Cargo.lock +339 -226
  2. package/Cargo.toml +7 -3
  3. package/common.js +50 -0
  4. package/index.d.ts +7 -0
  5. package/index.js +12 -0
  6. package/package.json +7 -4
  7. package/releases/aarch64-apple-darwin/index.node +0 -0
  8. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  9. package/{index.node → releases/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/scripts/build.js +10 -50
  14. package/sdk-core/.buildkite/docker/Dockerfile +1 -1
  15. package/sdk-core/.buildkite/docker/docker-compose.yaml +2 -2
  16. package/sdk-core/.buildkite/pipeline.yml +2 -0
  17. package/sdk-core/Cargo.toml +1 -88
  18. package/sdk-core/README.md +30 -6
  19. package/sdk-core/bridge-ffi/Cargo.toml +24 -0
  20. package/sdk-core/bridge-ffi/LICENSE.txt +23 -0
  21. package/sdk-core/bridge-ffi/build.rs +25 -0
  22. package/sdk-core/bridge-ffi/include/sdk-core-bridge.h +216 -0
  23. package/sdk-core/bridge-ffi/src/lib.rs +829 -0
  24. package/sdk-core/bridge-ffi/src/wrappers.rs +193 -0
  25. package/sdk-core/client/Cargo.toml +32 -0
  26. package/sdk-core/{src/pollers/gateway.rs → client/src/lib.rs} +101 -195
  27. package/sdk-core/client/src/metrics.rs +89 -0
  28. package/sdk-core/client/src/mocks.rs +167 -0
  29. package/sdk-core/{src/pollers → client/src}/retry.rs +172 -14
  30. package/sdk-core/core/Cargo.toml +96 -0
  31. package/sdk-core/{src → core/src}/core_tests/activity_tasks.rs +193 -37
  32. package/sdk-core/{src → core/src}/core_tests/child_workflows.rs +14 -14
  33. package/sdk-core/{src → core/src}/core_tests/determinism.rs +8 -8
  34. package/sdk-core/core/src/core_tests/local_activities.rs +328 -0
  35. package/sdk-core/{src → core/src}/core_tests/mod.rs +6 -9
  36. package/sdk-core/{src → core/src}/core_tests/queries.rs +54 -54
  37. package/sdk-core/{src → core/src}/core_tests/replay_flag.rs +8 -12
  38. package/sdk-core/{src → core/src}/core_tests/workers.rs +120 -33
  39. package/sdk-core/{src → core/src}/core_tests/workflow_cancels.rs +16 -26
  40. package/sdk-core/{src → core/src}/core_tests/workflow_tasks.rs +280 -292
  41. package/sdk-core/core/src/lib.rs +374 -0
  42. package/sdk-core/{src → core/src}/log_export.rs +3 -27
  43. package/sdk-core/core/src/pending_activations.rs +162 -0
  44. package/sdk-core/{src → core/src}/pollers/mod.rs +4 -22
  45. package/sdk-core/{src → core/src}/pollers/poll_buffer.rs +1 -1
  46. package/sdk-core/core/src/protosext/mod.rs +396 -0
  47. package/sdk-core/core/src/replay/mod.rs +210 -0
  48. package/sdk-core/core/src/retry_logic.rs +144 -0
  49. package/sdk-core/{src → core/src}/telemetry/metrics.rs +3 -58
  50. package/sdk-core/{src → core/src}/telemetry/mod.rs +8 -8
  51. package/sdk-core/{src → core/src}/telemetry/prometheus_server.rs +0 -0
  52. package/sdk-core/{src → core/src}/test_help/mod.rs +35 -83
  53. package/sdk-core/{src → core/src}/worker/activities/activity_heartbeat_manager.rs +95 -42
  54. package/sdk-core/core/src/worker/activities/local_activities.rs +973 -0
  55. package/sdk-core/{src → core/src}/worker/activities.rs +52 -33
  56. package/sdk-core/{src → core/src}/worker/dispatcher.rs +8 -6
  57. package/sdk-core/{src → core/src}/worker/mod.rs +347 -221
  58. package/sdk-core/core/src/worker/wft_delivery.rs +81 -0
  59. package/sdk-core/{src → core/src}/workflow/bridge.rs +5 -2
  60. package/sdk-core/{src → core/src}/workflow/driven_workflow.rs +17 -7
  61. package/sdk-core/{src → core/src}/workflow/history_update.rs +33 -7
  62. package/sdk-core/{src → core/src/workflow}/machines/activity_state_machine.rs +26 -26
  63. package/sdk-core/{src → core/src/workflow}/machines/cancel_external_state_machine.rs +8 -11
  64. package/sdk-core/{src → core/src/workflow}/machines/cancel_workflow_state_machine.rs +19 -21
  65. package/sdk-core/{src → core/src/workflow}/machines/child_workflow_state_machine.rs +20 -31
  66. package/sdk-core/{src → core/src/workflow}/machines/complete_workflow_state_machine.rs +3 -5
  67. package/sdk-core/{src → core/src/workflow}/machines/continue_as_new_workflow_state_machine.rs +18 -18
  68. package/sdk-core/{src → core/src/workflow}/machines/fail_workflow_state_machine.rs +5 -6
  69. package/sdk-core/core/src/workflow/machines/local_activity_state_machine.rs +1451 -0
  70. package/sdk-core/{src → core/src/workflow}/machines/mod.rs +54 -107
  71. package/sdk-core/{src → core/src/workflow}/machines/mutable_side_effect_state_machine.rs +0 -0
  72. package/sdk-core/{src → core/src/workflow}/machines/patch_state_machine.rs +29 -30
  73. package/sdk-core/{src → core/src/workflow}/machines/side_effect_state_machine.rs +0 -0
  74. package/sdk-core/{src → core/src/workflow}/machines/signal_external_state_machine.rs +17 -19
  75. package/sdk-core/{src → core/src/workflow}/machines/timer_state_machine.rs +20 -21
  76. package/sdk-core/{src → core/src/workflow}/machines/transition_coverage.rs +5 -2
  77. package/sdk-core/{src → core/src/workflow}/machines/upsert_search_attributes_state_machine.rs +0 -0
  78. package/sdk-core/core/src/workflow/machines/workflow_machines/local_acts.rs +96 -0
  79. package/sdk-core/{src → core/src/workflow}/machines/workflow_machines.rs +357 -171
  80. package/sdk-core/{src → core/src/workflow}/machines/workflow_task_state_machine.rs +1 -1
  81. package/sdk-core/{src → core/src}/workflow/mod.rs +200 -39
  82. package/sdk-core/{src → core/src}/workflow/workflow_tasks/cache_manager.rs +0 -0
  83. package/sdk-core/{src → core/src}/workflow/workflow_tasks/concurrency_manager.rs +38 -5
  84. package/sdk-core/{src → core/src}/workflow/workflow_tasks/mod.rs +317 -103
  85. package/sdk-core/{test_utils → core-api}/Cargo.toml +10 -7
  86. package/sdk-core/{src → core-api/src}/errors.rs +42 -92
  87. package/sdk-core/core-api/src/lib.rs +158 -0
  88. package/sdk-core/{src/worker/config.rs → core-api/src/worker.rs} +18 -23
  89. package/sdk-core/etc/deps.svg +156 -0
  90. package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +5 -5
  91. package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +3 -5
  92. package/sdk-core/fsm/rustfsm_trait/src/lib.rs +7 -1
  93. package/sdk-core/histories/fail_wf_task.bin +0 -0
  94. package/sdk-core/histories/timer_workflow_history.bin +0 -0
  95. package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +44 -13
  96. package/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +19 -1
  97. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/common.proto +1 -1
  98. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +9 -0
  99. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +1 -0
  100. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/reset.proto +1 -0
  101. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +13 -0
  102. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +14 -7
  103. package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +176 -18
  104. package/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +6 -0
  105. package/sdk-core/protos/api_upstream/temporal/api/query/v1/message.proto +11 -0
  106. package/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +3 -0
  107. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +156 -7
  108. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +135 -104
  109. package/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +78 -0
  110. package/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +78 -0
  111. package/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +205 -0
  112. package/sdk-core/protos/local/temporal/sdk/core/bridge/service.proto +61 -0
  113. package/sdk-core/protos/local/{child_workflow.proto → temporal/sdk/core/child_workflow/child_workflow.proto} +1 -1
  114. package/sdk-core/protos/local/{common.proto → temporal/sdk/core/common/common.proto} +5 -3
  115. package/sdk-core/protos/local/{core_interface.proto → temporal/sdk/core/core_interface.proto} +10 -10
  116. package/sdk-core/protos/local/temporal/sdk/core/external_data/external_data.proto +30 -0
  117. package/sdk-core/protos/local/{workflow_activation.proto → temporal/sdk/core/workflow_activation/workflow_activation.proto} +35 -11
  118. package/sdk-core/protos/local/{workflow_commands.proto → temporal/sdk/core/workflow_commands/workflow_commands.proto} +55 -4
  119. package/sdk-core/protos/local/{workflow_completion.proto → temporal/sdk/core/workflow_completion/workflow_completion.proto} +3 -3
  120. package/sdk-core/sdk/Cargo.toml +32 -0
  121. package/sdk-core/{src/prototype_rust_sdk → sdk/src}/conversions.rs +0 -0
  122. package/sdk-core/sdk/src/lib.rs +699 -0
  123. package/sdk-core/sdk/src/payload_converter.rs +11 -0
  124. package/sdk-core/sdk/src/workflow_context/options.rs +180 -0
  125. package/sdk-core/{src/prototype_rust_sdk → sdk/src}/workflow_context.rs +201 -124
  126. package/sdk-core/{src/prototype_rust_sdk → sdk/src}/workflow_future.rs +63 -30
  127. package/sdk-core/sdk-core-protos/Cargo.toml +10 -0
  128. package/sdk-core/sdk-core-protos/build.rs +28 -6
  129. package/sdk-core/sdk-core-protos/src/constants.rs +7 -0
  130. package/sdk-core/{src/test_help → sdk-core-protos/src}/history_builder.rs +134 -49
  131. package/sdk-core/sdk-core-protos/src/history_info.rs +216 -0
  132. package/sdk-core/sdk-core-protos/src/lib.rs +601 -168
  133. package/sdk-core/sdk-core-protos/src/task_token.rs +38 -0
  134. package/sdk-core/sdk-core-protos/src/utilities.rs +14 -0
  135. package/sdk-core/test-utils/Cargo.toml +32 -0
  136. package/sdk-core/{src/test_help → test-utils/src}/canned_histories.rs +59 -78
  137. package/sdk-core/test-utils/src/histfetch.rs +28 -0
  138. package/sdk-core/{test_utils → test-utils}/src/lib.rs +131 -68
  139. package/sdk-core/tests/integ_tests/client_tests.rs +1 -1
  140. package/sdk-core/tests/integ_tests/heartbeat_tests.rs +11 -7
  141. package/sdk-core/tests/integ_tests/polling_tests.rs +12 -11
  142. package/sdk-core/tests/integ_tests/queries_tests.rs +82 -78
  143. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +91 -71
  144. package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +3 -4
  145. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +2 -4
  146. package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +4 -6
  147. package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +4 -6
  148. package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +3 -4
  149. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +496 -0
  150. package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +5 -8
  151. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +125 -0
  152. package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +7 -13
  153. package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +33 -5
  154. package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +12 -16
  155. package/sdk-core/tests/integ_tests/workflow_tests.rs +85 -82
  156. package/sdk-core/tests/load_tests.rs +6 -6
  157. package/sdk-core/tests/main.rs +2 -2
  158. package/src/conversions.rs +24 -21
  159. package/src/errors.rs +8 -0
  160. package/src/lib.rs +323 -211
  161. package/sdk-core/protos/local/activity_result.proto +0 -46
  162. package/sdk-core/protos/local/activity_task.proto +0 -66
  163. package/sdk-core/src/core_tests/retry.rs +0 -147
  164. package/sdk-core/src/lib.rs +0 -403
  165. package/sdk-core/src/machines/local_activity_state_machine.rs +0 -117
  166. package/sdk-core/src/pending_activations.rs +0 -249
  167. package/sdk-core/src/protosext/mod.rs +0 -160
  168. package/sdk-core/src/prototype_rust_sdk.rs +0 -412
  169. package/sdk-core/src/task_token.rs +0 -20
  170. package/sdk-core/src/test_help/history_info.rs +0 -157
@@ -1,412 +0,0 @@
1
- //! This module is a rough prototype Rust SDK. It can be used to create closures that look sort of
2
- //! like normal workflow code. It should only depend on things in the core crate that are already
3
- //! publicly exposed.
4
- //!
5
- //! Needs lots of love to be production ready but the basis is there
6
-
7
- mod conversions;
8
- mod workflow_context;
9
- mod workflow_future;
10
-
11
- pub use workflow_context::{
12
- ActivityOptions, CancellableFuture, ChildWorkflow, ChildWorkflowOptions, WfContext,
13
- };
14
-
15
- use crate::{
16
- prototype_rust_sdk::workflow_context::{ChildWfCommon, PendingChildWorkflow},
17
- Core,
18
- };
19
- use anyhow::{anyhow, bail};
20
- use futures::{future::BoxFuture, stream::FuturesUnordered, FutureExt, StreamExt};
21
- use std::{
22
- collections::HashMap,
23
- fmt::Debug,
24
- future::Future,
25
- sync::{
26
- atomic::{AtomicUsize, Ordering},
27
- Arc,
28
- },
29
- time::Duration,
30
- };
31
- use temporal_sdk_core_protos::{
32
- coresdk::{
33
- activity_result::ActivityResult,
34
- child_workflow::ChildWorkflowResult,
35
- common::{NamespacedWorkflowExecution, Payload},
36
- workflow_activation::{
37
- resolve_child_workflow_execution_start::Status as ChildWorkflowStartStatus,
38
- wf_activation_job::Variant, WfActivation, WfActivationJob,
39
- },
40
- workflow_commands::{workflow_command, ContinueAsNewWorkflowExecution},
41
- },
42
- temporal::api::failure::v1::Failure,
43
- };
44
- use tokio::{
45
- sync::{
46
- mpsc::{unbounded_channel, UnboundedSender},
47
- oneshot, watch,
48
- },
49
- task::JoinError,
50
- };
51
-
52
- /// A worker that can poll for and respond to workflow tasks by using [WorkflowFunction]s
53
- pub struct TestRustWorker {
54
- core: Arc<dyn Core>,
55
- task_queue: String,
56
- task_timeout: Option<Duration>,
57
- /// Maps run id to the driver
58
- workflows: HashMap<String, UnboundedSender<WfActivation>>,
59
- /// Maps workflow id to the function for executing workflow runs with that ID
60
- workflow_fns: HashMap<String, WorkflowFunction>,
61
- /// Number of live workflows
62
- incomplete_workflows: Arc<AtomicUsize>,
63
- /// Handles for each spawned workflow run are inserted here to be cleaned up when all runs
64
- /// are finished
65
- join_handles: FuturesUnordered<BoxFuture<'static, Result<WorkflowResult<()>, JoinError>>>,
66
- }
67
- type WfFunc = dyn Fn(WfContext) -> BoxFuture<'static, WorkflowResult<()>> + Send + Sync + 'static;
68
-
69
- impl TestRustWorker {
70
- /// Create a new rust worker
71
- pub fn new(core: Arc<dyn Core>, task_queue: String, task_timeout: Option<Duration>) -> Self {
72
- Self {
73
- core,
74
- task_queue,
75
- task_timeout,
76
- workflows: Default::default(),
77
- workflow_fns: Default::default(),
78
- incomplete_workflows: Arc::new(AtomicUsize::new(0)),
79
- join_handles: FuturesUnordered::new(),
80
- }
81
- }
82
-
83
- /// Create a workflow, asking the server to start it with the provided workflow ID and using the
84
- /// provided workflow function.
85
- ///
86
- /// Increments the expected Workflow run count.
87
- ///
88
- /// Returns the run id of the started workflow
89
- pub async fn submit_wf(
90
- &self,
91
- workflow_id: impl Into<String>,
92
- workflow_type: impl Into<String>,
93
- input: Vec<Payload>,
94
- ) -> Result<String, tonic::Status> {
95
- let res = self
96
- .core
97
- .server_gateway()
98
- .start_workflow(
99
- input,
100
- self.task_queue.clone(),
101
- workflow_id.into(),
102
- workflow_type.into(),
103
- self.task_timeout,
104
- )
105
- .await?;
106
-
107
- self.incr_expected_run_count(1);
108
- Ok(res.run_id)
109
- }
110
-
111
- /// Register a Workflow function to invoke when Worker is requested to run `workflow_type`
112
- pub fn register_wf<F: Into<WorkflowFunction>>(
113
- &mut self,
114
- workflow_type: impl Into<String>,
115
- wf_function: F,
116
- ) {
117
- self.workflow_fns
118
- .insert(workflow_type.into(), wf_function.into());
119
- }
120
-
121
- /// Increment the expected Workflow run count on this Worker. The Worker tracks the run count
122
- /// and will resolve `run_until_done` when it goes down to 0.
123
- /// You do not have to increment if scheduled a Workflow with `submit_wf`.
124
- pub fn incr_expected_run_count(&self, count: usize) {
125
- self.incomplete_workflows.fetch_add(count, Ordering::SeqCst);
126
- }
127
-
128
- /// Drives all workflows until they have all finished, repeatedly polls server to fetch work
129
- /// for them.
130
- pub async fn run_until_done(mut self) -> Result<(), anyhow::Error> {
131
- let (shutdown_tx, shutdown_rx) = watch::channel(false);
132
- let poller = async move {
133
- let (completions_tx, mut completions_rx) = unbounded_channel();
134
- loop {
135
- let activation = self.core.poll_workflow_activation(&self.task_queue).await?;
136
-
137
- // If the activation is to start a workflow, create a new workflow driver for it,
138
- // using the function associated with that workflow id
139
- if let Some(WfActivationJob {
140
- variant: Some(Variant::StartWorkflow(sw)),
141
- }) = activation.jobs.get(0)
142
- {
143
- let wf_function = self
144
- .workflow_fns
145
- .get(&sw.workflow_type)
146
- .ok_or_else(|| anyhow!("Workflow type not found"))?;
147
-
148
- let (wff, activations) = wf_function.start_workflow(
149
- self.core.get_init_options().gateway_opts.namespace.clone(),
150
- self.task_queue.clone(),
151
- // NOTE: Don't clone args if this gets ported to be a non-test rust worker
152
- sw.arguments.clone(),
153
- completions_tx.clone(),
154
- );
155
- let mut shutdown_rx = shutdown_rx.clone();
156
- let jh = tokio::spawn(async move {
157
- tokio::select! {
158
- r = wff => r,
159
- _ = shutdown_rx.changed() => Ok(WfExitValue::Evicted)
160
- }
161
- });
162
- self.workflows
163
- .insert(activation.run_id.clone(), activations);
164
- self.join_handles.push(jh.boxed());
165
- }
166
-
167
- // The activation is expected to apply to some workflow we know about. Use it to
168
- // unblock things and advance the workflow.
169
- if let Some(tx) = self.workflows.get_mut(&activation.run_id) {
170
- tx.send(activation)
171
- .expect("Workflow should exist if we're sending it an activation");
172
- } else {
173
- bail!("Got activation for unknown workflow");
174
- };
175
-
176
- let completion = completions_rx.recv().await.expect("No workflows left?");
177
- if completion.has_execution_ending() {
178
- debug!("Workflow {} says it's finishing", &completion.run_id);
179
- self.incomplete_workflows.fetch_sub(1, Ordering::SeqCst);
180
- }
181
- self.core.complete_workflow_activation(completion).await?;
182
- if self.incomplete_workflows.load(Ordering::SeqCst) == 0 {
183
- break Ok(self);
184
- }
185
- }
186
- };
187
-
188
- let mut myself = poller.await?;
189
-
190
- // Die rebel scum
191
- let _ = shutdown_tx.send(true);
192
- while let Some(h) = myself.join_handles.next().await {
193
- h??;
194
- }
195
- Ok(())
196
- }
197
- }
198
-
199
- #[derive(Debug)]
200
- enum UnblockEvent {
201
- Timer(u32),
202
- Activity(u32, Box<ActivityResult>),
203
- WorkflowStart(u32, Box<ChildWorkflowStartStatus>),
204
- WorkflowComplete(u32, Box<ChildWorkflowResult>),
205
- SignalExternal(u32, Option<Failure>),
206
- CancelExternal(u32, Option<Failure>),
207
- }
208
-
209
- /// Result of awaiting on a timer
210
- pub struct TimerResult;
211
-
212
- /// Successful result of sending a signal to an external workflow
213
- pub struct SignalExternalOk;
214
- /// Result of awaiting on sending a signal to an external workflow
215
- pub type SignalExternalWfResult = Result<SignalExternalOk, Failure>;
216
-
217
- /// Successful result of sending a cancel request to an external workflow
218
- pub struct CancelExternalOk;
219
- /// Result of awaiting on sending a cancel request to an external workflow
220
- pub type CancelExternalWfResult = Result<CancelExternalOk, Failure>;
221
-
222
- trait Unblockable {
223
- type OtherDat;
224
-
225
- fn unblock(ue: UnblockEvent, od: Self::OtherDat) -> Self;
226
- }
227
-
228
- impl Unblockable for TimerResult {
229
- type OtherDat = ();
230
- fn unblock(ue: UnblockEvent, _: Self::OtherDat) -> Self {
231
- match ue {
232
- UnblockEvent::Timer(_) => TimerResult,
233
- _ => panic!("Invalid unblock event for timer"),
234
- }
235
- }
236
- }
237
-
238
- impl Unblockable for ActivityResult {
239
- type OtherDat = ();
240
- fn unblock(ue: UnblockEvent, _: Self::OtherDat) -> Self {
241
- match ue {
242
- UnblockEvent::Activity(_, result) => *result,
243
- _ => panic!("Invalid unblock event for activity"),
244
- }
245
- }
246
- }
247
-
248
- impl Unblockable for PendingChildWorkflow {
249
- // Other data here is workflow id
250
- type OtherDat = ChildWfCommon;
251
- fn unblock(ue: UnblockEvent, od: Self::OtherDat) -> Self {
252
- match ue {
253
- UnblockEvent::WorkflowStart(_, result) => Self {
254
- status: *result,
255
- common: od,
256
- },
257
- _ => panic!("Invalid unblock event for child workflow start"),
258
- }
259
- }
260
- }
261
-
262
- impl Unblockable for ChildWorkflowResult {
263
- type OtherDat = ();
264
- fn unblock(ue: UnblockEvent, _: Self::OtherDat) -> Self {
265
- match ue {
266
- UnblockEvent::WorkflowComplete(_, result) => *result,
267
- _ => panic!("Invalid unblock event for child workflow complete"),
268
- }
269
- }
270
- }
271
-
272
- impl Unblockable for SignalExternalWfResult {
273
- type OtherDat = ();
274
- fn unblock(ue: UnblockEvent, _: Self::OtherDat) -> Self {
275
- match ue {
276
- UnblockEvent::SignalExternal(_, maybefail) => {
277
- maybefail.map_or(Ok(SignalExternalOk), Err)
278
- }
279
- _ => panic!("Invalid unblock event for signal external workflow result"),
280
- }
281
- }
282
- }
283
-
284
- impl Unblockable for CancelExternalWfResult {
285
- type OtherDat = ();
286
- fn unblock(ue: UnblockEvent, _: Self::OtherDat) -> Self {
287
- match ue {
288
- UnblockEvent::CancelExternal(_, maybefail) => {
289
- maybefail.map_or(Ok(CancelExternalOk), Err)
290
- }
291
- _ => panic!("Invalid unblock event for signal external workflow result"),
292
- }
293
- }
294
- }
295
-
296
- /// Identifier for cancellable operations
297
- #[derive(Debug, Clone)]
298
- pub enum CancellableID {
299
- /// Timer sequence number
300
- Timer(u32),
301
- /// Activity sequence number
302
- Activity(u32),
303
- /// Start child sequence number
304
- ChildWorkflow(u32),
305
- /// Signal workflow
306
- SignalExternalWorkflow(u32),
307
- /// An external workflow identifier as may have been created by a started child workflow
308
- ExternalWorkflow {
309
- /// Sequence number which will be used for the cancel command
310
- seqnum: u32,
311
- /// Identifying information about the workflow to be cancelled
312
- execution: NamespacedWorkflowExecution,
313
- /// Set to true if this workflow is a child of the issuing workflow
314
- only_child: bool,
315
- },
316
- }
317
-
318
- #[derive(derive_more::From)]
319
- #[allow(clippy::large_enum_variant)]
320
- enum RustWfCmd {
321
- #[from(ignore)]
322
- Cancel(CancellableID),
323
- ForceWFTFailure(anyhow::Error),
324
- NewCmd(CommandCreateRequest),
325
- NewNonblockingCmd(workflow_command::Variant),
326
- SubscribeChildWorkflowCompletion(CommandSubscribeChildWorkflowCompletion),
327
- SubscribeSignal(String, UnboundedSender<Vec<Payload>>),
328
- }
329
-
330
- struct CommandCreateRequest {
331
- cmd: workflow_command::Variant,
332
- unblocker: oneshot::Sender<UnblockEvent>,
333
- }
334
-
335
- struct CommandSubscribeChildWorkflowCompletion {
336
- seq: u32,
337
- unblocker: oneshot::Sender<UnblockEvent>,
338
- }
339
-
340
- /// The user's async function / workflow code
341
- pub struct WorkflowFunction {
342
- wf_func: Box<WfFunc>,
343
- }
344
-
345
- impl<F, Fut> From<F> for WorkflowFunction
346
- where
347
- F: Fn(WfContext) -> Fut + Send + Sync + 'static,
348
- Fut: Future<Output = WorkflowResult<()>> + Send + 'static,
349
- {
350
- fn from(wf_func: F) -> Self {
351
- Self::new(wf_func)
352
- }
353
- }
354
-
355
- impl WorkflowFunction {
356
- /// Build a workflow function from a closure or function pointer which accepts a [WfContext]
357
- pub fn new<F, Fut>(wf_func: F) -> Self
358
- where
359
- F: Fn(WfContext) -> Fut + Send + Sync + 'static,
360
- Fut: Future<Output = WorkflowResult<()>> + Send + 'static,
361
- {
362
- Self {
363
- wf_func: Box::new(move |ctx: WfContext| wf_func(ctx).boxed()),
364
- }
365
- }
366
- }
367
-
368
- /// The result of running a workflow
369
- pub type WorkflowResult<T> = Result<WfExitValue<T>, anyhow::Error>;
370
-
371
- /// Workflow functions may return these values when exiting
372
- #[derive(Debug, derive_more::From)]
373
- pub enum WfExitValue<T: Debug> {
374
- /// Continue the workflow as a new execution
375
- #[from(ignore)]
376
- ContinueAsNew(ContinueAsNewWorkflowExecution),
377
- /// Confirm the workflow was cancelled (can be automatic in a more advanced iteration)
378
- #[from(ignore)]
379
- Cancelled,
380
- /// The run was evicted
381
- #[from(ignore)]
382
- Evicted,
383
- /// Finish with a result
384
- Normal(T),
385
- }
386
-
387
- #[cfg(test)]
388
- mod tests {
389
- use super::*;
390
- use crate::test_help::{build_fake_core, canned_histories, DEFAULT_WORKFLOW_TYPE, TEST_Q};
391
-
392
- pub async fn timer_wf(mut ctx: WfContext) -> WorkflowResult<()> {
393
- ctx.timer(Duration::from_secs(1)).await;
394
- Ok(().into())
395
- }
396
-
397
- #[tokio::test]
398
- async fn new_test_wf_core() {
399
- let wf_id = "fakeid";
400
- let wf_type = DEFAULT_WORKFLOW_TYPE;
401
- let t = canned_histories::single_timer("1");
402
- let core = build_fake_core(wf_id, t, [2]);
403
- let mut worker = TestRustWorker::new(Arc::new(core), TEST_Q.to_string(), None);
404
-
405
- worker.register_wf(wf_type.to_owned(), timer_wf);
406
- worker
407
- .submit_wf(wf_id.to_owned(), wf_type.to_owned(), vec![])
408
- .await
409
- .unwrap();
410
- worker.run_until_done().await.unwrap();
411
- }
412
- }
@@ -1,20 +0,0 @@
1
- use std::fmt::{Debug, Display, Formatter};
2
-
3
- #[derive(Hash, Eq, PartialEq, Clone, derive_more::From, derive_more::Into)]
4
- pub struct TaskToken(pub Vec<u8>);
5
-
6
- impl Display for TaskToken {
7
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
8
- f.write_str(&fmt_tt(&self.0))
9
- }
10
- }
11
-
12
- impl Debug for TaskToken {
13
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
14
- f.write_str(&format!("TaskToken({})", fmt_tt(&self.0)))
15
- }
16
- }
17
-
18
- pub fn fmt_tt(tt: &[u8]) -> String {
19
- base64::encode(tt)
20
- }
@@ -1,157 +0,0 @@
1
- use crate::workflow::HistoryUpdate;
2
- use temporal_sdk_core_protos::temporal::api::{
3
- enums::v1::EventType,
4
- history::v1::{History, HistoryEvent},
5
- };
6
-
7
- #[derive(Clone, Debug, PartialEq)]
8
- pub(crate) struct HistoryInfo {
9
- pub previous_started_event_id: i64,
10
- pub workflow_task_started_event_id: i64,
11
- // This needs to stay private so the struct can't be instantiated outside of the constructor,
12
- // which enforces some invariants regarding history structure that need to be upheld.
13
- events: Vec<HistoryEvent>,
14
- wf_task_count: usize,
15
- }
16
-
17
- type Result<T, E = HistoryInfoError> = std::result::Result<T, E>;
18
-
19
- #[derive(thiserror::Error, Debug)]
20
- #[allow(clippy::large_enum_variant)]
21
- pub enum HistoryInfoError {
22
- #[error("Latest wf started id and previous one are equal! ${previous_started_event_id:?}")]
23
- UnexpectedEventId {
24
- previous_started_event_id: i64,
25
- workflow_task_started_event_id: i64,
26
- },
27
- #[error("Invalid history! Event {0:?} should be WF task completed, failed, or timed out")]
28
- FailedOrTimeout(HistoryEvent),
29
- #[error("Last item in history wasn't WorkflowTaskStarted")]
30
- HistoryEndsUnexpectedly,
31
- }
32
-
33
- impl HistoryInfo {
34
- /// Constructs a new instance, retaining only enough events to reach the provided workflow
35
- /// task number. If not provided, all events are retained.
36
- pub(crate) fn new_from_history(h: &History, to_wf_task_num: Option<usize>) -> Result<Self> {
37
- let events = &h.events;
38
- if events.is_empty() {
39
- return Err(HistoryInfoError::HistoryEndsUnexpectedly);
40
- }
41
-
42
- let to_wf_task_num = to_wf_task_num.unwrap_or(usize::MAX);
43
- let mut workflow_task_started_event_id = 0;
44
- let mut previous_started_event_id = 0;
45
- let mut wf_task_count = 0;
46
- let mut history = events.iter().peekable();
47
- let mut events = vec![];
48
-
49
- while let Some(event) = history.next() {
50
- events.push(event.clone());
51
- let next_event = history.peek();
52
-
53
- if event.event_type == EventType::WorkflowTaskStarted as i32 {
54
- let next_is_completed = next_event.map_or(false, |ne| {
55
- ne.event_type == EventType::WorkflowTaskCompleted as i32
56
- });
57
- let next_is_failed_or_timeout = next_event.map_or(false, |ne| {
58
- ne.event_type == EventType::WorkflowTaskFailed as i32
59
- || ne.event_type == EventType::WorkflowTaskTimedOut as i32
60
- });
61
-
62
- if next_event.is_none() || next_is_completed {
63
- previous_started_event_id = workflow_task_started_event_id;
64
- workflow_task_started_event_id = event.event_id;
65
- if workflow_task_started_event_id == previous_started_event_id {
66
- return Err(HistoryInfoError::UnexpectedEventId {
67
- previous_started_event_id,
68
- workflow_task_started_event_id,
69
- });
70
- }
71
- wf_task_count += 1;
72
- if wf_task_count == to_wf_task_num || next_event.is_none() {
73
- return Ok(Self {
74
- previous_started_event_id,
75
- workflow_task_started_event_id,
76
- events,
77
- wf_task_count,
78
- });
79
- }
80
- } else if next_event.is_some() && !next_is_failed_or_timeout {
81
- return Err(HistoryInfoError::FailedOrTimeout(event.clone()));
82
- }
83
- }
84
-
85
- if next_event.is_none() {
86
- if event.is_final_wf_execution_event() {
87
- return Ok(Self {
88
- previous_started_event_id,
89
- workflow_task_started_event_id,
90
- events,
91
- wf_task_count,
92
- });
93
- }
94
- // No more events
95
- if workflow_task_started_event_id != event.event_id {
96
- return Err(HistoryInfoError::HistoryEndsUnexpectedly);
97
- }
98
- }
99
- }
100
- unreachable!()
101
- }
102
-
103
- /// Remove events from the beginning of this history such that it looks like what would've been
104
- /// delivered on a sticky queue where the previously started task was the one before the last
105
- /// task in this history.
106
- pub(crate) fn make_incremental(&mut self) {
107
- let last_complete_ix = self
108
- .events
109
- .iter()
110
- .rposition(|he| he.event_type() == EventType::WorkflowTaskCompleted)
111
- .expect("Must be a WFT completed event in history");
112
- self.events.drain(0..=last_complete_ix);
113
- }
114
-
115
- pub(crate) fn events(&self) -> &[HistoryEvent] {
116
- &self.events
117
- }
118
-
119
- /// Non-test code should *not* rely on just counting workflow tasks b/c of pagination
120
- pub(crate) const fn wf_task_count(&self) -> usize {
121
- self.wf_task_count
122
- }
123
- }
124
-
125
- impl From<HistoryInfo> for HistoryUpdate {
126
- fn from(v: HistoryInfo) -> Self {
127
- Self::new_from_events(v.events, v.previous_started_event_id)
128
- }
129
- }
130
-
131
- impl From<HistoryInfo> for History {
132
- fn from(i: HistoryInfo) -> Self {
133
- Self { events: i.events }
134
- }
135
- }
136
-
137
- #[cfg(test)]
138
- mod tests {
139
- use crate::test_help::canned_histories;
140
-
141
- #[test]
142
- fn history_info_constructs_properly() {
143
- let t = canned_histories::single_timer("timer1");
144
-
145
- let history_info = t.get_history_info(1).unwrap();
146
- assert_eq!(3, history_info.events.len());
147
- let history_info = t.get_history_info(2).unwrap();
148
- assert_eq!(8, history_info.events.len());
149
- }
150
-
151
- #[test]
152
- fn incremental_works() {
153
- let t = canned_histories::single_timer("timer1");
154
- let hi = t.get_one_wft(2).unwrap();
155
- dbg!(hi.events);
156
- }
157
- }