@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
@@ -23,6 +23,9 @@ use std::os::unix::fs::OpenOptionsExt;
23
23
  use std::process::Stdio;
24
24
 
25
25
  /// Configuration for Temporalite.
26
+ /// Will be removed eventually as its successor, Temporal CLI matures.
27
+ /// We don't care for the duplication between this struct and [TemporalDevServerConfig] and prefer that over another
28
+ /// abstraction since the existence of this struct is temporary.
26
29
  #[derive(Debug, Clone, derive_builder::Builder)]
27
30
  pub struct TemporaliteConfig {
28
31
  /// Required path to executable or download info.
@@ -59,7 +62,10 @@ impl TemporaliteConfig {
59
62
  /// Start a Temporalite server with configurable stdout destination.
60
63
  pub async fn start_server_with_output(&self, output: Stdio) -> anyhow::Result<EphemeralServer> {
61
64
  // Get exe path
62
- let exe_path = self.exe.get_or_download("temporalite").await?;
65
+ let exe_path = self
66
+ .exe
67
+ .get_or_download("temporalite", "temporalite", None)
68
+ .await?;
63
69
 
64
70
  // Get free port if not already given
65
71
  let port = self.port.unwrap_or_else(|| get_free_port(&self.ip));
@@ -77,6 +83,8 @@ impl TemporaliteConfig {
77
83
  self.log.0.clone(),
78
84
  "--log-level".to_owned(),
79
85
  self.log.1.clone(),
86
+ "--dynamic-config-value".to_owned(),
87
+ "frontend.enableServerVersionCheck=false".to_owned(),
80
88
  ];
81
89
  if let Some(db_filename) = &self.db_filename {
82
90
  args.push("--filename".to_owned());
@@ -101,6 +109,89 @@ impl TemporaliteConfig {
101
109
  }
102
110
  }
103
111
 
112
+ /// Configuration for Temporal CLI dev server.
113
+ #[derive(Debug, Clone, derive_builder::Builder)]
114
+ pub struct TemporalDevServerConfig {
115
+ /// Required path to executable or download info.
116
+ pub exe: EphemeralExe,
117
+ /// Namespace to use.
118
+ #[builder(default = "\"default\".to_owned()")]
119
+ pub namespace: String,
120
+ /// IP to bind to.
121
+ #[builder(default = "\"127.0.0.1\".to_owned()")]
122
+ pub ip: String,
123
+ /// Port to use or obtains a free one if none given.
124
+ #[builder(default)]
125
+ pub port: Option<u16>,
126
+ /// Sqlite DB filename if persisting or non-persistent if none.
127
+ #[builder(default)]
128
+ pub db_filename: Option<String>,
129
+ /// Whether to enable the UI.
130
+ #[builder(default)]
131
+ pub ui: bool,
132
+ /// Log format and level
133
+ #[builder(default = "(\"pretty\".to_owned(), \"warn\".to_owned())")]
134
+ pub log: (String, String),
135
+ /// Additional arguments to Temporalite.
136
+ #[builder(default)]
137
+ pub extra_args: Vec<String>,
138
+ }
139
+
140
+ impl TemporalDevServerConfig {
141
+ /// Start a Temporal CLI dev server.
142
+ pub async fn start_server(&self) -> anyhow::Result<EphemeralServer> {
143
+ self.start_server_with_output(Stdio::inherit()).await
144
+ }
145
+
146
+ /// Start a Temporal CLI dev server with configurable stdout destination.
147
+ pub async fn start_server_with_output(&self, output: Stdio) -> anyhow::Result<EphemeralServer> {
148
+ // Get exe path
149
+ let exe_path = self
150
+ .exe
151
+ .get_or_download("cli", "temporal", Some("tar.gz"))
152
+ .await?;
153
+
154
+ // Get free port if not already given
155
+ let port = self.port.unwrap_or_else(|| get_free_port(&self.ip));
156
+
157
+ // Build arg set
158
+ let mut args = vec![
159
+ "server".to_owned(),
160
+ "start-dev".to_owned(),
161
+ "--port".to_owned(),
162
+ port.to_string(),
163
+ "--namespace".to_owned(),
164
+ self.namespace.clone(),
165
+ "--ip".to_owned(),
166
+ self.ip.clone(),
167
+ "--log-format".to_owned(),
168
+ self.log.0.clone(),
169
+ "--log-level".to_owned(),
170
+ self.log.1.clone(),
171
+ "--dynamic-config-value".to_owned(),
172
+ "frontend.enableServerVersionCheck=false".to_owned(),
173
+ ];
174
+ if let Some(db_filename) = &self.db_filename {
175
+ args.push("--filename".to_owned());
176
+ args.push(db_filename.clone());
177
+ }
178
+ if !self.ui {
179
+ args.push("--headless".to_owned());
180
+ }
181
+ args.extend(self.extra_args.clone());
182
+
183
+ // Start
184
+ EphemeralServer::start(EphemeralServerConfig {
185
+ exe_path,
186
+ port,
187
+ args,
188
+ has_test_service: false,
189
+ output,
190
+ })
191
+ .await
192
+ }
193
+ }
194
+
104
195
  /// Configuration for the test server.
105
196
  #[derive(Debug, Clone, derive_builder::Builder)]
106
197
  pub struct TestServerConfig {
@@ -123,7 +214,10 @@ impl TestServerConfig {
123
214
  /// Start a test server with configurable stdout.
124
215
  pub async fn start_server_with_output(&self, output: Stdio) -> anyhow::Result<EphemeralServer> {
125
216
  // Get exe path
126
- let exe_path = self.exe.get_or_download("temporal-test-server").await?;
217
+ let exe_path = self
218
+ .exe
219
+ .get_or_download("temporal-test-server", "temporal-test-server", None)
220
+ .await?;
127
221
 
128
222
  // Get free port if not already given
129
223
  let port = self.port.unwrap_or_else(|| get_free_port("0.0.0.0"));
@@ -172,7 +266,7 @@ impl EphemeralServer {
172
266
  .stdout(config.output)
173
267
  .spawn()?;
174
268
  let target = format!("127.0.0.1:{}", config.port);
175
- let target_url = format!("http://{}", target);
269
+ let target_url = format!("http://{target}");
176
270
  let success = Ok(EphemeralServer {
177
271
  target,
178
272
  has_test_service: config.has_test_service,
@@ -262,7 +356,7 @@ pub enum EphemeralExe {
262
356
  #[derive(Debug, Clone)]
263
357
  pub enum EphemeralExeVersion {
264
358
  /// Use a default version for the given SDK name and version.
265
- Default {
359
+ SDKDefault {
266
360
  /// Name of the SDK to get the default for.
267
361
  sdk_name: String,
268
362
  /// Version of the SDK to get the default for.
@@ -280,7 +374,12 @@ struct DownloadInfo {
280
374
  }
281
375
 
282
376
  impl EphemeralExe {
283
- async fn get_or_download(&self, artifact_name: &str) -> anyhow::Result<PathBuf> {
377
+ async fn get_or_download(
378
+ &self,
379
+ artifact_name: &str,
380
+ downloaded_name_prefix: &str,
381
+ preferred_format: Option<&str>,
382
+ ) -> anyhow::Result<PathBuf> {
284
383
  match self {
285
384
  EphemeralExe::ExistingPath(exe_path) => {
286
385
  let path = PathBuf::from(exe_path);
@@ -301,12 +400,12 @@ impl EphemeralExe {
301
400
  };
302
401
  // Create dest file based on SDK name/version or fixed version
303
402
  let dest = dest_dir.join(match version {
304
- EphemeralExeVersion::Default {
403
+ EphemeralExeVersion::SDKDefault {
305
404
  sdk_name,
306
405
  sdk_version,
307
- } => format!("{}-{}-{}{}", artifact_name, sdk_name, sdk_version, out_ext),
406
+ } => format!("{downloaded_name_prefix}-{sdk_name}-{sdk_version}{out_ext}"),
308
407
  EphemeralExeVersion::Fixed(version) => {
309
- format!("{}-{}{}", artifact_name, version, out_ext)
408
+ format!("{downloaded_name_prefix}-{version}{out_ext}")
310
409
  }
311
410
  });
312
411
  debug!(
@@ -326,8 +425,11 @@ impl EphemeralExe {
326
425
  other => return Err(anyhow!("Unsupported arch: {}", other)),
327
426
  };
328
427
  let mut get_info_params = vec![("arch", arch), ("platform", platform)];
428
+ if let Some(format) = preferred_format {
429
+ get_info_params.push(("format", format));
430
+ }
329
431
  let version_name = match version {
330
- EphemeralExeVersion::Default {
432
+ EphemeralExeVersion::SDKDefault {
331
433
  sdk_name,
332
434
  sdk_version,
333
435
  } => {
@@ -340,8 +442,7 @@ impl EphemeralExe {
340
442
  let client = reqwest::Client::new();
341
443
  let info: DownloadInfo = client
342
444
  .get(format!(
343
- "https://temporal.download/{}/{}",
344
- artifact_name, version_name
445
+ "https://temporal.download/{artifact_name}/{version_name}"
345
446
  ))
346
447
  .query(&get_info_params)
347
448
  .send()
@@ -371,7 +472,7 @@ impl EphemeralExe {
371
472
  fn get_free_port(bind_ip: &str) -> u16 {
372
473
  // Can just ask OS to give us a port then close socket. OS's don't give that
373
474
  // port back to anyone else anytime soon.
374
- std::net::TcpListener::bind(format!("{}:0", bind_ip))
475
+ std::net::TcpListener::bind(format!("{bind_ip}:0"))
375
476
  .unwrap()
376
477
  .local_addr()
377
478
  .unwrap()
@@ -0,0 +1,155 @@
1
+ //! Utilities for and tracking of internal versions which alter history in incompatible ways
2
+ //! so that we can use older code paths for workflows executed on older core versions.
3
+
4
+ use std::collections::{BTreeSet, HashSet};
5
+ use temporal_sdk_core_protos::temporal::api::{
6
+ history::v1::WorkflowTaskCompletedEventAttributes, sdk::v1::WorkflowTaskCompletedMetadata,
7
+ workflowservice::v1::get_system_info_response,
8
+ };
9
+
10
+ /// This enumeration contains internal flags that may result in incompatible history changes with
11
+ /// older workflows, or other breaking changes.
12
+ ///
13
+ /// When a flag has existed long enough the version it was introduced in is no longer supported, it
14
+ /// may be removed from the enum. *Importantly*, all variants must be given explicit values, such
15
+ /// that removing older variants does not create any change in existing values. Removed flag
16
+ /// variants must be reserved forever (a-la protobuf), and should be called out in a comment.
17
+ #[repr(u32)]
18
+ #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Clone, Debug)]
19
+ pub(crate) enum CoreInternalFlags {
20
+ /// In this flag additional checks were added to a number of state machines to ensure that
21
+ /// the ID and type of activities, local activities, and child workflows match during replay.
22
+ IdAndTypeDeterminismChecks = 1,
23
+ /// Introduced automatically upserting search attributes for each patched call, and
24
+ /// nondeterminism checks for upserts.
25
+ UpsertSearchAttributeOnPatch = 2,
26
+ /// We received a value higher than this code can understand.
27
+ TooHigh = u32::MAX,
28
+ }
29
+
30
+ #[derive(Debug, Clone, PartialEq, Eq)]
31
+ pub(crate) struct InternalFlags {
32
+ enabled: bool,
33
+ core: BTreeSet<CoreInternalFlags>,
34
+ lang: BTreeSet<u32>,
35
+ core_since_last_complete: HashSet<CoreInternalFlags>,
36
+ lang_since_last_complete: HashSet<u32>,
37
+ }
38
+
39
+ impl InternalFlags {
40
+ pub fn new(server_capabilities: &get_system_info_response::Capabilities) -> Self {
41
+ Self {
42
+ enabled: server_capabilities.sdk_metadata,
43
+ core: Default::default(),
44
+ lang: Default::default(),
45
+ core_since_last_complete: Default::default(),
46
+ lang_since_last_complete: Default::default(),
47
+ }
48
+ }
49
+
50
+ #[cfg(test)]
51
+ pub fn all_core_enabled() -> Self {
52
+ Self {
53
+ enabled: true,
54
+ core: BTreeSet::from([
55
+ CoreInternalFlags::IdAndTypeDeterminismChecks,
56
+ CoreInternalFlags::UpsertSearchAttributeOnPatch,
57
+ ]),
58
+ lang: Default::default(),
59
+ core_since_last_complete: Default::default(),
60
+ lang_since_last_complete: Default::default(),
61
+ }
62
+ }
63
+
64
+ pub fn add_from_complete(&mut self, e: &WorkflowTaskCompletedEventAttributes) {
65
+ if !self.enabled {
66
+ return;
67
+ }
68
+
69
+ if let Some(metadata) = e.sdk_metadata.as_ref() {
70
+ self.core.extend(
71
+ metadata
72
+ .core_used_flags
73
+ .iter()
74
+ .map(|u| CoreInternalFlags::from_u32(*u)),
75
+ );
76
+ self.lang.extend(metadata.lang_used_flags.iter());
77
+ }
78
+ }
79
+
80
+ pub fn add_lang_used(&mut self, flags: impl IntoIterator<Item = u32>) {
81
+ if !self.enabled {
82
+ return;
83
+ }
84
+
85
+ self.lang_since_last_complete.extend(flags.into_iter());
86
+ }
87
+
88
+ /// Returns true if this flag may currently be used. If `should_record` is true, always returns
89
+ /// true and records the flag as being used, for taking later via
90
+ /// [Self::gather_for_wft_complete].
91
+ pub fn try_use(&mut self, core_patch: CoreInternalFlags, should_record: bool) -> bool {
92
+ if !self.enabled {
93
+ // If the server does not support the metadata field, we must assume we can never use
94
+ // any internal flags since they can't be recorded for future use
95
+ return false;
96
+ }
97
+
98
+ if should_record {
99
+ self.core_since_last_complete.insert(core_patch);
100
+ true
101
+ } else {
102
+ self.core.contains(&core_patch)
103
+ }
104
+ }
105
+
106
+ /// Wipes the recorded flags used during the current WFT and returns a partially filled
107
+ /// sdk metadata message that can be combined with any existing data before sending the WFT
108
+ /// complete
109
+ pub fn gather_for_wft_complete(&mut self) -> WorkflowTaskCompletedMetadata {
110
+ WorkflowTaskCompletedMetadata {
111
+ core_used_flags: self
112
+ .core_since_last_complete
113
+ .drain()
114
+ .map(|p| p as u32)
115
+ .collect(),
116
+ lang_used_flags: self.lang_since_last_complete.drain().collect(),
117
+ }
118
+ }
119
+
120
+ pub fn all_lang(&self) -> &BTreeSet<u32> {
121
+ &self.lang
122
+ }
123
+ }
124
+
125
+ impl CoreInternalFlags {
126
+ fn from_u32(v: u32) -> Self {
127
+ match v {
128
+ 1 => Self::IdAndTypeDeterminismChecks,
129
+ 2 => Self::UpsertSearchAttributeOnPatch,
130
+ _ => Self::TooHigh,
131
+ }
132
+ }
133
+ }
134
+
135
+ #[cfg(test)]
136
+ mod tests {
137
+ use super::*;
138
+ use temporal_sdk_core_protos::temporal::api::workflowservice::v1::get_system_info_response::Capabilities;
139
+
140
+ #[test]
141
+ fn disabled_in_capabilities_disables() {
142
+ let mut f = InternalFlags::new(&Capabilities::default());
143
+ f.add_lang_used([1]);
144
+ f.add_from_complete(&WorkflowTaskCompletedEventAttributes {
145
+ sdk_metadata: Some(WorkflowTaskCompletedMetadata {
146
+ core_used_flags: vec![1],
147
+ lang_used_flags: vec![],
148
+ }),
149
+ ..Default::default()
150
+ });
151
+ let gathered = f.gather_for_wft_complete();
152
+ assert_matches!(gathered.core_used_flags.as_slice(), &[]);
153
+ assert_matches!(gathered.lang_used_flags.as_slice(), &[]);
154
+ }
155
+ }
@@ -13,6 +13,7 @@ extern crate core;
13
13
 
14
14
  mod abstractions;
15
15
  pub mod ephemeral_server;
16
+ mod internal_flags;
16
17
  mod pollers;
17
18
  mod protosext;
18
19
  pub mod replay;
@@ -36,13 +37,16 @@ pub use temporal_sdk_core_api as api;
36
37
  pub use temporal_sdk_core_protos as protos;
37
38
  pub use temporal_sdk_core_protos::TaskToken;
38
39
  pub use url::Url;
40
+ #[cfg(feature = "save_wf_inputs")]
41
+ pub use worker::replay_wf_state_inputs;
39
42
  pub use worker::{Worker, WorkerConfig, WorkerConfigBuilder};
40
43
 
41
44
  use crate::{
42
45
  replay::{mock_client_from_histories, Historator, HistoryForReplay},
43
46
  telemetry::{
44
- metrics::MetricsContext, remove_trace_subscriber_for_current_thread,
45
- set_trace_subscriber_for_current_thread, telemetry_init, TelemetryInstance,
47
+ metrics::{MetricsContext, TemporalMeter},
48
+ remove_trace_subscriber_for_current_thread, set_trace_subscriber_for_current_thread,
49
+ telemetry_init, TelemetryInstance,
46
50
  },
47
51
  worker::client::WorkerClientBag,
48
52
  };
@@ -51,7 +55,7 @@ use std::sync::Arc;
51
55
  use temporal_client::{ConfiguredClient, TemporalServiceClientWithMetrics};
52
56
  use temporal_sdk_core_api::{
53
57
  errors::{CompleteActivityError, PollActivityError, PollWfError},
54
- telemetry::{CoreTelemetry, TelemetryOptions},
58
+ telemetry::TelemetryOptions,
55
59
  Worker as WorkerTrait,
56
60
  };
57
61
  use temporal_sdk_core_protos::coresdk::ActivityHeartbeat;
@@ -62,7 +66,7 @@ use temporal_sdk_core_protos::coresdk::ActivityHeartbeat;
62
66
  /// After the worker is initialized, you should use [CoreRuntime::tokio_handle] to run the worker's
63
67
  /// async functions.
64
68
  ///
65
- /// Lang implementations may pass in a [temporal_client::ConfiguredClient] directly (or a
69
+ /// Lang implementations may pass in a [ConfiguredClient] directly (or a
66
70
  /// [RetryClient] wrapping one, or a handful of other variants of the same idea). When they do so,
67
71
  /// this function will always overwrite the client retry configuration, force the client to use the
68
72
  /// namespace defined in the worker config, and set the client identity appropriately. IE: Use
@@ -97,9 +101,12 @@ where
97
101
  worker_config.use_worker_versioning,
98
102
  ));
99
103
 
100
- let metrics = MetricsContext::top_level(worker_config.namespace.clone(), &runtime.telemetry)
101
- .with_task_q(worker_config.task_queue.clone());
102
- Ok(Worker::new(worker_config, sticky_q, client_bag, metrics))
104
+ Ok(Worker::new(
105
+ worker_config,
106
+ sticky_q,
107
+ client_bag,
108
+ Some(&runtime.telemetry),
109
+ ))
103
110
  }
104
111
 
105
112
  /// Create a worker for replaying a specific history. It will auto-shutdown as soon as the history
@@ -126,7 +133,7 @@ where
126
133
  let post_activate = historator.get_post_activate_hook();
127
134
  let shutdown_tok = historator.get_shutdown_setter();
128
135
  let client = mock_client_from_histories(historator);
129
- let mut worker = Worker::new(config, None, Arc::new(client), MetricsContext::no_op());
136
+ let mut worker = Worker::new(config, None, Arc::new(client), None);
130
137
  worker.set_post_activate_hook(post_activate);
131
138
  shutdown_tok(worker.shutdown_token());
132
139
  Ok(worker)
@@ -258,7 +265,7 @@ impl CoreRuntime {
258
265
  }
259
266
 
260
267
  /// Returns the metric meter used for recording metrics, if they were enabled.
261
- pub fn metric_meter(&self) -> Option<&opentelemetry::metrics::Meter> {
268
+ pub fn metric_meter(&self) -> Option<TemporalMeter> {
262
269
  self.telemetry.get_metric_meter()
263
270
  }
264
271
 
@@ -274,7 +274,7 @@ impl TryFrom<activity_execution_result::Status> for LocalActivityExecutionResult
274
274
  Status::Failed(f)
275
275
  if f.failure
276
276
  .as_ref()
277
- .map(|fail| fail.is_timeout())
277
+ .map(|fail| fail.is_timeout().is_some())
278
278
  .unwrap_or_default() =>
279
279
  {
280
280
  Ok(LocalActivityExecutionResult::TimedOut(f))
@@ -3,14 +3,16 @@
3
3
  //! users during testing.
4
4
 
5
5
  use crate::{
6
- worker::client::{mocks::mock_manual_workflow_client, WorkerClient},
6
+ worker::{
7
+ client::{mocks::mock_manual_workflow_client, WorkerClient},
8
+ PostActivateHookData,
9
+ },
7
10
  Worker,
8
11
  };
9
12
  use futures::{FutureExt, Stream, StreamExt};
10
13
  use once_cell::sync::OnceCell;
11
14
  use parking_lot::Mutex;
12
15
  use std::{
13
- collections::HashMap,
14
16
  pin::Pin,
15
17
  sync::Arc,
16
18
  task::{Context, Poll},
@@ -147,25 +149,18 @@ impl Historator {
147
149
 
148
150
  /// Returns a callback that can be used as the post-activation hook for a worker to indicate
149
151
  /// we're ready to replay the next history, or whatever else.
150
- pub(crate) fn get_post_activate_hook(&self) -> impl Fn(&Worker, &str, usize) + Send + Sync {
151
- let dat = self.dat.clone();
152
+ pub(crate) fn get_post_activate_hook(
153
+ &self,
154
+ ) -> impl Fn(&Worker, PostActivateHookData) + Send + Sync {
152
155
  let done_tx = self.replay_done_tx.clone();
153
- move |worker, activated_run_id, last_processed_event| {
154
- // We can't hold the lock while evaluating the hook, or we'd deadlock.
155
- let last_event_in_hist = dat
156
- .lock()
157
- .run_id_to_last_event_num
158
- .get(activated_run_id)
159
- .cloned();
160
- if let Some(le) = last_event_in_hist {
161
- if last_processed_event >= le {
162
- worker.request_wf_eviction(
163
- activated_run_id,
164
- "Always evict workflows after replay",
165
- EvictionReason::LangRequested,
166
- );
167
- done_tx.send(activated_run_id.to_string()).unwrap();
168
- }
156
+ move |worker, data| {
157
+ if !data.replaying {
158
+ worker.request_wf_eviction(
159
+ data.run_id,
160
+ "Always evict workflows after replay",
161
+ EvictionReason::LangRequested,
162
+ );
163
+ done_tx.send(data.run_id.to_string()).unwrap();
169
164
  }
170
165
  }
171
166
  }
@@ -184,7 +179,7 @@ impl Stream for Historator {
184
179
  fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
185
180
  match self.iter.poll_next_unpin(cx) {
186
181
  Poll::Ready(Some(history)) => {
187
- let run_id = history
182
+ history
188
183
  .hist
189
184
  .extract_run_id_from_start()
190
185
  .expect(
@@ -192,11 +187,6 @@ impl Stream for Historator {
192
187
  execution started events",
193
188
  )
194
189
  .to_string();
195
- let last_event = history.hist.last_event_id();
196
- self.dat
197
- .lock()
198
- .run_id_to_last_event_num
199
- .insert(run_id, last_event as usize);
200
190
  Poll::Ready(Some(history))
201
191
  }
202
192
  Poll::Ready(None) => {
@@ -210,6 +200,5 @@ impl Stream for Historator {
210
200
 
211
201
  #[derive(Default)]
212
202
  struct HistoratorDat {
213
- run_id_to_last_event_num: HashMap<String, usize>,
214
203
  all_dispatched: bool,
215
204
  }
@@ -139,7 +139,7 @@ impl<'a> tracing::field::Visit for JsonVisitor<'a> {
139
139
  fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn std::fmt::Debug) {
140
140
  self.0.insert(
141
141
  field.name().to_string(),
142
- serde_json::json!(format!("{:?}", value)),
142
+ serde_json::json!(format!("{value:?}")),
143
143
  );
144
144
  }
145
145
  }