@temporalio/core-bridge 1.7.0 → 1.7.2

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 (44) hide show
  1. package/Cargo.lock +500 -400
  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/client/src/lib.rs +23 -6
  9. package/sdk-core/client/src/raw.rs +15 -6
  10. package/sdk-core/core/Cargo.toml +1 -0
  11. package/sdk-core/core/src/core_tests/activity_tasks.rs +13 -5
  12. package/sdk-core/core/src/core_tests/determinism.rs +49 -2
  13. package/sdk-core/core/src/core_tests/workflow_tasks.rs +21 -39
  14. package/sdk-core/core/src/internal_flags.rs +132 -60
  15. package/sdk-core/core/src/worker/activities/activity_task_poller_stream.rs +10 -7
  16. package/sdk-core/core/src/worker/activities.rs +152 -142
  17. package/sdk-core/core/src/worker/client.rs +12 -8
  18. package/sdk-core/core/src/worker/mod.rs +8 -5
  19. package/sdk-core/core/src/worker/workflow/history_update.rs +86 -2
  20. package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +4 -1
  21. package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +23 -88
  22. package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +6 -6
  23. package/sdk-core/core/src/worker/workflow/managed_run.rs +9 -2
  24. package/sdk-core/core/src/worker/workflow/mod.rs +22 -8
  25. package/sdk-core/core/src/worker/workflow/workflow_stream.rs +29 -27
  26. package/sdk-core/protos/api_upstream/.github/workflows/publish-docs.yml +23 -0
  27. package/sdk-core/protos/api_upstream/Makefile +1 -1
  28. package/sdk-core/protos/api_upstream/buf.yaml +5 -0
  29. package/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +17 -0
  30. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +2 -0
  31. package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +6 -3
  32. package/sdk-core/protos/api_upstream/temporal/api/protocol/v1/message.proto +1 -1
  33. package/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +12 -22
  34. package/sdk-core/protos/api_upstream/temporal/api/update/v1/message.proto +2 -2
  35. package/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +2 -0
  36. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +145 -48
  37. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +19 -8
  38. package/sdk-core/test-utils/src/lib.rs +29 -7
  39. package/sdk-core/tests/integ_tests/activity_functions.rs +5 -0
  40. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +2 -4
  41. package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +0 -1
  42. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +5 -7
  43. package/sdk-core/tests/integ_tests/workflow_tests.rs +3 -7
  44. package/sdk-core/tests/main.rs +16 -24
@@ -38,7 +38,7 @@ fsm! {
38
38
  // upon observing a history event indicating that the command has been recorded. Note that this
39
39
  // does not imply that the command has been _executed_, only that it _will be_ executed at some
40
40
  // point in the future.
41
- CommandIssued --(CommandRecorded(CmdRecDat), shared on_command_recorded) --> Done;
41
+ CommandIssued --(CommandRecorded, on_command_recorded) --> Done;
42
42
  }
43
43
 
44
44
  /// Instantiates an UpsertSearchAttributesMachine and packs it together with an initial command
@@ -62,37 +62,21 @@ pub(super) fn upsert_search_attrs(
62
62
  );
63
63
  // We must still create the command to preserve compatability with anyone previously doing
64
64
  // this.
65
- create_new(Default::default(), true, internal_flags)
65
+ create_new(Default::default())
66
66
  } else {
67
- create_new(attribs.search_attributes.into(), false, internal_flags)
67
+ create_new(attribs.search_attributes.into())
68
68
  }
69
69
  }
70
70
 
71
71
  /// May be used by other state machines / internal needs which desire upserting search attributes.
72
72
  pub(super) fn upsert_search_attrs_internal(
73
73
  attribs: UpsertWorkflowSearchAttributesCommandAttributes,
74
- internal_flags: InternalFlagsRef,
75
74
  ) -> NewMachineWithCommand {
76
- create_new(
77
- attribs.search_attributes.unwrap_or_default(),
78
- true,
79
- internal_flags,
80
- )
75
+ create_new(attribs.search_attributes.unwrap_or_default())
81
76
  }
82
77
 
