@temporalio/core-bridge 1.5.2 → 1.7.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 (194) hide show
  1. package/Cargo.lock +304 -112
  2. package/lib/index.d.ts +8 -6
  3. package/lib/index.js.map +1 -1
  4. package/package.json +9 -4
  5. package/releases/aarch64-apple-darwin/index.node +0 -0
  6. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  7. package/releases/x86_64-apple-darwin/index.node +0 -0
  8. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  9. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  10. package/sdk-core/.buildkite/docker/Dockerfile +2 -2
  11. package/sdk-core/.buildkite/docker/docker-compose.yaml +1 -1
  12. package/sdk-core/.buildkite/pipeline.yml +2 -4
  13. package/sdk-core/.cargo/config.toml +5 -2
  14. package/sdk-core/.github/workflows/heavy.yml +29 -0
  15. package/sdk-core/Cargo.toml +1 -1
  16. package/sdk-core/README.md +20 -10
  17. package/sdk-core/client/src/lib.rs +215 -39
  18. package/sdk-core/client/src/metrics.rs +17 -8
  19. package/sdk-core/client/src/raw.rs +4 -4
  20. package/sdk-core/client/src/retry.rs +32 -20
  21. package/sdk-core/core/Cargo.toml +25 -12
  22. package/sdk-core/core/src/abstractions/take_cell.rs +28 -0
  23. package/sdk-core/core/src/abstractions.rs +204 -14
  24. package/sdk-core/core/src/core_tests/activity_tasks.rs +143 -50
  25. package/sdk-core/core/src/core_tests/child_workflows.rs +6 -5
  26. package/sdk-core/core/src/core_tests/determinism.rs +165 -2
  27. package/sdk-core/core/src/core_tests/local_activities.rs +431 -43
  28. package/sdk-core/core/src/core_tests/queries.rs +34 -16
  29. package/sdk-core/core/src/core_tests/workers.rs +8 -5
  30. package/sdk-core/core/src/core_tests/workflow_tasks.rs +588 -55
  31. package/sdk-core/core/src/ephemeral_server/mod.rs +113 -12
  32. package/sdk-core/core/src/internal_flags.rs +155 -0
  33. package/sdk-core/core/src/lib.rs +16 -9
  34. package/sdk-core/core/src/protosext/mod.rs +1 -1
  35. package/sdk-core/core/src/replay/mod.rs +16 -27
  36. package/sdk-core/core/src/telemetry/log_export.rs +1 -1
  37. package/sdk-core/core/src/telemetry/metrics.rs +69 -35
  38. package/sdk-core/core/src/telemetry/mod.rs +60 -21
  39. package/sdk-core/core/src/telemetry/prometheus_server.rs +19 -13
  40. package/sdk-core/core/src/test_help/mod.rs +73 -14
  41. package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +119 -160
  42. package/sdk-core/core/src/worker/activities/activity_task_poller_stream.rs +89 -0
  43. package/sdk-core/core/src/worker/activities/local_activities.rs +379 -129
  44. package/sdk-core/core/src/worker/activities.rs +350 -175
  45. package/sdk-core/core/src/worker/client/mocks.rs +22 -2
  46. package/sdk-core/core/src/worker/client.rs +18 -2
  47. package/sdk-core/core/src/worker/mod.rs +183 -64
  48. package/sdk-core/core/src/worker/workflow/bridge.rs +1 -3
  49. package/sdk-core/core/src/worker/workflow/driven_workflow.rs +3 -5
  50. package/sdk-core/core/src/worker/workflow/history_update.rs +916 -277
  51. package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +216 -183
  52. package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +9 -12
  53. package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +7 -9
  54. package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +160 -87
  55. package/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +13 -14
  56. package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +7 -9
  57. package/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +14 -17
  58. package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +242 -110
  59. package/sdk-core/core/src/worker/workflow/machines/mod.rs +27 -19
  60. package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +9 -11
  61. package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +321 -206
  62. package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +13 -18
  63. package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +20 -29
  64. package/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +2 -2
  65. package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +257 -51
  66. package/sdk-core/core/src/worker/workflow/machines/workflow_machines/local_acts.rs +6 -17
  67. package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +310 -150
  68. package/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +17 -20
  69. package/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +31 -15
  70. package/sdk-core/core/src/worker/workflow/managed_run.rs +1052 -380
  71. package/sdk-core/core/src/worker/workflow/mod.rs +598 -390
  72. package/sdk-core/core/src/worker/workflow/run_cache.rs +40 -57
  73. package/sdk-core/core/src/worker/workflow/wft_extraction.rs +137 -0
  74. package/sdk-core/core/src/worker/workflow/wft_poller.rs +1 -4
  75. package/sdk-core/core/src/worker/workflow/workflow_stream/saved_wf_inputs.rs +117 -0
  76. package/sdk-core/core/src/worker/workflow/workflow_stream/tonic_status_serde.rs +24 -0
  77. package/sdk-core/core/src/worker/workflow/workflow_stream.rs +469 -718
  78. package/sdk-core/core-api/Cargo.toml +2 -1
  79. package/sdk-core/core-api/src/errors.rs +1 -34
  80. package/sdk-core/core-api/src/lib.rs +19 -9
  81. package/sdk-core/core-api/src/telemetry.rs +4 -6
  82. package/sdk-core/core-api/src/worker.rs +19 -1
  83. package/sdk-core/etc/deps.svg +115 -140
  84. package/sdk-core/etc/regen-depgraph.sh +5 -0
  85. package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +86 -61
  86. package/sdk-core/fsm/rustfsm_trait/src/lib.rs +29 -71
  87. package/sdk-core/histories/ends_empty_wft_complete.bin +0 -0
  88. package/sdk-core/histories/evict_while_la_running_no_interference-16_history.bin +0 -0
  89. package/sdk-core/histories/old_change_marker_format.bin +0 -0
  90. package/sdk-core/protos/api_upstream/.github/CODEOWNERS +2 -1
  91. package/sdk-core/protos/api_upstream/Makefile +6 -6
  92. package/sdk-core/protos/api_upstream/build/go.mod +7 -0
  93. package/sdk-core/protos/api_upstream/build/go.sum +5 -0
  94. package/sdk-core/protos/api_upstream/build/tools.go +29 -0
  95. package/sdk-core/protos/api_upstream/go.mod +6 -0
  96. package/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +9 -2
  97. package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +7 -26
  98. package/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +13 -2
  99. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +3 -2
  100. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +3 -7
  101. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/common.proto +3 -2
  102. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +8 -8
  103. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +25 -2
  104. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +2 -2
  105. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/query.proto +2 -2
  106. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/reset.proto +2 -2
  107. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/schedule.proto +2 -2
  108. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +2 -2
  109. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +24 -19
  110. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +2 -2
  111. package/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +2 -2
  112. package/sdk-core/protos/api_upstream/temporal/api/failure/v1/message.proto +2 -2
  113. package/sdk-core/protos/api_upstream/temporal/api/filter/v1/message.proto +2 -2
  114. package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +49 -26
  115. package/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +4 -2
  116. package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +5 -2
  117. package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +2 -2
  118. package/sdk-core/protos/api_upstream/temporal/api/protocol/v1/message.proto +57 -0
  119. package/sdk-core/protos/api_upstream/temporal/api/query/v1/message.proto +2 -2
  120. package/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +2 -2
  121. package/sdk-core/protos/api_upstream/temporal/api/schedule/v1/message.proto +2 -2
  122. package/sdk-core/protos/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +63 -0
  123. package/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +2 -2
  124. package/sdk-core/protos/api_upstream/temporal/api/update/v1/message.proto +71 -6
  125. package/sdk-core/protos/api_upstream/temporal/api/version/v1/message.proto +2 -2
  126. package/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +2 -2
  127. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +64 -28
  128. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +4 -4
  129. package/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +7 -8
  130. package/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +10 -7
  131. package/sdk-core/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +19 -30
  132. package/sdk-core/protos/local/temporal/sdk/core/common/common.proto +1 -0
  133. package/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +1 -0
  134. package/sdk-core/protos/local/temporal/sdk/core/external_data/external_data.proto +8 -0
  135. package/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +67 -60
  136. package/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +85 -84
  137. package/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +9 -3
  138. package/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +2 -2
  139. package/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +2 -2
  140. package/sdk-core/sdk/Cargo.toml +5 -4
  141. package/sdk-core/sdk/src/lib.rs +108 -26
  142. package/sdk-core/sdk/src/workflow_context/options.rs +7 -1
  143. package/sdk-core/sdk/src/workflow_context.rs +24 -17
  144. package/sdk-core/sdk/src/workflow_future.rs +16 -15
  145. package/sdk-core/sdk-core-protos/Cargo.toml +5 -2
  146. package/sdk-core/sdk-core-protos/build.rs +36 -2
  147. package/sdk-core/sdk-core-protos/src/history_builder.rs +138 -106
  148. package/sdk-core/sdk-core-protos/src/history_info.rs +10 -1
  149. package/sdk-core/sdk-core-protos/src/lib.rs +272 -87
  150. package/sdk-core/sdk-core-protos/src/task_token.rs +12 -2
  151. package/sdk-core/test-utils/Cargo.toml +3 -1
  152. package/sdk-core/test-utils/src/canned_histories.rs +106 -296
  153. package/sdk-core/test-utils/src/histfetch.rs +1 -1
  154. package/sdk-core/test-utils/src/lib.rs +82 -23
  155. package/sdk-core/test-utils/src/wf_input_saver.rs +50 -0
  156. package/sdk-core/test-utils/src/workflows.rs +29 -0
  157. package/sdk-core/tests/fuzzy_workflow.rs +130 -0
  158. package/sdk-core/tests/{load_tests.rs → heavy_tests.rs} +125 -51
  159. package/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +25 -3
  160. package/sdk-core/tests/integ_tests/heartbeat_tests.rs +10 -5
  161. package/sdk-core/tests/integ_tests/metrics_tests.rs +218 -16
  162. package/sdk-core/tests/integ_tests/polling_tests.rs +4 -47
  163. package/sdk-core/tests/integ_tests/queries_tests.rs +5 -128
  164. package/sdk-core/tests/integ_tests/visibility_tests.rs +83 -25
  165. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +161 -72
  166. package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +1 -0
  167. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +6 -13
  168. package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +80 -3
  169. package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +6 -2
  170. package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +3 -10
  171. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +94 -200
  172. package/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +2 -4
  173. package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +34 -28
  174. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +76 -7
  175. package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +1 -0
  176. package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +18 -14
  177. package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +6 -20
  178. package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +10 -21
  179. package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +7 -8
  180. package/sdk-core/tests/integ_tests/workflow_tests.rs +13 -14
  181. package/sdk-core/tests/main.rs +3 -13
  182. package/sdk-core/tests/runner.rs +75 -36
  183. package/sdk-core/tests/wf_input_replay.rs +32 -0
  184. package/src/conversions.rs +14 -8
  185. package/src/runtime.rs +9 -8
  186. package/ts/index.ts +8 -6
  187. package/sdk-core/bridge-ffi/Cargo.toml +0 -24
  188. package/sdk-core/bridge-ffi/LICENSE.txt +0 -23
  189. package/sdk-core/bridge-ffi/build.rs +0 -25
  190. package/sdk-core/bridge-ffi/include/sdk-core-bridge.h +0 -224
  191. package/sdk-core/bridge-ffi/src/lib.rs +0 -746
  192. package/sdk-core/bridge-ffi/src/wrappers.rs +0 -221
  193. package/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +0 -210
  194. package/sdk-core/sdk/src/conversions.rs +0 -8
