@temporalio/core-bridge 1.11.6 → 1.11.8

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 (191) hide show
  1. package/Cargo.lock +902 -468
  2. package/package.json +3 -3
  3. package/releases/aarch64-apple-darwin/index.node +0 -0
  4. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  5. package/releases/x86_64-apple-darwin/index.node +0 -0
  6. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  7. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  8. package/sdk-core/.cargo/config.toml +5 -0
  9. package/sdk-core/.github/workflows/per-pr.yml +59 -5
  10. package/sdk-core/Cargo.toml +3 -2
  11. package/sdk-core/client/Cargo.toml +3 -3
  12. package/sdk-core/client/src/lib.rs +154 -161
  13. package/sdk-core/client/src/metrics.rs +15 -8
  14. package/sdk-core/client/src/proxy.rs +1 -1
  15. package/sdk-core/client/src/raw.rs +176 -33
  16. package/sdk-core/client/src/retry.rs +102 -465
  17. package/sdk-core/client/src/worker_registry/mod.rs +2 -2
  18. package/sdk-core/client/src/workflow_handle/mod.rs +19 -1
  19. package/sdk-core/core/Cargo.toml +12 -14
  20. package/sdk-core/core/benches/workflow_replay.rs +1 -1
  21. package/sdk-core/core/src/abstractions.rs +2 -2
  22. package/sdk-core/core/src/core_tests/activity_tasks.rs +99 -46
  23. package/sdk-core/core/src/core_tests/child_workflows.rs +68 -9
  24. package/sdk-core/core/src/core_tests/determinism.rs +2 -2
  25. package/sdk-core/core/src/core_tests/local_activities.rs +20 -33
  26. package/sdk-core/core/src/core_tests/mod.rs +7 -8
  27. package/sdk-core/core/src/core_tests/queries.rs +79 -79
  28. package/sdk-core/core/src/core_tests/replay_flag.rs +5 -5
  29. package/sdk-core/core/src/core_tests/updates.rs +6 -6
  30. package/sdk-core/core/src/core_tests/workers.rs +19 -22
  31. package/sdk-core/core/src/core_tests/workflow_cancels.rs +3 -3
  32. package/sdk-core/core/src/core_tests/workflow_tasks.rs +154 -106
  33. package/sdk-core/core/src/ephemeral_server/mod.rs +66 -10
  34. package/sdk-core/core/src/internal_flags.rs +103 -12
  35. package/sdk-core/core/src/lib.rs +21 -13
  36. package/sdk-core/core/src/pollers/mod.rs +200 -6
  37. package/sdk-core/core/src/pollers/poll_buffer.rs +32 -8
  38. package/sdk-core/core/src/protosext/mod.rs +7 -7
  39. package/sdk-core/core/src/protosext/protocol_messages.rs +2 -2
  40. package/sdk-core/core/src/replay/mod.rs +8 -9
  41. package/sdk-core/core/src/retry_logic.rs +8 -6
  42. package/sdk-core/core/src/telemetry/log_export.rs +4 -4
  43. package/sdk-core/core/src/telemetry/metrics.rs +111 -25
  44. package/sdk-core/core/src/telemetry/mod.rs +11 -4
  45. package/sdk-core/core/src/telemetry/otel.rs +108 -144
  46. package/sdk-core/core/src/telemetry/prometheus_server.rs +1 -4
  47. package/sdk-core/core/src/test_help/mod.rs +27 -21
  48. package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +7 -5
  49. package/sdk-core/core/src/worker/activities/local_activities.rs +9 -9
  50. package/sdk-core/core/src/worker/activities.rs +34 -46
  51. package/sdk-core/core/src/worker/client/mocks.rs +24 -2
  52. package/sdk-core/core/src/worker/client.rs +169 -33
  53. package/sdk-core/core/src/worker/mod.rs +132 -56
  54. package/sdk-core/core/src/worker/nexus.rs +410 -0
  55. package/sdk-core/core/src/worker/tuner/resource_based.rs +27 -5
  56. package/sdk-core/core/src/worker/tuner.rs +29 -2
  57. package/sdk-core/core/src/worker/workflow/driven_workflow.rs +8 -3
  58. package/sdk-core/core/src/worker/workflow/history_update.rs +5 -8
  59. package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +83 -87
  60. package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +38 -38
  61. package/sdk-core/core/src/worker/workflow/machines/cancel_nexus_op_state_machine.rs +117 -0
  62. package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +8 -18
  63. package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +114 -108
  64. package/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +16 -31
  65. package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +7 -14
  66. package/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +8 -15
  67. package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +34 -75
  68. package/sdk-core/core/src/worker/workflow/machines/mod.rs +26 -48
  69. package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +10 -17
  70. package/sdk-core/core/src/worker/workflow/machines/nexus_operation_state_machine.rs +543 -0
  71. package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +22 -31
  72. package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +53 -51
  73. package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +40 -45
  74. package/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +2 -2
  75. package/sdk-core/core/src/worker/workflow/machines/update_state_machine.rs +8 -10
  76. package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +24 -30
  77. package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +182 -116
  78. package/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +4 -8
  79. package/sdk-core/core/src/worker/workflow/managed_run.rs +75 -45
  80. package/sdk-core/core/src/worker/workflow/mod.rs +104 -55
  81. package/sdk-core/core/src/worker/workflow/run_cache.rs +23 -4
  82. package/sdk-core/core/src/worker/workflow/wft_extraction.rs +4 -4
  83. package/sdk-core/core/src/worker/workflow/wft_poller.rs +3 -3
  84. package/sdk-core/core/src/worker/workflow/workflow_stream.rs +32 -13
  85. package/sdk-core/core-api/Cargo.toml +2 -3
  86. package/sdk-core/core-api/src/errors.rs +22 -20
  87. package/sdk-core/core-api/src/lib.rs +24 -5
  88. package/sdk-core/core-api/src/telemetry/metrics.rs +27 -1
  89. package/sdk-core/core-api/src/telemetry.rs +37 -3
  90. package/sdk-core/core-api/src/worker.rs +36 -3
  91. package/sdk-core/docker/docker-compose-ci.yaml +25 -0
  92. package/sdk-core/etc/otel-collector-ci.yaml +36 -0
  93. package/sdk-core/etc/otel-collector-config.yaml +3 -3
  94. package/sdk-core/etc/prometheus.yaml +1 -1
  95. package/sdk-core/fsm/Cargo.toml +1 -1
  96. package/sdk-core/fsm/rustfsm_procmacro/Cargo.toml +1 -1
  97. package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +3 -4
  98. package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +1 -1
  99. package/sdk-core/fsm/rustfsm_trait/Cargo.toml +1 -1
  100. package/sdk-core/sdk/Cargo.toml +1 -2
  101. package/sdk-core/sdk/src/activity_context.rs +1 -1
  102. package/sdk-core/sdk/src/interceptors.rs +1 -1
  103. package/sdk-core/sdk/src/lib.rs +126 -54
  104. package/sdk-core/sdk/src/workflow_context/options.rs +184 -74
  105. package/sdk-core/sdk/src/workflow_context.rs +193 -79
  106. package/sdk-core/sdk/src/workflow_future.rs +151 -131
  107. package/sdk-core/sdk-core-protos/Cargo.toml +3 -4
  108. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/VERSION +1 -1
  109. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/account/v1/message.proto +46 -0
  110. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/request_response.proto +254 -5
  111. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/service.proto +108 -2
  112. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/identity/v1/message.proto +94 -15
  113. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/namespace/v1/message.proto +102 -4
  114. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/nexus/v1/message.proto +84 -0
  115. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/operation/v1/message.proto +25 -10
  116. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/region/v1/message.proto +14 -1
  117. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/resource/v1/message.proto +25 -0
  118. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/sink/v1/message.proto +41 -0
  119. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/usage/v1/message.proto +59 -0
  120. package/sdk-core/sdk-core-protos/protos/api_upstream/.github/PULL_REQUEST_TEMPLATE.md +2 -0
  121. package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/create-release.yml +135 -0
  122. package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/push-to-buf.yml +20 -0
  123. package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/trigger-api-go-delete-release.yml +13 -0
  124. package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/trigger-api-go-publish-release.yml +13 -0
  125. package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/trigger-api-go-update.yml +13 -21
  126. package/sdk-core/sdk-core-protos/protos/api_upstream/Makefile +2 -2
  127. package/sdk-core/sdk-core-protos/protos/api_upstream/buf.yaml +1 -0
  128. package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv2.json +3386 -1047
  129. package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv3.yaml +3529 -1144
  130. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/batch/v1/message.proto +39 -1
  131. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/command/v1/message.proto +6 -0
  132. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/common/v1/message.proto +39 -1
  133. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/deployment/v1/message.proto +252 -0
  134. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +1 -0
  135. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/common.proto +6 -0
  136. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/deployment.proto +96 -0
  137. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/event_type.proto +2 -0
  138. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +2 -0
  139. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/nexus.proto +42 -0
  140. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/reset.proto +2 -0
  141. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/workflow.proto +43 -2
  142. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/errordetails/v1/message.proto +13 -1
  143. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/failure/v1/message.proto +14 -0
  144. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/history/v1/message.proto +70 -12
  145. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/nexus/v1/message.proto +12 -0
  146. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/query/v1/message.proto +9 -2
  147. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +46 -2
  148. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflow/v1/message.proto +206 -0
  149. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +482 -97
  150. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +230 -43
  151. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/core_interface.proto +6 -0
  152. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/nexus/nexus.proto +71 -0
  153. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +46 -2
  154. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +55 -9
  155. package/sdk-core/sdk-core-protos/src/history_builder.rs +5 -5
  156. package/sdk-core/sdk-core-protos/src/history_info.rs +5 -6
  157. package/sdk-core/sdk-core-protos/src/lib.rs +414 -34
  158. package/sdk-core/sdk-core-protos/src/task_token.rs +1 -1
  159. package/sdk-core/test-utils/Cargo.toml +3 -11
  160. package/sdk-core/test-utils/src/canned_histories.rs +1 -1
  161. package/sdk-core/test-utils/src/lib.rs +159 -85
  162. package/sdk-core/tests/fuzzy_workflow.rs +3 -3
  163. package/sdk-core/tests/heavy_tests.rs +3 -3
  164. package/sdk-core/tests/integ_tests/client_tests.rs +171 -20
  165. package/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +45 -39
  166. package/sdk-core/tests/integ_tests/heartbeat_tests.rs +7 -6
  167. package/sdk-core/tests/integ_tests/metrics_tests.rs +492 -35
  168. package/sdk-core/tests/integ_tests/polling_tests.rs +7 -5
  169. package/sdk-core/tests/integ_tests/queries_tests.rs +14 -17
  170. package/sdk-core/tests/integ_tests/update_tests.rs +47 -44
  171. package/sdk-core/tests/integ_tests/visibility_tests.rs +4 -3
  172. package/sdk-core/tests/integ_tests/worker_tests.rs +5 -5
  173. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +15 -13
  174. package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +28 -14
  175. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +7 -1
  176. package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +57 -4
  177. package/sdk-core/tests/integ_tests/workflow_tests/eager.rs +1 -1
  178. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +24 -18
  179. package/sdk-core/tests/integ_tests/workflow_tests/nexus.rs +506 -0
  180. package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +1 -1
  181. package/sdk-core/tests/integ_tests/workflow_tests/priority.rs +104 -0
  182. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +34 -31
  183. package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +1 -1
  184. package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +10 -7
  185. package/sdk-core/tests/integ_tests/workflow_tests.rs +152 -116
  186. package/sdk-core/tests/main.rs +36 -6
  187. package/sdk-core/tests/runner.rs +30 -9
  188. package/src/conversions/slot_supplier_bridge.rs +4 -0
  189. package/src/conversions.rs +1 -0
  190. package/src/worker.rs +5 -7
  191. package/sdk-core/core/src/worker/activities/activity_task_poller_stream.rs +0 -78
