@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,25 +1,37 @@
1
- use crate::prototype_rust_sdk::{
2
- CancelExternalWfResult, CancellableID, CommandCreateRequest,
3
- CommandSubscribeChildWorkflowCompletion, RustWfCmd, SignalExternalWfResult, TimerResult,
4
- UnblockEvent, Unblockable,
1
+ mod options;
2
+
3
+ pub use options::{ActivityOptions, ChildWorkflowOptions, LocalActivityOptions};
4
+
5
+ use crate::{
6
+ workflow_context::options::IntoWorkflowCommand, CancelExternalWfResult, CancellableID,
7
+ CommandCreateRequest, CommandSubscribeChildWorkflowCompletion, RustWfCmd,
8
+ SignalExternalWfResult, TimerResult, UnblockEvent, Unblockable,
5
9
  };
6
10
  use crossbeam::channel::{Receiver, Sender};
7
11
  use futures::{task::Context, FutureExt, Stream};
8
12
  use parking_lot::RwLock;
9
13
  use std::{
10
- collections::HashMap, future::Future, marker::PhantomData, pin::Pin, sync::Arc, task::Poll,
11
- time::Duration,
14
+ collections::HashMap,
15
+ future::Future,
16
+ marker::PhantomData,
17
+ pin::Pin,
18
+ sync::{
19
+ atomic::{AtomicBool, Ordering},
20
+ Arc,
21
+ },
22
+ task::Poll,
23
+ time::{Duration, SystemTime},
12
24
  };
13
25
  use temporal_sdk_core_protos::coresdk::{
14
- activity_result::ActivityResult,
15
- child_workflow::{ChildWorkflowCancellationType, ChildWorkflowResult},
26
+ activity_result::{activity_resolution, ActivityResolution},
27
+ child_workflow::ChildWorkflowResult,
16
28
  common::{NamespacedWorkflowExecution, Payload},
17
29
  workflow_activation::resolve_child_workflow_execution_start::Status as ChildWorkflowStartStatus,
18
30
  workflow_commands::{
19
31
  request_cancel_external_workflow_execution as cancel_we,
20
- signal_external_workflow_execution as sig_we, workflow_command, ActivityCancellationType,
21
- RequestCancelExternalWorkflowExecution, ScheduleActivity, SetPatchMarker,
22
- SignalExternalWorkflowExecution, StartChildWorkflowExecution, StartTimer,
32
+ signal_external_workflow_execution as sig_we, workflow_command,
33
+ RequestCancelExternalWorkflowExecution, SetPatchMarker, SignalExternalWorkflowExecution,
34
+ StartTimer,
23
35
  },
24
36
  };
25
37
  use tokio::sync::{mpsc, oneshot, watch};
@@ -28,12 +40,17 @@ use tokio_stream::wrappers::UnboundedReceiverStream;
28
40
  /// Used within workflows to issue commands, get info, etc.
29
41
  pub struct WfContext {
30
42
  namespace: String,
43
+ task_queue: String,
31
44
  args: Vec<Payload>,
32
45
 
33
46
  chan: Sender<RustWfCmd>,
34
47
  am_cancelled: watch::Receiver<bool>,
35
48
  shared: Arc<RwLock<WfContextSharedData>>,
36
49
 
50
+ seq_nums: RwLock<WfCtxProtectedDat>,
51
+ }
52
+
53
+ struct WfCtxProtectedDat {
37
54
  next_timer_sequence_number: u32,
38
55
  next_activity_sequence_number: u32,
39
56
  next_child_workflow_sequence_number: u32,
@@ -41,11 +58,40 @@ pub struct WfContext {
41
58
  next_signal_external_wf_sequence_number: u32,
42
59
  }
43
60
 
61
+ impl WfCtxProtectedDat {
62
+ fn next_timer_seq(&mut self) -> u32 {
63
+ let seq = self.next_timer_sequence_number;
64
+ self.next_timer_sequence_number += 1;
65
+ seq
66
+ }
67
+ fn next_activity_seq(&mut self) -> u32 {
68
+ let seq = self.next_activity_sequence_number;
69
+ self.next_activity_sequence_number += 1;
70
+ seq
71
+ }
72
+ fn next_child_workflow_seq(&mut self) -> u32 {
73
+ let seq = self.next_child_workflow_sequence_number;
74
+ self.next_child_workflow_sequence_number += 1;
75
+ seq
76
+ }
77
+ fn next_cancel_external_wf_seq(&mut self) -> u32 {
78
+ let seq = self.next_cancel_external_wf_sequence_number;
79
+ self.next_cancel_external_wf_sequence_number += 1;
80
+ seq
81
+ }
82
+ fn next_signal_external_wf_seq(&mut self) -> u32 {
83
+ let seq = self.next_signal_external_wf_sequence_number;
84
+ self.next_signal_external_wf_sequence_number += 1;
85
+ seq
86
+ }
87
+ }
88
+
44
89
  #[derive(Clone, Debug, Default)]
45
90
  pub struct WfContextSharedData {
46
91
  /// Maps change ids -> resolved status
47
92
  pub changes: HashMap<String, bool>,
48
93
  pub is_replaying: bool,
94
+ pub wf_time: Option<SystemTime>,
49
95
  }
50
96
 
51
97
  // TODO: Dataconverter type interface to replace Payloads here. Possibly just use serde
@@ -55,6 +101,7 @@ impl WfContext {
55
101
  /// sent from the workflow.
56
102
  pub(super) fn new(
57
103
  namespace: String,
104
+ task_queue: String,
58
105
  args: Vec<Payload>,
59
106
  am_cancelled: watch::Receiver<bool>,
60
107
  ) -> (Self, Receiver<RustWfCmd>) {
@@ -63,15 +110,18 @@ impl WfContext {
63
110
  (
64
111
  Self {
65
112
  namespace,
113
+ task_queue,
66
114
  args,
67
115
  chan,
68
116
  am_cancelled,
69
117
  shared: Arc::new(RwLock::new(Default::default())),
70
- next_timer_sequence_number: 1,
71
- next_activity_sequence_number: 1,
72
- next_child_workflow_sequence_number: 1,
73
- next_cancel_external_wf_sequence_number: 1,
74
- next_signal_external_wf_sequence_number: 1,
118
+ seq_nums: RwLock::new(WfCtxProtectedDat {
119
+ next_timer_sequence_number: 1,
120
+ next_activity_sequence_number: 1,
121
+ next_child_workflow_sequence_number: 1,
122
+ next_cancel_external_wf_sequence_number: 1,
123
+ next_signal_external_wf_sequence_number: 1,
124
+ }),
75
125
  },
76
126
  rx,
77
127
  )
@@ -87,6 +137,11 @@ impl WfContext {
87
137
  self.args.as_slice()
88
138
  }
89
139
 
140
+ /// Return the current time according to the workflow (which is not wall-clock time).
141
+ pub fn workflow_time(&self) -> Option<SystemTime> {
142
+ self.shared.read().wf_time
143
+ }
144
+
90
145
  pub(crate) fn get_shared_data(&self) -> Arc<RwLock<WfContextSharedData>> {
91
146
  self.shared.clone()
92
147
  }
@@ -103,9 +158,8 @@ impl WfContext {
103
158
  }
104
159
 
105
160
  /// Request to create a timer
106
- pub fn timer(&mut self, duration: Duration) -> impl CancellableFuture<TimerResult> {
107
- let seq = self.next_timer_sequence_number;
108
- self.next_timer_sequence_number += 1;
161
+ pub fn timer(&self, duration: Duration) -> impl CancellableFuture<TimerResult> {
162
+ let seq = self.seq_nums.write().next_timer_seq();
109
163
  let (cmd, unblocker) = CancellableWFCommandFut::new(CancellableID::Timer(seq));
110
164
  self.send(
111
165
  CommandCreateRequest {
@@ -122,13 +176,18 @@ impl WfContext {
122
176
  }
123
177
 
124
178
  /// Request to run an activity
125
- pub fn activity(&mut self, opts: ActivityOptions) -> impl CancellableFuture<ActivityResult> {
126
- let seq = self.next_activity_sequence_number;
127
- self.next_activity_sequence_number += 1;
179
+ pub fn activity(
180
+ &self,
181
+ mut opts: ActivityOptions,
182
+ ) -> impl CancellableFuture<ActivityResolution> {
183
+ if opts.task_queue.is_empty() {
184
+ opts.task_queue = self.task_queue.clone()
185
+ }
186
+ let seq = self.seq_nums.write().next_activity_seq();
128
187
  let (cmd, unblocker) = CancellableWFCommandFut::new(CancellableID::Activity(seq));
129
188
  self.send(
130
189
  CommandCreateRequest {
131
- cmd: opts.to_command(seq).into(),
190
+ cmd: opts.into_command(seq).into(),
132
191
  unblocker,
133
192
  }
134
193
  .into(),
@@ -136,8 +195,33 @@ impl WfContext {
136
195
  cmd
137
196
  }
138
197
 
139
- /// Request to start a child workflow, Returned future resolves when the child has been started.
140
- pub fn child_workflow(&mut self, opts: ChildWorkflowOptions) -> ChildWorkflow {
198
+ /// Request to run a local activity
199
+ pub fn local_activity(
200
+ &self,
201
+ opts: LocalActivityOptions,
202
+ ) -> impl CancellableFuture<ActivityResolution> + '_ {
203
+ LATimerBackoffFut::new(opts, self)
204
+ }
205
+
206
+ /// Request to run a local activity with no implementation of timer-backoff based retrying.
207
+ fn local_activity_no_timer_retry(
208
+ &self,
209
+ opts: LocalActivityOptions,
210
+ ) -> impl CancellableFuture<ActivityResolution> {
211
+ let seq = self.seq_nums.write().next_activity_seq();
212
+ let (cmd, unblocker) = CancellableWFCommandFut::new(CancellableID::LocalActivity(seq));
213
+ self.send(
214
+ CommandCreateRequest {
215
+ cmd: opts.into_command(seq).into(),
216
+ unblocker,
217
+ }
218
+ .into(),
219
+ );
220
+ cmd
221
+ }
222
+
223
+ /// Creates a child workflow stub with the provided options
224
+ pub fn child_workflow(&self, opts: ChildWorkflowOptions) -> ChildWorkflow {
141
225
  ChildWorkflow { opts }
142
226
  }
143
227
 
@@ -180,7 +264,7 @@ impl WfContext {
180
264
  /// Send a signal to an external workflow. May resolve as a failure if the signal didn't work
181
265
  /// or was cancelled.
182
266
  pub fn signal_workflow(
183
- &mut self,
267
+ &self,
184
268
  workflow_id: impl Into<String>,
185
269
  run_id: impl Into<String>,
186
270
  signal_name: impl Into<String>,
@@ -196,7 +280,7 @@ impl WfContext {
196
280
 
197
281
  /// Return a stream that produces values when the named signal is sent to this workflow
198
282
  pub fn make_signal_channel(
199
- &mut self,
283
+ &self,
200
284
  signal_name: impl Into<String>,
201
285
  ) -> impl Stream<Item = Vec<Payload>> {
202
286
  let (tx, rx) = mpsc::unbounded_channel();
@@ -211,14 +295,12 @@ impl WfContext {
211
295
 
212
296
  /// Request the cancellation of an external workflow. May resolve as a failure if the workflow
213
297
  /// was not found or the cancel was otherwise unsendable.
214
- /// TODO: Own result type
215
298
  pub fn cancel_external(
216
- &mut self,
299
+ &self,
217
300
  target: NamespacedWorkflowExecution,
218
301
  ) -> impl Future<Output = CancelExternalWfResult> {
219
302
  let target = cancel_we::Target::WorkflowExecution(target);
220
- let seq = self.next_cancel_external_wf_sequence_number;
221
- self.next_cancel_external_wf_sequence_number += 1;
303
+ let seq = self.seq_nums.write().next_cancel_external_wf_seq();
222
304
  let (cmd, unblocker) = WFCommandFut::new();
223
305
  self.send(
224
306
  CommandCreateRequest {
@@ -235,13 +317,12 @@ impl WfContext {
235
317
  }
236
318
 
237
319
  fn send_signal_wf(
238
- &mut self,
320
+ &self,
239
321
  signal_name: impl Into<String>,
240
322
  payload: impl Into<Payload>,
241
323
  target: sig_we::Target,
242
324
  ) -> impl CancellableFuture<SignalExternalWfResult> {
243
- let seq = self.next_signal_external_wf_sequence_number;
244
- self.next_signal_external_wf_sequence_number += 1;
325
+ let seq = self.seq_nums.write().next_signal_external_wf_seq();
245
326
  let (cmd, unblocker) =
246
327
  CancellableWFCommandFut::new(CancellableID::SignalExternalWorkflow(seq));
247
328
  self.send(
@@ -261,7 +342,7 @@ impl WfContext {
261
342
  }
262
343
 
263
344
  /// Cancel any cancellable operation by ID
264
- fn cancel(&mut self, cancellable_id: CancellableID) {
345
+ fn cancel(&self, cancellable_id: CancellableID) {
265
346
  self.send(RustWfCmd::Cancel(cancellable_id));
266
347
  }
267
348
 
@@ -274,7 +355,7 @@ impl WfContext {
274
355
  /// Used in the prototype SDK for cancelling operations like timers and activities.
275
356
  pub trait CancellableFuture<T>: Future<Output = T> {
276
357
  /// Cancel this Future
277
- fn cancel(&self, cx: &mut WfContext);
358
+ fn cancel(&self, cx: &WfContext);
278
359
  }
279
360
 
280
361
  struct WFCommandFut<T, D> {
@@ -362,98 +443,96 @@ impl<T, D> CancellableFuture<T> for CancellableWFCommandFut<T, D>
362
443
  where
363
444
  T: Unblockable<OtherDat = D>,
364
445
  {
365
- fn cancel(&self, cx: &mut WfContext) {
446
+ fn cancel(&self, cx: &WfContext) {
366
447
  cx.cancel(self.cancellable_id.clone());
367
448
  }
368
449
  }
369
450
 
370
- /// Options for scheduling an activity
371
- #[derive(Default, Debug)]
372
- pub struct ActivityOptions {
373
- /// Identifier to use for tracking the activity in Workflow history.
374
- /// The `activityId` can be accessed by the activity function.
375
- /// Does not need to be unique.
376
- ///
377
- /// If `None` use the context's sequence number
378
- pub activity_id: Option<String>,
379
- /// Type of activity to schedule
380
- pub activity_type: String,
381
- /// Task queue to schedule the activity in
382
- pub task_queue: String,
383
- /// Time that the Activity Task can stay in the Task Queue before it is picked up by a Worker.
384
- /// Do not specify this timeout unless using host specific Task Queues for Activity Tasks are
385
- /// being used for routing.
386
- /// `schedule_to_start_timeout` is always non-retryable.
387
- /// Retrying after this timeout doesn't make sense as it would just put the Activity Task back
388
- /// into the same Task Queue.
389
- pub schedule_to_start_timeout: Option<Duration>,
390
- /// Maximum time of a single Activity execution attempt.
391
- /// Note that the Temporal Server doesn't detect Worker process failures directly.
392
- /// It relies on this timeout to detect that an Activity that didn't complete on time.
393
- /// So this timeout should be as short as the longest possible execution of the Activity body.
394
- /// Potentially long running Activities must specify `heartbeat_timeout` and heartbeat from the
395
- /// activity periodically for timely failure detection.
396
- /// Either this option or `schedule_to_close_timeout` is required.
397
- pub start_to_close_timeout: Option<Duration>,
398
- /// Total time that a workflow is willing to wait for Activity to complete.
399
- /// `schedule_to_close_timeout` limits the total time of an Activity's execution including
400
- /// retries (use `start_to_close_timeout` to limit the time of a single attempt).
401
- /// Either this option or `start_to_close_timeout` is required.
402
- pub schedule_to_close_timeout: Option<Duration>,
403
- /// Heartbeat interval. Activity must heartbeat before this interval passes after a last
404
- /// heartbeat or activity start.
405
- pub heartbeat_timeout: Option<Duration>,
406
- /// Determines what the SDK does when the Activity is cancelled.
407
- pub cancellation_type: ActivityCancellationType,
408
- // Add more fields here as needed
451
+ struct LATimerBackoffFut<'a> {
452
+ la_opts: LocalActivityOptions,
453
+ current_fut: Pin<Box<dyn CancellableFuture<ActivityResolution> + Send + Unpin + 'a>>,
454
+ timer_fut: Option<Pin<Box<dyn CancellableFuture<TimerResult> + Send + Unpin + 'a>>>,
455
+ ctx: &'a WfContext,
456
+ next_attempt: u32,
457
+ next_sched_time: Option<prost_types::Timestamp>,
458
+ did_cancel: AtomicBool,
409
459
  }
410
-
411
- impl ActivityOptions {
412
- /// Turns an `ActivityOptions` struct to a `ScheduleActivity` struct using given `seq`
413
- pub fn to_command(&self, seq: u32) -> ScheduleActivity {
414
- ScheduleActivity {
415
- seq,
416
- activity_id: match &self.activity_id {
417
- None => seq.to_string(),
418
- Some(aid) => aid.clone(),
419
- },
420
- activity_type: self.activity_type.clone(),
421
- task_queue: self.task_queue.clone(),
422
- schedule_to_close_timeout: self.schedule_to_close_timeout.map(Into::into),
423
- schedule_to_start_timeout: self.schedule_to_start_timeout.map(Into::into),
424
- start_to_close_timeout: self.start_to_close_timeout.map(Into::into),
425
- heartbeat_timeout: self.heartbeat_timeout.map(Into::into),
426
- cancellation_type: self.cancellation_type as i32,
427
- ..Default::default()
460
+ impl<'a> LATimerBackoffFut<'a> {
461
+ pub(crate) fn new(opts: LocalActivityOptions, ctx: &'a WfContext) -> Self {
462
+ Self {
463
+ la_opts: opts.clone(),
464
+ current_fut: Box::pin(ctx.local_activity_no_timer_retry(opts)),
465
+ timer_fut: None,
466
+ ctx,
467
+ next_attempt: 1,
468
+ next_sched_time: None,
469
+ did_cancel: AtomicBool::new(false),
428
470
  }
429
471
  }
430
472
  }
473
+ impl<'a> Unpin for LATimerBackoffFut<'a> {}
474
+ impl<'a> Future for LATimerBackoffFut<'a> {
475
+ type Output = ActivityResolution;
431
476
 
432
- /// Options for scheduling a child workflow
433
- #[derive(Default, Debug, Clone)]
434
- pub struct ChildWorkflowOptions {
435
- /// Workflow ID
436
- pub workflow_id: String,
437
- /// Type of workflow to schedule
438
- pub workflow_type: String,
439
- /// Input to send the child Workflow
440
- pub input: Vec<Payload>,
441
- /// Cancellation strategy for the child workflow
442
- pub cancel_type: ChildWorkflowCancellationType,
443
- }
477
+ fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
478
+ // If the timer exists, wait for it first
479
+ if let Some(tf) = self.timer_fut.as_mut() {
480
+ return match tf.poll_unpin(cx) {
481
+ Poll::Ready(tr) => {
482
+ self.timer_fut = None;
483
+ // Schedule next LA if this timer wasn't cancelled
484
+ if let TimerResult::Fired = tr {
485
+ let mut opts = self.la_opts.clone();
486
+ opts.attempt = Some(self.next_attempt);
487
+ opts.original_schedule_time = self.next_sched_time.clone();
488
+ self.current_fut = Box::pin(self.ctx.local_activity_no_timer_retry(opts));
489
+ Poll::Pending
490
+ } else {
491
+ Poll::Ready(ActivityResolution {
492
+ status: Some(
493
+ activity_resolution::Status::Cancelled(Default::default()),
494
+ ),
495
+ })
496
+ }
497
+ }
498
+ Poll::Pending => Poll::Pending,
499
+ };
500
+ }
501
+ let poll_res = self.current_fut.poll_unpin(cx);
502
+ if let Poll::Ready(ref r) = poll_res {
503
+ // If we've already said we want to cancel, don't schedule the backoff timer. Just
504
+ // return cancel status. This can happen if cancel comes after the LA says it wants to
505
+ // back off but before we have scheduled the timer.
506
+ if self.did_cancel.load(Ordering::Acquire) {
507
+ return Poll::Ready(ActivityResolution {
508
+ status: Some(activity_resolution::Status::Cancelled(Default::default())),
509
+ });
510
+ }
444
511
 
445
- impl ChildWorkflowOptions {
446
- /// Turns a `ChildWorkflowOptions` struct to a `StartChildWorkflowExecution` struct using
447
- /// given `seq`
448
- pub fn into_command(self, seq: u32) -> StartChildWorkflowExecution {
449
- StartChildWorkflowExecution {
450
- seq,
451
- workflow_id: self.workflow_id,
452
- workflow_type: self.workflow_type,
453
- input: self.input,
454
- cancellation_type: self.cancel_type as i32,
455
- ..Default::default()
512
+ if let Some(activity_resolution::Status::Backoff(b)) = r.status.as_ref() {
513
+ let timer_f = self.ctx.timer(
514
+ b.backoff_duration
515
+ .clone()
516
+ .expect("Duration is set")
517
+ .try_into()
518
+ .expect("duration converts ok"),
519
+ );
520
+ self.timer_fut = Some(Box::pin(timer_f));
521
+ self.next_attempt = b.attempt;
522
+ self.next_sched_time = b.original_schedule_time.clone();
523
+ return Poll::Pending;
524
+ }
525
+ }
526
+ poll_res
527
+ }
528
+ }
529
+ impl<'a> CancellableFuture<ActivityResolution> for LATimerBackoffFut<'a> {
530
+ fn cancel(&self, ctx: &WfContext) {
531
+ self.did_cancel.store(true, Ordering::Release);
532
+ if let Some(tf) = self.timer_fut.as_ref() {
533
+ tf.cancel(ctx);
456
534
  }
535
+ self.current_fut.cancel(ctx);
457
536
  }
458
537
  }
459
538
 
@@ -494,14 +573,12 @@ pub struct StartedChildWorkflow {
494
573
 
495
574
  impl ChildWorkflow {
496
575
  /// Start the child workflow, the returned Future is cancellable.
497
- pub fn start(self, cx: &mut WfContext) -> impl CancellableFuture<PendingChildWorkflow> {
498
- let child_seq = cx.next_child_workflow_sequence_number;
499
- cx.next_child_workflow_sequence_number += 1;
576
+ pub fn start(self, cx: &WfContext) -> impl CancellableFuture<PendingChildWorkflow> {
577
+ let child_seq = cx.seq_nums.write().next_child_workflow_seq();
500
578
  // Immediately create the command/future for the result, otherwise if the user does
501
579
  // not await the result until *after* we receive an activation for it, there will be nothing
502
580
  // to match when unblocking.
503
- let cancel_seq = cx.next_cancel_external_wf_sequence_number;
504
- cx.next_cancel_external_wf_sequence_number += 1;
581
+ let cancel_seq = cx.seq_nums.write().next_cancel_external_wf_seq();
505
582
  let (result_cmd, unblocker) =
506
583
  CancellableWFCommandFut::new(CancellableID::ExternalWorkflow {
507
584
  seqnum: cancel_seq,
@@ -546,7 +623,7 @@ impl StartedChildWorkflow {
546
623
  }
547
624
 
548
625
  /// Cancel the child workflow
549
- pub fn cancel(&self, cx: &mut WfContext) -> impl Future<Output = CancelExternalWfResult> {
626
+ pub fn cancel(&self, cx: &WfContext) -> impl Future<Output = CancelExternalWfResult> {
550
627
  let target = NamespacedWorkflowExecution {
551
628
  namespace: cx.namespace().to_string(),
552
629
  workflow_id: self.common.workflow_id.clone(),
@@ -558,7 +635,7 @@ impl StartedChildWorkflow {
558
635
  /// Signal the child workflow
559
636
  pub fn signal(
560
637
  &self,
561
- cx: &mut WfContext,
638
+ cx: &WfContext,
562
639
  signal_name: impl Into<String>,
563
640
  payload: impl Into<Payload>,
564
641
  ) -> impl CancellableFuture<SignalExternalWfResult> {