@@ -1,22 +1,22 @@
1
1
  use crate::{
2
2
  telemetry::metrics::workflow_type,
3
3
  worker::workflow::{
4
- managed_run::WorkflowManager, HistoryUpdate, LocalActivityRequestSink, ManagedRunHandle,
5
- NewIncomingWFT, RunUpdateResponse,
4
+ managed_run::{ManagedRun, RunUpdateAct},
5
+ HistoryUpdate, LocalActivityRequestSink, PermittedWFT, RunBasics,
6
6
  },
7
7
  MetricsContext,
8
8
  };
9
9
  use lru::LruCache;
10
- use std::{num::NonZeroUsize, time::Instant};
11
- use tokio::sync::mpsc::UnboundedSender;
10
+ use std::{mem, num::NonZeroUsize, rc::Rc};
11
+ use temporal_sdk_core_protos::temporal::api::workflowservice::v1::get_system_info_response;
12
12
 
13
13
  pub(super) struct RunCache {
14
14
  max: usize,
15
15
  namespace: String,
16
- run_update_tx: UnboundedSender<RunUpdateResponse>,
16
+ server_capabilities: get_system_info_response::Capabilities,
17
17
  /// Run id -> Data
18
- runs: LruCache<String, ManagedRunHandle>,
19
- local_activity_request_sink: LocalActivityRequestSink,
18
+ runs: LruCache<String, ManagedRun>,
19
+ local_activity_request_sink: Rc<dyn LocalActivityRequestSink>,
20
20
 
21
21
  metrics: MetricsContext,
22
22
  }