@@ -47,25 +47,44 @@ pub(crate) enum InternalFlags {
47
47
  lang: BTreeSet<u32>,
48
48
  core_since_last_complete: HashSet<CoreInternalFlags>,
49
49
  lang_since_last_complete: HashSet<u32>,
50
+ last_sdk_name: String,
51
+ last_sdk_version: String,
52
+ sdk_name: String,
53
+ sdk_version: String,
50
54
  },
51
55
  Disabled,
52
56
  }
53
57
 
54
58
  impl InternalFlags {
55
- pub(crate) fn new(server_capabilities: &get_system_info_response::Capabilities) -> Self {
59
+ pub(crate) fn new(
60
+ server_capabilities: &get_system_info_response::Capabilities,
61
+ sdk_name: String,
62
+ sdk_version: String,
63
+ ) -> Self {
56
64
  match server_capabilities.sdk_metadata {
57
65
  true => Self::Enabled {
58
66
  core: Default::default(),
59
67
  lang: Default::default(),
60
68
  core_since_last_complete: Default::default(),
61
69
  lang_since_last_complete: Default::default(),
70
+ last_sdk_name: "".to_string(),
71
+ last_sdk_version: "".to_string(),
72
+ sdk_name,
73
+ sdk_version,
62
74
  },
63
75
  false => Self::Disabled,
64
76
  }
65
77
  }
66
78
 
67
79
  pub(crate) fn add_from_complete(&mut self, e: &WorkflowTaskCompletedEventAttributes) {
68
- if let Self::Enabled { core, lang, .. } = self {
80
+ if let Self::Enabled {
81
+ core,
82
+ lang,
83
+ last_sdk_name,
84
+ last_sdk_version,
85
+ ..
86
+ } = self
87
+ {
69
88
  if let Some(metadata) = e.sdk_metadata.as_ref() {
70
89
  core.extend(
71
90
  metadata
@@ -74,6 +93,12 @@ impl InternalFlags {
74
93
  .map(|u| CoreInternalFlags::from_u32(*u)),
75
94
  );
76
95
  lang.extend(metadata.lang_used_flags.iter());
96
+ if !metadata.sdk_name.is_empty() {
97
+ *last_sdk_name = metadata.sdk_name.clone();
98
+ }
99
+ if !metadata.sdk_version.is_empty() {
100
+ *last_sdk_version = metadata.sdk_version.clone();
101
+ }
77
102
  }
78
103
  }
79
104
  }
@@ -133,6 +158,10 @@ impl InternalFlags {
133
158
  lang_since_last_complete,
134
159
  core,
135
160
  lang,
161
+ last_sdk_name,
162
+ last_sdk_version,
163
+ sdk_name,
164
+ sdk_version,
136
165
  } => {
137
166
  let core_newly_used: Vec<_> = core_since_last_complete
138
167
  .iter()
@@ -146,11 +175,21 @@ impl InternalFlags {
146
175
  .collect();
147
176
  core.extend(core_since_last_complete.iter());
148
177
  lang.extend(lang_since_last_complete.iter());
178
+ let sdk_name = if last_sdk_name != sdk_name {
179
+ sdk_name.clone()
180
+ } else {
181
+ "".to_string()
182
+ };
183
+ let sdk_version = if last_sdk_version != sdk_version {
184
+ sdk_version.clone()
185
+ } else {
186
+ "".to_string()
187
+ };
149
188
  WorkflowTaskCompletedMetadata {
150
189
  core_used_flags: core_newly_used,
151
190
  lang_used_flags: lang_newly_used,
152
- sdk_name: "".to_string(),
153
- sdk_version: "".to_string(),
191
+ sdk_name,
192
+ sdk_version,
154
193
  }
155
194
  }
156
195
  Self::Disabled => WorkflowTaskCompletedMetadata::default(),
@@ -186,9 +225,19 @@ mod tests {
186
225
  use super::*;
187
226
  use temporal_sdk_core_protos::temporal::api::workflowservice::v1::get_system_info_response::Capabilities;
188
227
 
228
+ impl Default for InternalFlags {
229
+ fn default() -> Self {
230
+ Self::Disabled
231
+ }
232
+ }
233
+
189
234
  #[test]
190
235
  fn disabled_in_capabilities_disables() {
191
- let mut f = InternalFlags::new(&Capabilities::default());
236
+ let mut f = InternalFlags::new(
237
+ &Capabilities::default(),
238
+ "name".to_string(),
239
+ "ver".to_string(),
240
+ );
192
241
  f.add_lang_used([1]);
193
242
  f.add_from_complete(&WorkflowTaskCompletedEventAttributes {
194
243
  sdk_metadata: Some(WorkflowTaskCompletedMetadata {
@@ -214,23 +263,29 @@ mod tests {
214
263
  }
215
264
 
216
265
  #[test]
217
- fn only_writes_new_flags() {
218
- let mut f = InternalFlags::new(&Capabilities {
219
- sdk_metadata: true,
220
- ..Default::default()
221
- });
266
+ fn only_writes_new_flags_and_sdk_info() {
267
+ let mut f = InternalFlags::new(
268
+ &Capabilities {
269
+ sdk_metadata: true,
270
+ ..Default::default()
271
+ },
272
+ "name".to_string(),
273
+ "ver".to_string(),
274
+ );
222
275
  f.add_lang_used([1]);
223
276
  f.try_use(CoreInternalFlags::IdAndTypeDeterminismChecks, true);
224
277
  let gathered = f.gather_for_wft_complete();
225
278
  assert_matches!(gathered.core_used_flags.as_slice(), &[1]);
226
279
  assert_matches!(gathered.lang_used_flags.as_slice(), &[1]);
280
+ assert_matches!(gathered.sdk_name.as_str(), "name");
281
+ assert_matches!(gathered.sdk_version.as_str(), "ver");
227
282
 
228
283
  f.add_from_complete(&WorkflowTaskCompletedEventAttributes {
229
284
  sdk_metadata: Some(WorkflowTaskCompletedMetadata {
230
285
  core_used_flags: vec![2],
231
286
  lang_used_flags: vec![2],
232
- sdk_name: "".to_string(),
233
- sdk_version: "".to_string(),
287
+ sdk_name: "name".to_string(),
288
+ sdk_version: "ver".to_string(),
234
289
  }),
235
290
  ..Default::default()
236
291
  });
@@ -239,5 +294,41 @@ mod tests {
239
294
  let gathered = f.gather_for_wft_complete();
240
295
  assert_matches!(gathered.core_used_flags.as_slice(), &[]);
241
296
  assert_matches!(gathered.lang_used_flags.as_slice(), &[]);
297
+ assert!(gathered.sdk_name.is_empty());
298
+ assert!(gathered.sdk_version.is_empty());
299
+
300
+ f.add_from_complete(&WorkflowTaskCompletedEventAttributes {
301
+ sdk_metadata: Some(WorkflowTaskCompletedMetadata::default()),
302
+ ..Default::default()
303
+ });
304
+ let gathered = f.gather_for_wft_complete();
305
+ assert_matches!(gathered.core_used_flags.as_slice(), &[]);
306
+ assert_matches!(gathered.lang_used_flags.as_slice(), &[]);
307
+ assert!(gathered.sdk_name.is_empty());
308
+ assert!(gathered.sdk_version.is_empty());
309
+
310
+ f.add_from_complete(&WorkflowTaskCompletedEventAttributes {
311
+ sdk_metadata: Some(WorkflowTaskCompletedMetadata {
312
+ sdk_name: "other sdk".to_string(),
313
+ sdk_version: "other ver".to_string(),
314
+ ..Default::default()
315
+ }),
316
+ ..Default::default()
317
+ });
318
+ let gathered = f.gather_for_wft_complete();
319
+ assert_matches!(gathered.sdk_name.as_str(), "name");
320
+ assert_matches!(gathered.sdk_version.as_str(), "ver");
321
+
322
+ f.add_from_complete(&WorkflowTaskCompletedEventAttributes {
323
+ sdk_metadata: Some(WorkflowTaskCompletedMetadata {
324
+ sdk_name: "name".to_string(),
325
+ sdk_version: "ver2".to_string(),
326
+ ..Default::default()
327
+ }),
328
+ ..Default::default()
329
+ });
330
+ let gathered = f.gather_for_wft_complete();
331
+ assert!(gathered.sdk_name.is_empty());
332
+ assert_matches!(gathered.sdk_version.as_str(), "ver");
242
333
  }
243
334
  }
@@ -50,19 +50,19 @@ pub use worker::{
50
50
  use crate::{
51
51
  replay::{HistoryForReplay, ReplayWorkerInput},
52
52
  telemetry::{
53
- metrics::MetricsContext, remove_trace_subscriber_for_current_thread,
54
- set_trace_subscriber_for_current_thread, telemetry_init, TelemetryInstance,
53
+ TelemetryInstance, metrics::MetricsContext, remove_trace_subscriber_for_current_thread,
54
+ set_trace_subscriber_for_current_thread, telemetry_init,
55
55
  },
56
56
  worker::client::WorkerClientBag,
57
57
  };
58
58
  use anyhow::bail;
59
59
  use futures_util::Stream;
60
60
  use std::sync::Arc;
61
- use temporal_client::{ConfiguredClient, TemporalServiceClientWithMetrics};
61
+ use temporal_client::{ConfiguredClient, NamespacedClient, TemporalServiceClientWithMetrics};
62
62
  use temporal_sdk_core_api::{
63
- errors::{CompleteActivityError, PollActivityError, PollWfError},
64
- telemetry::TelemetryOptions,
65
63
  Worker as WorkerTrait,
64
+ errors::{CompleteActivityError, PollError},
65
+ telemetry::TelemetryOptions,
66
66
  };
67
67
  use temporal_sdk_core_protos::coresdk::ActivityHeartbeat;
68
68
 
@@ -90,9 +90,9 @@ where
90
90
  bail!("Passed in client is not bound to the same namespace as the worker");
91
91
  }
92
92
  if client.namespace() == "" {
93
- bail!("Namespace cannot be empty");
93
+ bail!("Client namespace cannot be empty");
94
94
  }
95
- let client_ident = client.get_options().identity.clone();
95
+ let client_ident = client.get_identity().to_owned();
96
96
  let sticky_q = sticky_q_name_for_worker(&client_ident, &worker_config);
97
97
  let client_bag = Arc::new(WorkerClientBag::new(
98
98
  client,
@@ -162,31 +162,39 @@ mod sealed {
162
162
  /// use-case was worker initialization.
163
163
  ///
164
164
  /// Needs to exist in this crate to avoid blanket impl conflicts.
165
- pub struct AnyClient(Box<ConfiguredClient<TemporalServiceClientWithMetrics>>);
165
+ pub struct AnyClient {
166
+ pub(crate) inner: Box<ConfiguredClient<TemporalServiceClientWithMetrics>>,
167
+ }
166
168
  impl AnyClient {
167
169
  pub(crate) fn into_inner(self) -> Box<ConfiguredClient<TemporalServiceClientWithMetrics>> {
168
- self.0
170
+ self.inner
169
171
  }
170
172
  }
171
173
 
172
174
  impl From<RetryClient<ConfiguredClient<TemporalServiceClientWithMetrics>>> for AnyClient {
173
175
  fn from(c: RetryClient<ConfiguredClient<TemporalServiceClientWithMetrics>>) -> Self {
174
- Self(Box::new(c.into_inner()))
176
+ Self {
177
+ inner: Box::new(c.into_inner()),
178
+ }
175
179
  }
176
180
  }
177
181
  impl From<RetryClient<Client>> for AnyClient {
178
182
  fn from(c: RetryClient<Client>) -> Self {
179
- Self(Box::new(c.into_inner().into_inner()))
183
+ Self {
184
+ inner: Box::new(c.into_inner().into_inner()),
185
+ }
180
186
  }
181
187
  }
182
188
  impl From<Arc<RetryClient<Client>>> for AnyClient {
183
189
  fn from(c: Arc<RetryClient<Client>>) -> Self {
184
- Self(Box::new(c.get_client().inner().clone()))
190
+ Self {
191
+ inner: Box::new(c.get_client().inner().clone()),
192
+ }
185
193
  }
186
194
  }
187
195
  impl From<ConfiguredClient<TemporalServiceClientWithMetrics>> for AnyClient {
188
196
  fn from(c: ConfiguredClient<TemporalServiceClientWithMetrics>) -> Self {
189
- Self(Box::new(c))
197
+ Self { inner: Box::new(c) }
190
198
  }
191
199
  }
192
200
  }
@@ -1,28 +1,35 @@
1
1
  mod poll_buffer;
2
2
 
3
3
  pub(crate) use poll_buffer::{
4
- new_activity_task_buffer, new_workflow_task_buffer, WorkflowTaskPoller,
4
+ WorkflowTaskPoller, new_activity_task_buffer, new_nexus_task_buffer, new_workflow_task_buffer,
5
5
  };
6
6
  pub use temporal_client::{
7
7
  Client, ClientOptions, ClientOptionsBuilder, ClientTlsConfig, RetryClient, RetryConfig,
8
8
  TlsConfig, WorkflowClientTrait,
9
9
  };
10
10
 
11
- use crate::abstractions::OwnedMeteredSemPermit;
11
+ use crate::{
12
+ abstractions::{OwnedMeteredSemPermit, TrackedOwnedMeteredSemPermit},
13
+ telemetry::metrics::MetricsContext,
14
+ };
15
+ use anyhow::{anyhow, bail};
16
+ use futures_util::{Stream, stream};
17
+ use std::{fmt::Debug, marker::PhantomData};
18
+ use temporal_sdk_core_api::worker::{ActivitySlotKind, NexusSlotKind, SlotKind, WorkflowSlotKind};
12
19
  use temporal_sdk_core_protos::temporal::api::workflowservice::v1::{
13
- PollActivityTaskQueueResponse, PollWorkflowTaskQueueResponse,
20
+ PollActivityTaskQueueResponse, PollNexusTaskQueueResponse, PollWorkflowTaskQueueResponse,
14
21
  };
22
+ use tokio::select;
23
+ use tokio_util::sync::CancellationToken;
15
24
 
16
25
  #[cfg(test)]
17
26
  use futures_util::Future;
18
27
  #[cfg(test)]
19
28
  pub(crate) use poll_buffer::MockPermittedPollBuffer;
20
- use temporal_sdk_core_api::worker::{ActivitySlotKind, WorkflowSlotKind};
21
29
 
22
30
  pub(crate) type Result<T, E = tonic::Status> = std::result::Result<T, E>;
23
31
 
24
- /// A trait for things that poll the server. Hides complexity of concurrent polling or polling
25
- /// on sticky/nonsticky queues simultaneously.
32
+ /// A trait for things that long poll the server.
26
33
  #[cfg_attr(test, mockall::automock)]
27
34
  #[cfg_attr(test, allow(unused))]
28
35
  #[async_trait::async_trait]
@@ -45,6 +52,10 @@ pub(crate) type BoxedActPoller = BoxedPoller<(
45
52
  PollActivityTaskQueueResponse,
46
53
  OwnedMeteredSemPermit<ActivitySlotKind>,
47
54
  )>;
55
+ pub(crate) type BoxedNexusPoller = BoxedPoller<(
56
+ PollNexusTaskQueueResponse,
57
+ OwnedMeteredSemPermit<NexusSlotKind>,
58
+ )>;
48
59
 
49
60
  #[async_trait::async_trait]
50
61
  impl<T> Poller<T> for Box<dyn Poller<T> + Send + Sync>
@@ -85,3 +96,186 @@ mockall::mock! {
85
96
  where Self: 'a;
86
97
  }
87
98
  }
99
+
100
+ #[derive(Debug)]
101
+ pub(crate) struct PermittedTqResp<T: ValidatableTask> {
102
+ pub(crate) permit: OwnedMeteredSemPermit<T::SlotKind>,
103
+ pub(crate) resp: T,
104
+ }
105
+
106
+ #[derive(Debug)]
107
+ pub(crate) struct TrackedPermittedTqResp<T: ValidatableTask> {
108
+ pub(crate) permit: TrackedOwnedMeteredSemPermit<T::SlotKind>,
109
+ pub(crate) resp: T,
110
+ }
111
+
112
+ pub(crate) trait ValidatableTask:
113
+ Debug + Default + PartialEq + Send + Sync + 'static
114
+ {
115
+ type SlotKind: SlotKind;
116
+
117
+ fn validate(&self) -> Result<(), anyhow::Error>;
118
+ fn task_name() -> &'static str;
119
+ }
120
+
121
+ pub(crate) struct TaskPollerStream<P, T>
122
+ where
123
+ P: Poller<(T, OwnedMeteredSemPermit<T::SlotKind>)>,
124
+ T: ValidatableTask,
125
+ {
126
+ poller: P,
127
+ metrics: MetricsContext,
128
+ metrics_no_task: fn(&MetricsContext),
129
+ shutdown_token: CancellationToken,
130
+ poller_was_shutdown: bool,
131
+ _phantom: PhantomData<T>,
132
+ }
133
+
134
+ impl<P, T> TaskPollerStream<P, T>
135
+ where
136
+ P: Poller<(T, OwnedMeteredSemPermit<T::SlotKind>)>,
137
+ T: ValidatableTask,
138
+ {
139
+ pub(crate) fn new(
140
+ poller: P,
141
+ metrics: MetricsContext,
142
+ metrics_no_task: fn(&MetricsContext),
143
+ shutdown_token: CancellationToken,
144
+ ) -> Self {
145
+ Self {
146
+ poller,
147
+ metrics,
148
+ metrics_no_task,
149
+ shutdown_token,
150
+ poller_was_shutdown: false,
151
+ _phantom: PhantomData,
152
+ }
153
+ }
154
+
155
+ fn into_stream(self) -> impl Stream<Item = Result<PermittedTqResp<T>, tonic::Status>> {
156
+ stream::unfold(self, |mut state| async move {
157
+ loop {
158
+ let poll = async {
159
+ loop {
160
+ return match state.poller.poll().await {
161
+ Some(Ok((task, permit))) => {
162
+ if task == Default::default() {
163
+ // We get the default proto in the event that the long poll
164
+ // times out.
165
+ debug!("Poll {} task timeout", T::task_name());
166
+ (state.metrics_no_task)(&state.metrics);
167
+ continue;
168
+ }
169
+
170
+ if let Err(e) = task.validate() {
171
+ warn!(
172
+ "Received invalid {} task ({}): {:?}",
173
+ T::task_name(),
174
+ e,
175
+ &task
176
+ );
177
+ return Some(Err(tonic::Status::invalid_argument(
178
+ e.to_string(),
179
+ )));
180
+ }
181
+
182
+ Some(Ok(PermittedTqResp { resp: task, permit }))
183
+ }
184
+ Some(Err(e)) => {
185
+ warn!(error=?e, "Error while polling for {} tasks", T::task_name());
186
+ Some(Err(e))
187
+ }
188
+ // If poller returns None, it's dead, thus we also return None to
189
+ // terminate this stream.
190
+ None => None,
191
+ };
192
+ }
193
+ };
194
+ if state.poller_was_shutdown {
195
+ return poll.await.map(|res| (res, state));
196
+ }
197
+ select! {
198
+ biased;
199
+
200
+ _ = state.shutdown_token.cancelled() => {
201
+ state.poller.notify_shutdown();
202
+ state.poller_was_shutdown = true;
203
+ continue;
204
+ }
205
+ res = poll => {
206
+ return res.map(|res| (res, state));
207
+ }
208
+ }
209
+ }
210
+ })
211
+ }
212
+ }
213
+
214
+ impl ValidatableTask for PollActivityTaskQueueResponse {
215
+ type SlotKind = ActivitySlotKind;
216
+
217
+ fn validate(&self) -> Result<(), anyhow::Error> {
218
+ if self.task_token.is_empty() {
219
+ return Err(anyhow!("missing task token"));
220
+ }
221
+ Ok(())
222
+ }
223
+
224
+ fn task_name() -> &'static str {
225
+ "activity"
226
+ }
227
+ }
228
+
229
+ pub(crate) fn new_activity_task_poller(
230
+ poller: BoxedActPoller,
231
+ metrics: MetricsContext,
232
+ shutdown_token: CancellationToken,
233
+ ) -> impl Stream<Item = Result<PermittedTqResp<PollActivityTaskQueueResponse>, tonic::Status>> {
234
+ TaskPollerStream::new(
235
+ poller,
236
+ metrics,
237
+ MetricsContext::act_poll_timeout,
238
+ shutdown_token,
239
+ )
240
+ .into_stream()
241
+ }
242
+
243
+ impl ValidatableTask for PollNexusTaskQueueResponse {
244
+ type SlotKind = NexusSlotKind;
245
+
246
+ fn validate(&self) -> Result<(), anyhow::Error> {
247
+ if self.task_token.is_empty() {
248
+ bail!("missing task token");
249
+ } else if self.request.is_none() {
250
+ bail!("missing request field");
251
+ } else if self
252
+ .request
253
+ .as_ref()
254
+ .expect("just request exists")
255
+ .variant
256
+ .is_none()
257
+ {
258
+ bail!("missing request variant");
259
+ }
260
+ Ok(())
261
+ }
262
+
263
+ fn task_name() -> &'static str {
264
+ "nexus"
265
+ }
266
+ }
267
+
268
+ pub(crate) type NexusPollItem = Result<PermittedTqResp<PollNexusTaskQueueResponse>, tonic::Status>;
269
+ pub(crate) fn new_nexus_task_poller(
270
+ poller: BoxedNexusPoller,
271
+ metrics: MetricsContext,
272
+ shutdown_token: CancellationToken,
273
+ ) -> impl Stream<Item = NexusPollItem> {
274
+ TaskPollerStream::new(
275
+ poller,
276
+ metrics,
277
+ MetricsContext::nexus_poll_timeout,
278
+ shutdown_token,
279
+ )
280
+ .into_stream()
281
+ }
@@ -1,29 +1,30 @@
1
1
  use crate::{
2
- abstractions::{dbg_panic, MeteredPermitDealer, OwnedMeteredSemPermit},
2
+ abstractions::{MeteredPermitDealer, OwnedMeteredSemPermit, dbg_panic},
3
3
  pollers::{self, Poller},
4
4
  worker::client::WorkerClient,
5
5
  };
6
- use futures_util::{future::BoxFuture, stream::FuturesUnordered, FutureExt, StreamExt};
6
+ use futures_util::{FutureExt, StreamExt, future::BoxFuture, stream::FuturesUnordered};
7
7
  use governor::{Quota, RateLimiter};
8
8
  use std::{
9
9
  fmt::Debug,
10
10
  future::Future,
11
11
  sync::{
12
- atomic::{AtomicBool, AtomicUsize, Ordering},
13
12
  Arc,
13
+ atomic::{AtomicBool, AtomicUsize, Ordering},
14
14
  },
15
15
  time::Duration,
16
16
  };
17
- use temporal_sdk_core_api::worker::{ActivitySlotKind, SlotKind, WorkflowSlotKind};
17
+ use temporal_sdk_core_api::worker::{ActivitySlotKind, NexusSlotKind, SlotKind, WorkflowSlotKind};
18
18
  use temporal_sdk_core_protos::temporal::api::{
19
19
  taskqueue::v1::TaskQueue,
20
- workflowservice::v1::{PollActivityTaskQueueResponse, PollWorkflowTaskQueueResponse},
20
+ workflowservice::v1::{
21
+ PollActivityTaskQueueResponse, PollNexusTaskQueueResponse, PollWorkflowTaskQueueResponse,
22
+ },
21
23
  };
22
24
  use tokio::{
23
25
  sync::{
24
- broadcast,
25
- mpsc::{unbounded_channel, UnboundedReceiver},
26
- Mutex,
26
+ Mutex, broadcast,
27
+ mpsc::{UnboundedReceiver, unbounded_channel},
27
28
  },
28
29
  task::JoinHandle,
29
30
  };
@@ -297,6 +298,29 @@ pub(crate) fn new_activity_task_buffer(
297
298
  )
298
299
  }
299
300
 
301
+ pub(crate) type PollNexusTaskBuffer = LongPollBuffer<PollNexusTaskQueueResponse, NexusSlotKind>;
302
+ pub(crate) fn new_nexus_task_buffer(
303
+ client: Arc<dyn WorkerClient>,
304
+ task_queue: String,
305
+ concurrent_pollers: usize,
306
+ semaphore: MeteredPermitDealer<NexusSlotKind>,
307
+ shutdown: CancellationToken,
308
+ num_pollers_handler: Option<impl Fn(usize) + Send + Sync + 'static>,
309
+ ) -> PollNexusTaskBuffer {
310
+ LongPollBuffer::new(
311
+ move || {
312
+ let client = client.clone();
313
+ let task_queue = task_queue.clone();
314
+ async move { client.poll_nexus_task(task_queue).await }
315
+ },
316
+ semaphore,
317
+ concurrent_pollers,
318
+ shutdown,
319
+ num_pollers_handler,
320
+ None::<fn() -> BoxFuture<'static, ()>>,
321
+ )
322
+ }
323
+
300
324
  #[cfg(test)]
301
325
  #[derive(derive_more::Constructor)]
302
326
  pub(crate) struct MockPermittedPollBuffer<PT, SK: SlotKind> {
@@ -1,9 +1,9 @@
1
1
  pub(crate) mod protocol_messages;
2
2
 
3
3
  use crate::{
4
- protosext::protocol_messages::IncomingProtocolMessage,
5
- worker::{LocalActivityExecutionResult, LEGACY_QUERY_ID},
6
4
  CompleteActivityError, TaskToken,
5
+ protosext::protocol_messages::IncomingProtocolMessage,
6
+ worker::{LEGACY_QUERY_ID, LocalActivityExecutionResult},
7
7
  };
8
8
  use anyhow::anyhow;
9
9
  use itertools::Itertools;
@@ -23,11 +23,11 @@ use temporal_sdk_core_protos::{
23
23
  },
24
24
  external_data::LocalActivityMarkerData,
25
25
  workflow_activation::{
26
- query_to_job, workflow_activation_job, QueryWorkflow, WorkflowActivation,
27
- WorkflowActivationJob,
26
+ QueryWorkflow, WorkflowActivation, WorkflowActivationJob, query_to_job,
27
+ workflow_activation_job,
28
28
  },
29
29
  workflow_commands::{
30
- query_result, ActivityCancellationType, QueryResult, ScheduleLocalActivity,
30
+ ActivityCancellationType, QueryResult, ScheduleLocalActivity, query_result,
31
31
  },
32
32
  workflow_completion,
33
33
  },
@@ -35,7 +35,7 @@ use temporal_sdk_core_protos::{
35
35
  common::v1::{Payload, RetryPolicy, WorkflowExecution},
36
36
  enums::v1::EventType,
37
37
  failure::v1::Failure,
38
- history::v1::{history_event, History, HistoryEvent, MarkerRecordedEventAttributes},
38
+ history::v1::{History, HistoryEvent, MarkerRecordedEventAttributes, history_event},
39
39
  query::v1::WorkflowQuery,
40
40
  workflowservice::v1::PollWorkflowTaskQueueResponse,
41
41
  },
@@ -400,7 +400,7 @@ impl ValidScheduleLA {
400
400
  return Err(anyhow!(
401
401
  "One or both of schedule_to_close or start_to_close timeouts must be set for \
402
402
  local activities"
403
- ))
403
+ ));
404
404
  }
405
405
  };
406
406
  let retry_policy = v.retry_policy.unwrap_or_default();
@@ -2,8 +2,8 @@ use anyhow::{anyhow, bail};
2
2
  use std::collections::HashMap;
3
3
  use temporal_sdk_core_protos::temporal::api::{
4
4
  common::v1::Payload,
5
- history::v1::{history_event, HistoryEvent},
6
- protocol::v1::{message::SequencingId, Message},
5
+ history::v1::{HistoryEvent, history_event},
6
+ protocol::v1::{Message, message::SequencingId},
7
7
  update,
8
8
  };
9
9
 
@@ -3,21 +3,23 @@
3
3
  //! users during testing.
4
4
 
5
5
  use crate::{
6
+ Worker,
6
7
  worker::{
7
- client::mocks::{mock_manual_workflow_client, MockManualWorkerClient},
8
8
  PostActivateHookData,
9
+ client::mocks::{MockManualWorkerClient, mock_manual_workflow_client},
9
10
  },
10
- Worker,
11
11
  };
12
12
  use futures_util::{FutureExt, Stream, StreamExt};
13
13
  use parking_lot::Mutex;
14
- use std::sync::OnceLock;
15
14
  use std::{
16
15
  pin::Pin,
17
- sync::Arc,
16
+ sync::{Arc, OnceLock},
18
17
  task::{Context, Poll},
19
18
  };
20
19
  use temporal_sdk_core_api::worker::WorkerConfig;
20
+ pub use temporal_sdk_core_protos::{
21
+ DEFAULT_WORKFLOW_TYPE, HistoryInfo, TestHistoryBuilder, default_wes_attribs,
22
+ };
21
23
  use temporal_sdk_core_protos::{
22
24
  coresdk::workflow_activation::remove_from_cache::EvictionReason,
23
25
  temporal::api::{
@@ -28,10 +30,7 @@ use temporal_sdk_core_protos::{
28
30
  },
29
31
  },
30
32
  };
31
- pub use temporal_sdk_core_protos::{
32
- default_wes_attribs, HistoryInfo, TestHistoryBuilder, DEFAULT_WORKFLOW_TYPE,
33
- };
34
- use tokio::sync::{mpsc, mpsc::UnboundedSender, Mutex as TokioMutex};
33
+ use tokio::sync::{Mutex as TokioMutex, mpsc, mpsc::UnboundedSender};
35
34
  use tokio_stream::wrappers::UnboundedReceiverStream;
36
35
  use tokio_util::sync::CancellationToken;
37
36
 
@@ -202,7 +201,7 @@ impl Historator {
202
201
  /// we're ready to replay the next history, or whatever else.
203
202
  pub(crate) fn get_post_activate_hook(
204
203
  &self,
205
- ) -> impl Fn(&Worker, PostActivateHookData) + Send + Sync {
204
+ ) -> impl Fn(&Worker, PostActivateHookData) + Send + Sync + use<> {
206
205
  let done_tx = self.replay_done_tx.clone();
207
206
  move |worker, data| {
208
207
  if !data.replaying {