83
- fn create_new(
84
- sa_map: SearchAttributes,
85
- should_skip_determinism: bool,
86
- internal_flags: InternalFlagsRef,
87
- ) -> NewMachineWithCommand {
88
- let sm = UpsertSearchAttributesMachine::from_parts(
89
- Created {}.into(),
90
- SharedState {
91
- sa_map: sa_map.clone(),
92
- should_skip_determinism,
93
- internal_flags,
94
- },
95
- );
78
+ fn create_new(sa_map: SearchAttributes) -> NewMachineWithCommand {
79
+ let sm = UpsertSearchAttributesMachine::from_parts(Created {}.into(), SharedState {});
96
80
  let cmd = Command {
97
81
  command_type: CommandType::UpsertWorkflowSearchAttributes as i32,
98
82
  attributes: Some(
@@ -110,11 +94,7 @@ fn create_new(
110
94
  }
111
95
 
112
96
  #[derive(Clone)]
113
- pub(super) struct SharedState {
114
- should_skip_determinism: bool,
115
- sa_map: SearchAttributes,
116
- internal_flags: InternalFlagsRef,
117
- }
97
+ pub(super) struct SharedState {}
118
98
 
119
99
  /// The state-machine-specific set of commands that are the results of state transition in the
120
100
  /// UpsertSearchAttributesMachine. There are none of these because this state machine emits the
@@ -131,30 +111,9 @@ pub(super) struct Created {}
131
111
  /// higher-level machinery, it transitions into this state.
132
112
  #[derive(Debug, Default, Clone, derive_more::Display)]
133
113
  pub(super) struct CommandIssued {}
134
- pub(super) struct CmdRecDat {
135
- sa_map: Option<SearchAttributes>,
136
- replaying: bool,
137
- }
138
114
 
139
115
  impl CommandIssued {
140
- pub(super) fn on_command_recorded(
141
- self,
142
- shared: &mut SharedState,
143
- dat: CmdRecDat,
144
- ) -> UpsertSearchAttributesMachineTransition<Done> {
145
- if shared.internal_flags.borrow_mut().try_use(
146
- CoreInternalFlags::UpsertSearchAttributeOnPatch,
147
- !dat.replaying,
148
- ) {
149
- let sa = dat.sa_map.unwrap_or_default();
150
- if !shared.should_skip_determinism && shared.sa_map != sa {
151
- return TransitionResult::Err(WFMachinesError::Nondeterminism(format!(
152
- "Search attribute upsert calls must remain deterministic, but {:?} does not \
153
- match the attributes from history: {:?}",
154
- shared.sa_map, sa
155
- )));
156
- }
157
- }
116
+ pub(super) fn on_command_recorded(self) -> UpsertSearchAttributesMachineTransition<Done> {
158
117
  TransitionResult::default()
159
118
  }
160
119
  }
@@ -198,14 +157,9 @@ impl TryFrom<HistEventData> for UpsertSearchAttributesMachineEvents {
198
157
 
199
158
  fn try_from(e: HistEventData) -> Result<Self, Self::Error> {
200
159
  match e.event.attributes {
201
- Some(history_event::Attributes::UpsertWorkflowSearchAttributesEventAttributes(
202
- attrs,
203
- )) => Ok(UpsertSearchAttributesMachineEvents::CommandRecorded(
204
- CmdRecDat {
205
- sa_map: attrs.search_attributes,
206
- replaying: e.replaying,
207
- },
208
- )),
160
+ Some(history_event::Attributes::UpsertWorkflowSearchAttributesEventAttributes(_)) => {
161
+ Ok(UpsertSearchAttributesMachineEvents::CommandRecorded)
162
+ }
209
163
  _ => Err(Self::Error::Nondeterminism(format!(
210
164
  "UpsertWorkflowSearchAttributesMachine does not handle {e}"
211
165
  ))),
@@ -241,7 +195,6 @@ impl From<Created> for CommandIssued {
241
195
  mod tests {
242
196
  use super::{super::OnEventWrapper, *};
243
197
  use crate::{
244
- internal_flags::InternalFlags,
245
198
  replay::TestHistoryBuilder,
246
199
  test_help::{build_mock_pollers, mock_worker, MockPollCfg, ResponseType},
247
200
  worker::{
@@ -249,8 +202,8 @@ mod tests {
249
202
  workflow::{machines::patch_state_machine::VERSION_SEARCH_ATTR_KEY, ManagedWFFunc},
250
203
  },
251
204
  };
252
- use rustfsm::{MachineError, StateMachine};
253
- use std::{cell::RefCell, collections::HashMap, rc::Rc};
205
+ use rustfsm::StateMachine;
206
+ use std::collections::HashMap;
254
207
  use temporal_sdk::{WfContext, WorkflowFunction};
255
208
  use temporal_sdk_core_api::Worker;
256
209
  use temporal_sdk_core_protos::{
@@ -317,25 +270,14 @@ mod tests {
317
270
  }
318
271
 
319
272
  #[rstest::rstest]
320
- fn upsert_search_attrs_sm(#[values(true, false)] nondetermistic: bool) {
321
- let mut sm = UpsertSearchAttributesMachine::from_parts(
322
- Created {}.into(),
323
- SharedState {
324
- sa_map: Default::default(),
325
- should_skip_determinism: false,
326
- internal_flags: Rc::new(RefCell::new(InternalFlags::all_core_enabled())),
327
- },
328
- );
329
-
330
- let sa_attribs = if nondetermistic {
331
- UpsertWorkflowSearchAttributesEventAttributes {
332
- workflow_task_completed_event_id: 0,
333
- search_attributes: Some(SearchAttributes {
334
- indexed_fields: HashMap::from([("Yo".to_string(), Payload::default())]),
335
- }),
336
- }
337
- } else {
338
- Default::default()
273
+ fn upsert_search_attrs_sm() {
274
+ let mut sm = UpsertSearchAttributesMachine::from_parts(Created {}.into(), SharedState {});
275
+
276
+ let sa_attribs = UpsertWorkflowSearchAttributesEventAttributes {
277
+ workflow_task_completed_event_id: 0,
278
+ search_attributes: Some(SearchAttributes {
279
+ indexed_fields: HashMap::from([("Yo".to_string(), Payload::default())]),
280
+ }),
339
281
  };
340
282
  let recorded_history_event = HistoryEvent {
341
283
  event_type: EventType::UpsertWorkflowSearchAttributes as i32,
@@ -365,15 +307,8 @@ mod tests {
365
307
  assert_eq!(CommandIssued {}.to_string(), sm.state().to_string());
366
308
 
367
309
  let recorded_res = OnEventWrapper::on_event_mut(&mut sm, cmd_recorded_sm_event);
368
- if nondetermistic {
369
- assert_matches!(
370
- recorded_res.unwrap_err(),
371
- MachineError::Underlying(WFMachinesError::Nondeterminism(_))
372
- );
373
- } else {
374
- recorded_res.expect("CommandRecorded should transition CommandIssued -> Done");
375
- assert_eq!(Done {}.to_string(), sm.state().to_string());
376
- }
310
+ recorded_res.expect("CommandRecorded should transition CommandIssued -> Done");
311
+ assert_eq!(Done {}.to_string(), sm.state().to_string());
377
312
  }
378
313
 
379
314
  #[rstest::rstest]
@@ -331,6 +331,11 @@ impl WorkflowMachines {
331
331
  /// sent off to the server. They are not removed from the internal queue, that happens when
332
332
  /// corresponding history events from the server are being handled.
333
333
  pub(crate) fn get_commands(&self) -> Vec<ProtoCommand> {
334
+ // Since we're about to write a WFT, record any internal flags we know about which aren't
335
+ // already recorded.
336
+ (*self.observed_internal_flags)
337
+ .borrow_mut()
338
+ .write_all_known();
334
339
  self.commands
335
340
  .iter()
336
341
  .filter_map(|c| {
@@ -363,8 +368,6 @@ impl WorkflowMachines {
363
368
  available_internal_flags: (*self.observed_internal_flags)
364
369
  .borrow()
365
370
  .all_lang()
366
- .iter()
367
- .copied()
368
371
  .collect(),
369
372
  }
370
373
  }
@@ -924,10 +927,7 @@ impl WorkflowMachines {
924
927
  }
925
928
  ProtoCmdAttrs::UpsertWorkflowSearchAttributesCommandAttributes(attrs) => {
926
929
  self.add_cmd_to_wf_task(
927
- upsert_search_attrs_internal(
928
- attrs,
929
- self.observed_internal_flags.clone(),
930
- ),
930
+ upsert_search_attrs_internal(attrs),
931
931
  CommandIdKind::NeverResolves,
932
932
  );
933
933
  }
@@ -550,8 +550,15 @@ impl ManagedRun {
550
550
 
551
551
  /// Delete the currently tracked workflow activation and return it, if any. Should be called
552
552
  /// after the processing of the activation completion, and WFT reporting.
553
- pub(super) fn delete_activation(&mut self) -> Option<OutstandingActivation> {
554
- self.activation.take()
553
+ pub(super) fn delete_activation(
554
+ &mut self,
555
+ pred: impl FnOnce(&OutstandingActivation) -> bool,
556
+ ) -> Option<OutstandingActivation> {
557
+ if self.activation().map(pred).unwrap_or_default() {
558
+ self.activation.take()
559
+ } else {
560
+ None
561
+ }
555
562
  }
556
563
 
557
564
  /// Called when local activities resolve
@@ -23,8 +23,8 @@ pub(crate) use managed_run::ManagedWFFunc;
23
23
 
24
24
  use crate::{
25
25
  abstractions::{
26
- stream_when_allowed, take_cell::TakeCell, MeteredSemaphore, TrackedOwnedMeteredSemPermit,
27
- UsedMeteredSemPermit,
26
+ dbg_panic, stream_when_allowed, take_cell::TakeCell, MeteredSemaphore,
27
+ TrackedOwnedMeteredSemPermit, UsedMeteredSemPermit,
28
28
  },
29
29
  internal_flags::InternalFlags,
30
30
  protosext::{legacy_query_failure, ValidPollWFTQResponse},
@@ -294,6 +294,7 @@ impl Workflows {
294
294
  workflow_completion::Success::from_variants(vec![]).into(),
295
295
  ),
296
296
  },
297
+ true,
297
298
  // We need to say a type, but the type is irrelevant, so imagine some
298
299
  // boxed function we'll never call.
299
300
  Option::<Box<dyn Fn(PostActivateHookData) + Send>>::None,
@@ -309,6 +310,7 @@ impl Workflows {
309
310
  run_id,
310
311
  status: Some(auto_fail_to_complete_status(machines_err)),
311
312
  },
313
+ true,
312
314
  Option::<Box<dyn Fn(PostActivateHookData) + Send>>::None,
313
315
  )
314
316
  .await?;
@@ -324,8 +326,9 @@ impl Workflows {
324
326
  pub(super) async fn activation_completed(
325
327
  &self,
326
328
  completion: WorkflowActivationCompletion,
329
+ is_autocomplete: bool,
327
330
  post_activate_hook: Option<impl Fn(PostActivateHookData)>,
328
- ) -> Result<usize, CompleteWfError> {
331
+ ) -> Result<(), CompleteWfError> {
329
332
  let is_empty_completion = completion.is_empty();
330
333
  let completion = validate_completion(completion)?;
331
334
  let run_id = completion.run_id().to_string();
@@ -337,7 +340,7 @@ impl Workflows {
337
340
  if !was_sent {
338
341
  if is_empty_completion {
339
342
  // Empty complete which is likely an evict reply, we can just ignore.
340
- return Ok(0);
343
+ return Ok(());
341
344
  }
342
345
  panic!(
343
346
  "A non-empty completion was not processed. Workflow processing may have \
@@ -345,9 +348,18 @@ impl Workflows {
345
348
  );
346
349
  }
347
350
 
348
- let completion_outcome = rx
349
- .await
350
- .expect("Send half of activation complete response not dropped");
351
+ let completion_outcome = if let Ok(c) = rx.await {
352
+ c
353
+ } else {
354
+ dbg_panic!("Send half of activation complete response channel went missing");
355
+ self.request_eviction(
356
+ run_id,
357
+ "Send half of activation complete response channel went missing",
358
+ EvictionReason::Fatal,
359
+ );
360
+ return Ok(());
361
+ };
362
+
351
363
  let mut wft_from_complete = None;
352
364
  let wft_report_status = match completion_outcome.outcome {
353
365
  ActivationCompleteOutcome::ReportWFTSuccess(report) => match report {
@@ -460,9 +472,10 @@ impl Workflows {
460
472
  run_id,
461
473
  wft_report_status,
462
474
  wft_from_complete: maybe_pwft,
475
+ is_autocomplete,
463
476
  });
464
477
 
465
- Ok(completion_outcome.most_recently_processed_event)
478
+ Ok(())
466
479
  }
467
480
 
468
481
  /// Tell workflow that a local activity has finished with the provided result
@@ -932,6 +945,7 @@ struct PostActivationMsg {
932
945
  run_id: String,
933
946
  wft_report_status: WFTReportStatus,
934
947
  wft_from_complete: Option<(PreparedWFT, HistoryPaginator)>,
948
+ is_autocomplete: bool,
935
949
  }
936
950
  #[derive(Debug, Clone)]
937
951
  #[cfg_attr(
@@ -338,37 +338,39 @@ impl WFStream {
338
338
 
339
339
  // If we reported to server, we always want to mark it complete.
340
340
  let maybe_t = self.complete_wft(run_id, report.wft_report_status);
341
- // Delete the activation
342
- let activation = self
343
- .runs
344
- .get_mut(run_id)
345
- .and_then(|rh| rh.delete_activation());
346
-
347
- // Evict the run if the activation contained an eviction
348
- let mut applied_buffered_poll_for_this_run = false;
349
- if activation.map(|a| a.has_eviction()).unwrap_or_default() {
350
- debug!(run_id=%run_id, "Evicting run");
351
-
352
- if let Some(mut rh) = self.runs.remove(run_id) {
353
- if let Some(buff) = rh.take_buffered_wft() {
354
- // Don't try to apply a buffered poll for this run if we just got a new WFT
355
- // from completing, because by definition that buffered poll is now an
356
- // out-of-date WFT.
357
- if wft_from_complete.is_none() {
358
- res = self.instantiate_or_update(buff);
359
- applied_buffered_poll_for_this_run = true;
341
+ // Delete the activation, but only if the report came from lang, or we know the outstanding
342
+ // activation is expected to be completed internally.
343
+ if let Some(activation) = self.runs.get_mut(run_id).and_then(|rh| {
344
+ rh.delete_activation(|act| {
345
+ !report.is_autocomplete || matches!(act, OutstandingActivation::Autocomplete)
346
+ })
347
+ }) {
348
+ // Evict the run if the activation contained an eviction
349
+ let mut applied_buffered_poll_for_this_run = false;
350
+ if activation.has_eviction() {
351
+ debug!(run_id=%run_id, "Evicting run");
352
+
353
+ if let Some(mut rh) = self.runs.remove(run_id) {
354
+ if let Some(buff) = rh.take_buffered_wft() {
355
+ // Don't try to apply a buffered poll for this run if we just got a new WFT
356
+ // from completing, because by definition that buffered poll is now an
357
+ // out-of-date WFT.
358
+ if wft_from_complete.is_none() {
359
+ res = self.instantiate_or_update(buff);
360
+ applied_buffered_poll_for_this_run = true;
361
+ }
360
362
  }
361
363
  }
362
- }
363
364
 
364
- // Attempt to apply a buffered poll for some *other* run, if we didn't have a wft
365
- // from complete or a buffered poll for *this* run.
366
- if wft_from_complete.is_none() && !applied_buffered_poll_for_this_run {
367
- if let Some(buff) = self.buffered_polls_need_cache_slot.pop_front() {
368
- res = self.instantiate_or_update(buff);
365
+ // Attempt to apply a buffered poll for some *other* run, if we didn't have a wft
366
+ // from complete or a buffered poll for *this* run.
367
+ if wft_from_complete.is_none() && !applied_buffered_poll_for_this_run {
368
+ if let Some(buff) = self.buffered_polls_need_cache_slot.pop_front() {
369
+ res = self.instantiate_or_update(buff);
370
+ }
369
371
  }
370
- }
371
- };
372
+ };
373
+ }
372
374
 
373
375
  if let Some((wft, pag)) = wft_from_complete {
374
376
  debug!(run_id=%wft.execution.run_id, "New WFT from completion");
@@ -0,0 +1,23 @@
1
+ name: Publish docs
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+
8
+ env:
9
+ VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
10
+ VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
11
+
12
+ jobs:
13
+ publish:
14
+ runs-on: ubuntu-latest
15
+
16
+ steps:
17
+ - name: Checkout repo
18
+ uses: actions/checkout@v3
19
+ - name: Generate docs
20
+ run: |
21
+ docker run -v $(pwd)/docs:/out -v $(pwd)/:/protos pseudomuto/protoc-gen-doc --doc_opt=html,index.html $(find temporal/api -type f -name "*.proto")
22
+ - name: Deploy
23
+ run: npx vercel deploy docs/ --prod --token=${{ secrets.VERCEL_TOKEN }}
@@ -29,7 +29,7 @@ $(PROTO_OUT):
29
29
  mkdir $(PROTO_OUT)
30
30
 
31
31
  ##### Compile proto files for go #####
32
- grpc: buf-lint api-linter buf-breaking gogo-grpc fix-path
32
+ grpc: buf-lint api-linter gogo-grpc fix-path
33
33
 
34
34
  go-grpc: clean $(PROTO_OUT)
35
35
  printf $(COLOR) "Compile for go-gRPC..."
@@ -1,5 +1,10 @@
1
1
  version: v1
2
2
  breaking:
3
+ ignore:
4
+ # TODO: Remove after PR 237
5
+ - temporal/api/taskqueue/v1
6
+ - temporal/api/workflowservice/v1
7
+ - temporal/api/history/v1
3
8
  use:
4
9
  - PACKAGE
5
10
  lint:
@@ -121,3 +121,20 @@ message MeteringMetadata {
121
121
  // aip.dev/not-precedent: Negative values make no sense to represent. --)
122
122
  uint32 nonfirst_local_activity_execution_attempts = 13;
123
123
  }
124
+
125
+ // Identifies the version(s) of a worker that processed a task
126
+ message WorkerVersionStamp {
127
+ // An opaque whole-worker identifier
128
+ string build_id = 1;
129
+ // Set if the worker used a dynamically loadable bundle to process
130
+ // the task. The bundle could be a WASM blob, JS bundle, etc.
131
+ string bundle_id = 2;
132
+ }
133
+
134
+ // Identifies the version(s) that a worker is compatible with when polling or identifying itself
135
+ message WorkerVersionCapabilities {
136
+ // An opaque whole-worker identifier
137
+ string build_id = 1;
138
+
139
+ // Later, may include info like "I can process WASM and/or JS bundles"
140
+ }
@@ -108,6 +108,8 @@ enum SignalExternalWorkflowExecutionFailedCause {
108
108
  SIGNAL_EXTERNAL_WORKFLOW_EXECUTION_FAILED_CAUSE_UNSPECIFIED = 0;
109
109
  SIGNAL_EXTERNAL_WORKFLOW_EXECUTION_FAILED_CAUSE_EXTERNAL_WORKFLOW_EXECUTION_NOT_FOUND = 1;
110
110
  SIGNAL_EXTERNAL_WORKFLOW_EXECUTION_FAILED_CAUSE_NAMESPACE_NOT_FOUND = 2;
111
+ // Signal count limit is per workflow and controlled by server dynamic config "history.maximumSignalsPerExecution"
112
+ SIGNAL_EXTERNAL_WORKFLOW_EXECUTION_FAILED_CAUSE_SIGNAL_COUNT_LIMIT_EXCEEDED = 3;
111
113
  }
112
114
 
113
115
  enum ResourceExhaustedCause {
@@ -193,9 +193,10 @@ message WorkflowTaskCompletedEventAttributes {
193
193
  string identity = 3;
194
194
  // Binary ID of the worker who completed this task
195
195
  string binary_checksum = 4;
196
- // ID of the worker who picked up this workflow task, or missing if worker
197
- // is not using versioning.
198
- temporal.api.taskqueue.v1.VersionId worker_versioning_id = 5;
196
+ // Version info of the worker who processed this workflow task, or missing if worker is not
197
+ // using versioning. If present, the `build_id` field within is also used as `binary_checksum`,
198
+ // which may be omitted in that case (it may also be populated to preserve compatibility).
199
+ temporal.api.common.v1.WorkerVersionStamp worker_version = 5;
199
200
  // Data the SDK wishes to record for itself, but server need not interpret, and does not
200
201
  // directly impact workflow state.
201
202
  temporal.api.sdk.v1.WorkflowTaskCompletedMetadata sdk_metadata = 6;
@@ -409,6 +410,8 @@ message WorkflowExecutionSignaledEventAttributes {
409
410
  // Headers that were passed by the sender of the signal and copied by temporal
410
411
  // server into the workflow task.
411
412
  temporal.api.common.v1.Header header = 4;
413
+ // Indicates the signal did not generate a new workflow task when received.
414
+ bool skip_generate_workflow_task = 5;
412
415
  }
413
416
 
414
417
  message WorkflowExecutionTerminatedEventAttributes {
@@ -29,7 +29,7 @@ option java_package = "io.temporal.api.protocol.v1";
29
29
  option java_multiple_files = true;
30
30
  option java_outer_classname = "MessageProto";
31
31
  option ruby_package = "Temporalio::Api::Protocol::V1";
32
- option csharp_namespace = "Temporalt.Api.Protocol.V1";
32
+ option csharp_namespace = "Temporalio.Api.Protocol.V1";
33
33
 
34
34
  import "google/protobuf/any.proto";
35
35
 
@@ -38,6 +38,7 @@ import "google/protobuf/wrappers.proto";
38
38
  import "dependencies/gogoproto/gogo.proto";
39
39
 
40
40
  import "temporal/api/enums/v1/task_queue.proto";
41
+ import "temporal/api/common/v1/message.proto";
41
42
 
42
43
  // See https://docs.temporal.io/docs/concepts/task-queues/
43
44
  message TaskQueue {
@@ -71,13 +72,12 @@ message TaskQueuePartitionMetadata {
71
72
  }
72
73
 
73
74
  message PollerInfo {
74
- // Unix Nano
75
75
  google.protobuf.Timestamp last_access_time = 1 [(gogoproto.stdtime) = true];
76
76
  string identity = 2;
77
77
  double rate_per_second = 3;
78
- // If a worker has specified an ID for use with the worker versioning feature while polling,
79
- // that id must appear here.
80
- VersionId worker_versioning_id = 4;
78
+ // If a worker has opted into the worker versioning feature while polling, its capabilities will
79
+ // appear here.
80
+ temporal.api.common.v1.WorkerVersionCapabilities worker_version_capabilities = 4;
81
81
  }
82
82
 
83
83
  message StickyExecutionAttributes {
@@ -87,22 +87,12 @@ message StickyExecutionAttributes {
87
87
  google.protobuf.Duration schedule_to_start_timeout = 2 [(gogoproto.stdduration) = true];
88
88
  }
89
89
 
90
- // Used by the worker versioning APIs, represents a node in the version graph for a particular
91
- // task queue
92
- message VersionIdNode {
93
- VersionId version = 1;
94
- // A pointer to the previous version this version is considered to be compatible with
95
- VersionIdNode previous_compatible = 2;
96
- // A pointer to the last incompatible version (previous major version)
97
- VersionIdNode previous_incompatible = 3;
90
+ // Used by the worker versioning APIs, represents an ordering of one or more versions which are
91
+ // considered to be compatible with each other. Currently the versions are always worker build ids.
92
+ message CompatibleVersionSet {
93
+ // A unique identifier for this version set. Users don't need to understand or care about this
94
+ // value, but it has value for debugging purposes.
95
+ string version_set_id = 1;
96
+ // All the compatible versions, ordered from oldest to newest
97
+ repeated string build_ids = 2;
98
98
  }
99
-
100
- // Used by the worker versioning APIs, represents a specific version of something
101
- // Currently, that's just a whole-worker id. In the future, if we support
102
- // WASM workflow bundle based versioning, for example, then the inside of this
103
- // message may become a oneof of different version types.
104
- message VersionId {
105
- // An opaque whole-worker identifier
106
- string worker_build_id = 1;
107
- }
108
-
@@ -35,8 +35,8 @@ import "temporal/api/common/v1/message.proto";
35
35
  import "temporal/api/enums/v1/update.proto";
36
36
  import "temporal/api/failure/v1/message.proto";
37
37
 
38
- // Sepcifies to the gRPC server how the client wants the UpdateWorkflowExecution
39
- // call to wait before returning control to the caller.
38
+ // Specifies to the gRPC server how long the client wants the an update-related
39
+ // RPC call to wait before returning control to the caller.
40
40
  message WaitPolicy {
41
41
 
42
42
  // Indicates the update lifecycle stage that the gRPC call should wait for
@@ -57,6 +57,8 @@ message WorkflowExecutionInfo {
57
57
  string task_queue = 13;
58
58
  int64 state_transition_count = 14;
59
59
  int64 history_size_bytes = 15;
60
+ // If set, the most recent worker version stamp that appeared in a workflow task completion
61
+ temporal.api.common.v1.WorkerVersionStamp most_recent_worker_version_stamp = 16;
60
62
  }
61
63
 
62
64
  message WorkflowExecutionConfig {