@@ -25,8 +25,8 @@ impl RunCache {
25
25
  pub fn new(
26
26
  max_cache_size: usize,
27
27
  namespace: String,
28
- run_update_tx: UnboundedSender<RunUpdateResponse>,
29
- local_activity_request_sink: LocalActivityRequestSink,
28
+ server_capabilities: get_system_info_response::Capabilities,
29
+ local_activity_request_sink: impl LocalActivityRequestSink,
30
30
  metrics: MetricsContext,
31
31
  ) -> Self {
32
32
  // The cache needs room for at least one run, otherwise we couldn't do anything. In
@@ -39,80 +39,63 @@ impl RunCache {
39
39
  Self {
40
40
  max: max_cache_size,
41
41
  namespace,
42
- run_update_tx,
42
+ server_capabilities,
43
43
  runs: LruCache::new(
44
44
  NonZeroUsize::new(lru_size).expect("LRU size is guaranteed positive"),
45
45
  ),
46
- local_activity_request_sink,
46
+ local_activity_request_sink: Rc::new(local_activity_request_sink),
47
47
  metrics,
48
48
  }
49
49
  }
50
50
 
51
- pub fn instantiate_or_update(
52
- &mut self,
53
- run_id: &str,
54
- workflow_id: &str,
55
- wf_type: &str,
56
- history_update: HistoryUpdate,
57
- start_time: Instant,
58
- ) -> &mut ManagedRunHandle {
51
+ pub fn instantiate_or_update(&mut self, mut pwft: PermittedWFT) -> RunUpdateAct {
59
52
  let cur_num_cached_runs = self.runs.len();
53
+ let run_id = &pwft.work.execution.run_id;
60
54
 
61
- if self.runs.contains(run_id) {
62
- // For some weird reason, maybe a NLL bug, there are double-mutable-borrow errors if I
63
- // use get_mut above instead of in here (even though we always return from this branch).
64
- // So, forced to do this.
65
- let run_handle = self.runs.get_mut(run_id).unwrap();
66
-
67
- run_handle.metrics.sticky_cache_hit();
68
- run_handle.incoming_wft(NewIncomingWFT {
69
- history_update: Some(history_update),
70
- start_time,
71
- });
55
+ if let Some(run_handle) = self.runs.get_mut(run_id) {
56
+ let rur = run_handle.incoming_wft(pwft);
72
57
  self.metrics.cache_size(cur_num_cached_runs as u64);
73
- return run_handle;
58
+ return rur;
74
59
  }
75
60
 
76
61
  // Create a new workflow machines instance for this workflow, initialize it, and
77
62
  // track it.
78
63
  let metrics = self
79
64
  .metrics
80
- .with_new_attrs([workflow_type(wf_type.to_string())]);
81
- let wfm = WorkflowManager::new(
82
- history_update,
83
- self.namespace.clone(),
84
- workflow_id.to_string(),
85
- wf_type.to_string(),
86
- run_id.to_string(),
87
- metrics.clone(),
88
- );
89
- let mut mrh = ManagedRunHandle::new(
90
- wfm,
91
- self.run_update_tx.clone(),
65
+ .with_new_attrs([workflow_type(pwft.work.workflow_type.clone())]);
66
+ // Replace the update in the wft with a dummy one, since we must instantiate the machines
67
+ // with the update.
68
+ let history_update = mem::replace(&mut pwft.work.update, HistoryUpdate::dummy());
69
+ let mut mrh = ManagedRun::new(
70
+ RunBasics {
71
+ namespace: self.namespace.clone(),
72
+ workflow_id: pwft.work.execution.workflow_id.clone(),
73
+ workflow_type: pwft.work.workflow_type.clone(),
74
+ run_id: pwft.work.execution.run_id.clone(),
75
+ history: history_update,
76
+ metrics,
77
+ capabilities: &self.server_capabilities,
78
+ },
92
79
  self.local_activity_request_sink.clone(),
93
- metrics,
94
80
  );
95
- mrh.incoming_wft(NewIncomingWFT {
96
- history_update: None,
97
- start_time,
98
- });
99
- if self.runs.push(run_id.to_string(), mrh).is_some() {
81
+ let run_id = run_id.to_string();
82
+ let rur = mrh.incoming_wft(pwft);
83
+ if self.runs.push(run_id, mrh).is_some() {
100
84
  panic!("Overflowed run cache! Cache owner is expected to avoid this!");
101
85
  }
102
86
  self.metrics.cache_size(cur_num_cached_runs as u64 + 1);
103
- // This is safe, we just inserted.
104
- self.runs.get_mut(run_id).unwrap()
87
+ rur
105
88
  }
106
- pub fn remove(&mut self, k: &str) -> Option<ManagedRunHandle> {
89
+ pub fn remove(&mut self, k: &str) -> Option<ManagedRun> {
107
90
  let r = self.runs.pop(k);
108
91
  self.metrics.cache_size(self.len() as u64);
109
92
  r
110
93
  }
111
94
 
112
- pub fn get_mut(&mut self, k: &str) -> Option<&mut ManagedRunHandle> {
95
+ pub fn get_mut(&mut self, k: &str) -> Option<&mut ManagedRun> {
113
96
  self.runs.get_mut(k)
114
97
  }
115
- pub fn get(&mut self, k: &str) -> Option<&ManagedRunHandle> {
98
+ pub fn get(&mut self, k: &str) -> Option<&ManagedRun> {
116
99
  self.runs.get(k)
117
100
  }
118
101
 
@@ -121,16 +104,16 @@ impl RunCache {
121
104
  self.runs.peek_lru().map(|(run_id, _)| run_id.as_str())
122
105
  }
123
106
  /// Returns an iterator yielding cached runs in LRU order
124
- pub fn runs_lru_order(&self) -> impl Iterator<Item = (&str, &ManagedRunHandle)> {
107
+ pub fn runs_lru_order(&self) -> impl Iterator<Item = (&str, &ManagedRun)> {
125
108
  self.runs.iter().rev().map(|(k, v)| (k.as_str(), v))
126
109
  }
127
- pub fn peek(&self, k: &str) -> Option<&ManagedRunHandle> {
110
+ pub fn peek(&self, k: &str) -> Option<&ManagedRun> {
128
111
  self.runs.peek(k)
129
112
  }
130
113
  pub fn has_run(&self, k: &str) -> bool {
131
114
  self.runs.contains(k)
132
115
  }
133
- pub fn handles(&self) -> impl Iterator<Item = &ManagedRunHandle> {
116
+ pub fn handles(&self) -> impl Iterator<Item = &ManagedRun> {
134
117
  self.runs.iter().map(|(_, v)| v)
135
118
  }
136
119
  pub fn is_full(&self) -> bool {
@@ -0,0 +1,137 @@
1
+ use crate::{
2
+ abstractions::OwnedMeteredSemPermit,
3
+ protosext::ValidPollWFTQResponse,
4
+ worker::{
5
+ client::WorkerClient,
6
+ workflow::{
7
+ history_update::HistoryPaginator, CacheMissFetchReq, HistoryUpdate, NextPageReq,
8
+ PermittedWFT,
9
+ },
10
+ },
11
+ };
12
+ use futures::Stream;
13
+ use futures_util::{stream, stream::PollNext, FutureExt, StreamExt};
14
+ use std::{future, sync::Arc};
15
+ use temporal_sdk_core_protos::TaskToken;
16
+ use tracing::Span;
17
+
18
+ /// Transforms incoming validated WFTs and history fetching requests into [PermittedWFT]s ready
19
+ /// for application to workflow state
20
+ pub(super) struct WFTExtractor {}
21
+
22
+ pub(super) enum WFTExtractorOutput {
23
+ NewWFT(PermittedWFT),
24
+ FetchResult(PermittedWFT, Arc<HistfetchRC>),
25
+ NextPage {
26
+ paginator: HistoryPaginator,
27
+ update: HistoryUpdate,
28
+ span: Span,
29
+ rc: Arc<HistfetchRC>,
30
+ },
31
+ FailedFetch {
32
+ run_id: String,
33
+ err: tonic::Status,
34
+ auto_reply_fail_tt: Option<TaskToken>,
35
+ },
36
+ PollerDead,
37
+ }
38
+
39
+ type WFTStreamIn = (
40
+ Result<ValidPollWFTQResponse, tonic::Status>,
41
+ OwnedMeteredSemPermit,
42
+ );
43
+ #[derive(derive_more::From, Debug)]
44
+ pub(super) enum HistoryFetchReq {
45
+ Full(CacheMissFetchReq, Arc<HistfetchRC>),
46
+ NextPage(NextPageReq, Arc<HistfetchRC>),
47
+ }
48
+ /// Used inside of `Arc`s to ensure we don't shutdown while there are outstanding fetches.
49
+ #[derive(Debug)]
50
+ pub(super) struct HistfetchRC {}
51
+
52
+ impl WFTExtractor {
53
+ pub(super) fn build(
54
+ client: Arc<dyn WorkerClient>,
55
+ max_fetch_concurrency: usize,
56
+ wft_stream: impl Stream<Item = WFTStreamIn> + Send + 'static,
57
+ fetch_stream: impl Stream<Item = HistoryFetchReq> + Send + 'static,
58
+ ) -> impl Stream<Item = Result<WFTExtractorOutput, tonic::Status>> + Send + 'static {
59
+ let fetch_client = client.clone();
60
+ let wft_stream = wft_stream
61
+ .map(move |(wft, permit)| {
62
+ let client = client.clone();
63
+ async move {
64
+ match wft {
65
+ Ok(wft) => {
66
+ let run_id = wft.workflow_execution.run_id.clone();
67
+ let tt = wft.task_token.clone();
68
+ Ok(match HistoryPaginator::from_poll(wft, client).await {
69
+ Ok((pag, prep)) => WFTExtractorOutput::NewWFT(PermittedWFT {
70
+ work: prep,
71
+ permit: permit.into_used(),
72
+ paginator: pag,
73
+ }),
74
+ Err(err) => WFTExtractorOutput::FailedFetch {
75
+ run_id,
76
+ err,
77
+ auto_reply_fail_tt: Some(tt),
78
+ },
79
+ })
80
+ }
81
+ Err(e) => Err(e),
82
+ }
83
+ }
84
+ // This is... unattractive, but lets us avoid boxing all the futs in the stream
85
+ .left_future()
86
+ .left_future()
87
+ })
88
+ .chain(stream::iter([future::ready(Ok(
89
+ WFTExtractorOutput::PollerDead,
90
+ ))
91
+ .right_future()
92
+ .left_future()]));
93
+
94
+ stream::select_with_strategy(
95
+ wft_stream,
96
+ fetch_stream.map(move |fetchreq: HistoryFetchReq| {
97
+ let client = fetch_client.clone();
98
+ async move {
99
+ Ok(match fetchreq {
100
+ // It's OK to simply drop the refcounters in the event of fetch
101
+ // failure. We'll just proceed with shutdown.
102
+ HistoryFetchReq::Full(req, rc) => {
103
+ let run_id = req.original_wft.work.execution.run_id.clone();
104
+ match HistoryPaginator::from_fetchreq(req, client).await {
105
+ Ok(r) => WFTExtractorOutput::FetchResult(r, rc),
106
+ Err(err) => WFTExtractorOutput::FailedFetch {
107
+ run_id,
108
+ err,
109
+ auto_reply_fail_tt: None,
110
+ },
111
+ }
112
+ }
113
+ HistoryFetchReq::NextPage(mut req, rc) => {
114
+ match req.paginator.extract_next_update().await {
115
+ Ok(update) => WFTExtractorOutput::NextPage {
116
+ paginator: req.paginator,
117
+ update,
118
+ span: req.span,
119
+ rc,
120
+ },
121
+ Err(err) => WFTExtractorOutput::FailedFetch {
122
+ run_id: req.paginator.run_id,
123
+ err,
124
+ auto_reply_fail_tt: None,
125
+ },
126
+ }
127
+ }
128
+ })
129
+ }
130
+ .right_future()
131
+ }),
132
+ // Priority always goes to the fetching stream
133
+ |_: &mut ()| PollNext::Right,
134
+ )
135
+ .buffer_unordered(max_fetch_concurrency)
136
+ }
137
+ }
@@ -47,10 +47,7 @@ pub(crate) fn validate_wft(
47
47
  wft.try_into().map_err(|resp| {
48
48
  tonic::Status::new(
49
49
  tonic::Code::DataLoss,
50
- format!(
51
- "Server returned a poll WFT response we couldn't interpret: {:?}",
52
- resp
53
- ),
50
+ format!("Server returned a poll WFT response we couldn't interpret: {resp:?}"),
54
51
  )
55
52
  })
56
53
  }
@@ -0,0 +1,117 @@
1
+ use crate::{
2
+ telemetry::metrics::MetricsContext,
3
+ worker::{
4
+ client::mocks::DEFAULT_TEST_CAPABILITIES,
5
+ workflow::{
6
+ workflow_stream::{WFStream, WFStreamInput},
7
+ LAReqSink, LocalActivityRequestSink,
8
+ },
9
+ LocalActRequest, LocalActivityResolution,
10
+ },
11
+ };
12
+ use crossbeam::queue::SegQueue;
13
+ use futures::Stream;
14
+ use futures_util::StreamExt;
15
+ use serde::{Deserialize, Serialize};
16
+ use std::{future, sync::Arc};
17
+ use temporal_sdk_core_api::worker::WorkerConfig;
18
+ use tokio::sync::mpsc::UnboundedSender;
19
+ use tokio_util::sync::CancellationToken;
20
+
21
+ /// Replay everything that happened to internal workflow state. Useful for 100% deterministic
22
+ /// reproduction of bugs.
23
+ ///
24
+ /// Use `CoreWfStarter::enable_wf_state_input_recording` from the integration test utilities to
25
+ /// activate saving the data to disk, and use the `wf_input_replay` example binary to replay.
26
+ pub async fn replay_wf_state_inputs(mut config: WorkerConfig, inputs: impl Stream<Item = Vec<u8>>) {
27
+ use crate::worker::build_wf_basics;
28
+
29
+ let la_resp_q = Arc::new(SegQueue::new());
30
+ let la_resp_q_clone = la_resp_q.clone();
31
+ let inputs = inputs
32
+ .map(|bytes| {
33
+ rmp_serde::from_slice::<StoredWFStateInputDeSer>(&bytes)
34
+ .expect("Can decode wf stream input")
35
+ })
36
+ .filter_map(|si| {
37
+ future::ready(match si {
38
+ StoredWFStateInputDeSer::Stream(wfsi) => Some(wfsi),
39
+ StoredWFStateInputDeSer::ImmediateLASinkResolutions(lares) => {
40
+ la_resp_q_clone.push(lares);
41
+ None
42
+ }
43
+ })
44
+ });
45
+ let basics = build_wf_basics(
46
+ &mut config,
47
+ MetricsContext::no_op(),
48
+ CancellationToken::new(),
49
+ DEFAULT_TEST_CAPABILITIES.clone(),
50
+ );
51
+ let sink = ReadingFromFileLaReqSink {
52
+ resolutions: la_resp_q,
53
+ };
54
+ info!("Beginning workflow stream internal state replay");
55
+ let stream = WFStream::build_internal(inputs, basics, sink);
56
+ stream
57
+ .for_each(|o| async move { trace!("Stream output: {:?}", o) })
58
+ .await;
59
+ }
60
+
61
+ impl WFStream {
62
+ pub(super) fn prep_input(&mut self, action: &WFStreamInput) -> Option<PreppedInputWrite> {
63
+ // Remove the channel, we'll put it back, avoiding a clone
64
+ self.wf_state_inputs.take().map(|chan| PreppedInputWrite {
65
+ data: rmp_serde::to_vec(&StoredWFStateInputSer::Stream(action))
66
+ .expect("WF Inputs are serializable"),
67
+ chan,
68
+ })
69
+ }
70
+ pub(super) fn flush_write(&mut self, w: PreppedInputWrite) {
71
+ let _ = w.chan.send(w.data);
72
+ self.wf_state_inputs = Some(w.chan);
73
+ }
74
+ }
75
+ pub(super) struct PreppedInputWrite {
76
+ data: Vec<u8>,
77
+ chan: UnboundedSender<Vec<u8>>,
78
+ }
79
+
80
+ #[derive(Serialize)]
81
+ enum StoredWFStateInputSer<'a> {
82
+ Stream(&'a WFStreamInput),
83
+ ImmediateLASinkResolutions(&'a Vec<LocalActivityResolution>),
84
+ }
85
+
86
+ #[derive(Deserialize)]
87
+ enum StoredWFStateInputDeSer {
88
+ Stream(WFStreamInput),
89
+ ImmediateLASinkResolutions(Vec<LocalActivityResolution>),
90
+ }
91
+
92
+ struct ReadingFromFileLaReqSink {
93
+ resolutions: Arc<SegQueue<Vec<LocalActivityResolution>>>,
94
+ }
95
+ impl LocalActivityRequestSink for ReadingFromFileLaReqSink {
96
+ fn sink_reqs(&self, reqs: Vec<LocalActRequest>) -> Vec<LocalActivityResolution> {
97
+ if !reqs.is_empty() {
98
+ self.resolutions
99
+ .pop()
100
+ .expect("LA sink was called, but there's no stored immediate response")
101
+ } else {
102
+ vec![]
103
+ }
104
+ }
105
+ }
106
+
107
+ impl LAReqSink {
108
+ pub(crate) fn write_req(&self, res: &Vec<LocalActivityResolution>) {
109
+ if let Some(r) = self.recorder.as_ref() {
110
+ r.send(
111
+ rmp_serde::to_vec(&StoredWFStateInputSer::ImmediateLASinkResolutions(res))
112
+ .expect("LA immediate resolutions are serializable"),
113
+ )
114
+ .expect("WF input serialization channel is available for immediate LA result storage");
115
+ }
116
+ }
117
+ }
@@ -0,0 +1,24 @@
1
+ use tonic::{Code, Status};
2
+
3
+ #[derive(serde::Serialize, serde::Deserialize)]
4
+ #[serde(remote = "Status")]
5
+ pub(super) struct SerdeStatus {
6
+ #[serde(getter = "get_code")]
7
+ code: i32,
8
+ #[serde(getter = "get_owned_msg")]
9
+ message: String,
10
+ }
11
+
12
+ fn get_owned_msg(v: &Status) -> String {
13
+ v.message().to_string()
14
+ }
15
+
16
+ fn get_code(v: &Status) -> i32 {
17
+ v.code() as i32
18
+ }
19
+
20
+ impl From<SerdeStatus> for Status {
21
+ fn from(v: SerdeStatus) -> Self {
22
+ Status::new(Code::from(v.code), v.message)
23
+ }
24
+ }