@temporalio/core-bridge 1.1.0 → 1.3.1

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 (114) hide show
  1. package/Cargo.lock +786 -54
  2. package/Cargo.toml +2 -2
  3. package/common.js +7 -3
  4. package/index.d.ts +110 -3
  5. package/index.js +2 -6
  6. package/package.json +3 -3
  7. package/releases/aarch64-apple-darwin/index.node +0 -0
  8. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  9. package/releases/x86_64-apple-darwin/index.node +0 -0
  10. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  11. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  12. package/scripts/build.js +4 -3
  13. package/sdk-core/.buildkite/docker/Dockerfile +2 -1
  14. package/sdk-core/ARCHITECTURE.md +2 -2
  15. package/sdk-core/README.md +12 -0
  16. package/sdk-core/bridge-ffi/Cargo.toml +2 -2
  17. package/sdk-core/client/Cargo.toml +6 -4
  18. package/sdk-core/client/src/lib.rs +338 -215
  19. package/sdk-core/client/src/raw.rs +352 -106
  20. package/sdk-core/client/src/retry.rs +159 -133
  21. package/sdk-core/client/src/workflow_handle/mod.rs +1 -1
  22. package/sdk-core/core/Cargo.toml +18 -9
  23. package/sdk-core/core/src/core_tests/activity_tasks.rs +63 -23
  24. package/sdk-core/core/src/core_tests/child_workflows.rs +125 -3
  25. package/sdk-core/core/src/core_tests/local_activities.rs +6 -6
  26. package/sdk-core/core/src/core_tests/workers.rs +3 -2
  27. package/sdk-core/core/src/core_tests/workflow_tasks.rs +70 -2
  28. package/sdk-core/core/src/ephemeral_server/mod.rs +499 -0
  29. package/sdk-core/core/src/lib.rs +60 -26
  30. package/sdk-core/core/src/pollers/poll_buffer.rs +4 -4
  31. package/sdk-core/core/src/replay/mod.rs +3 -3
  32. package/sdk-core/core/src/retry_logic.rs +10 -9
  33. package/sdk-core/core/src/telemetry/mod.rs +10 -7
  34. package/sdk-core/core/src/test_help/mod.rs +18 -8
  35. package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +10 -10
  36. package/sdk-core/core/src/worker/activities/local_activities.rs +13 -13
  37. package/sdk-core/core/src/worker/activities.rs +6 -12
  38. package/sdk-core/core/src/worker/client.rs +193 -64
  39. package/sdk-core/core/src/worker/mod.rs +14 -19
  40. package/sdk-core/core/src/worker/workflow/driven_workflow.rs +3 -0
  41. package/sdk-core/core/src/worker/workflow/history_update.rs +5 -5
  42. package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +133 -85
  43. package/sdk-core/core/src/worker/workflow/machines/mod.rs +3 -2
  44. package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +160 -105
  45. package/sdk-core/core/src/worker/workflow/managed_run.rs +2 -1
  46. package/sdk-core/core/src/worker/workflow/mod.rs +59 -58
  47. package/sdk-core/core/src/worker/workflow/run_cache.rs +5 -3
  48. package/sdk-core/core/src/worker/workflow/workflow_stream.rs +7 -5
  49. package/sdk-core/core-api/Cargo.toml +2 -2
  50. package/sdk-core/core-api/src/errors.rs +3 -11
  51. package/sdk-core/core-api/src/worker.rs +7 -0
  52. package/sdk-core/protos/api_upstream/.buildkite/Dockerfile +1 -1
  53. package/sdk-core/protos/api_upstream/.github/CODEOWNERS +1 -1
  54. package/sdk-core/protos/api_upstream/.github/PULL_REQUEST_TEMPLATE.md +2 -6
  55. package/sdk-core/protos/api_upstream/.github/workflows/trigger-api-go-update.yml +29 -0
  56. package/sdk-core/protos/api_upstream/Makefile +2 -2
  57. package/sdk-core/protos/api_upstream/buf.yaml +1 -0
  58. package/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +86 -0
  59. package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +26 -0
  60. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +46 -0
  61. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +7 -0
  62. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +14 -0
  63. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +51 -0
  64. package/sdk-core/protos/api_upstream/temporal/api/failure/v1/message.proto +18 -0
  65. package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +57 -1
  66. package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +1 -3
  67. package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +4 -2
  68. package/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +11 -0
  69. package/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +23 -0
  70. package/sdk-core/protos/api_upstream/temporal/api/update/v1/message.proto +46 -0
  71. package/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +1 -0
  72. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +172 -0
  73. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +30 -0
  74. package/sdk-core/protos/grpc/health/v1/health.proto +63 -0
  75. package/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +18 -15
  76. package/sdk-core/protos/testsrv_upstream/Makefile +80 -0
  77. package/sdk-core/protos/testsrv_upstream/api-linter.yaml +38 -0
  78. package/sdk-core/protos/testsrv_upstream/buf.yaml +13 -0
  79. package/sdk-core/protos/testsrv_upstream/dependencies/gogoproto/gogo.proto +141 -0
  80. package/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +63 -0
  81. package/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +90 -0
  82. package/sdk-core/sdk/Cargo.toml +2 -2
  83. package/sdk-core/sdk/src/lib.rs +2 -2
  84. package/sdk-core/sdk/src/workflow_context/options.rs +36 -8
  85. package/sdk-core/sdk/src/workflow_context.rs +30 -6
  86. package/sdk-core/sdk/src/workflow_future.rs +4 -4
  87. package/sdk-core/sdk-core-protos/Cargo.toml +5 -5
  88. package/sdk-core/sdk-core-protos/build.rs +9 -1
  89. package/sdk-core/sdk-core-protos/src/history_builder.rs +6 -1
  90. package/sdk-core/sdk-core-protos/src/lib.rs +93 -32
  91. package/sdk-core/test-utils/Cargo.toml +3 -3
  92. package/sdk-core/test-utils/src/canned_histories.rs +58 -0
  93. package/sdk-core/test-utils/src/lib.rs +14 -10
  94. package/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +141 -0
  95. package/sdk-core/tests/integ_tests/heartbeat_tests.rs +55 -5
  96. package/sdk-core/tests/integ_tests/polling_tests.rs +1 -1
  97. package/sdk-core/tests/integ_tests/queries_tests.rs +4 -4
  98. package/sdk-core/tests/integ_tests/visibility_tests.rs +93 -0
  99. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +93 -10
  100. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +1 -1
  101. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +14 -14
  102. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +1 -1
  103. package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +12 -12
  104. package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +12 -1
  105. package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +3 -3
  106. package/sdk-core/tests/integ_tests/workflow_tests.rs +19 -4
  107. package/sdk-core/tests/load_tests.rs +2 -1
  108. package/sdk-core/tests/main.rs +10 -0
  109. package/src/conversions.rs +138 -91
  110. package/src/helpers.rs +190 -0
  111. package/src/lib.rs +10 -912
  112. package/src/runtime.rs +436 -0
  113. package/src/testing.rs +67 -0
  114. package/src/worker.rs +465 -0
@@ -24,7 +24,7 @@ use crate::{
24
24
  telemetry::VecDisplayer,
25
25
  worker::{
26
26
  activities::{ActivitiesFromWFTsHandle, PermittedTqResp},
27
- client::should_swallow_net_error,
27
+ client::WorkerClient,
28
28
  workflow::{
29
29
  managed_run::{ManagedRun, WorkflowManager},
30
30
  wft_poller::validate_wft,
@@ -32,7 +32,7 @@ use crate::{
32
32
  },
33
33
  LocalActRequest, LocalActivityResolution,
34
34
  },
35
- MetricsContext, WorkerClientBag,
35
+ MetricsContext,
36
36
  };
37
37
  use futures::{stream::BoxStream, Stream, StreamExt};
38
38
  use std::{
@@ -58,6 +58,7 @@ use temporal_sdk_core_protos::{
58
58
  },
59
59
  temporal::api::{
60
60
  command::v1::{command::Attributes, Command as ProtoCommand, Command},
61
+ common::v1::{Memo, RetryPolicy, SearchAttributes},
61
62
  enums::v1::WorkflowTaskFailedCause,
62
63
  taskqueue::v1::StickyExecutionAttributes,
63
64
  workflowservice::v1::PollActivityTaskQueueResponse,
@@ -83,6 +84,7 @@ type BoxedActivationStream = BoxStream<'static, Result<ActivationOrAuto, PollWfE
83
84
 
84
85
  /// Centralizes all state related to workflows and workflow tasks
85
86
  pub(crate) struct Workflows {
87
+ task_queue: String,
86
88
  local_tx: UnboundedSender<LocalInput>,
87
89
  processing_task: tokio::sync::Mutex<Option<JoinHandle<()>>>,
88
90
  activation_stream: tokio::sync::Mutex<(
@@ -90,7 +92,7 @@ pub(crate) struct Workflows {
90
92
  // Used to indicate polling may begin
91
93
  Option<oneshot::Sender<()>>,
92
94
  )>,
93
- client: Arc<WorkerClientBag>,
95
+ client: Arc<dyn WorkerClient>,
94
96
  /// Will be populated when this worker is using a cache and should complete WFTs with a sticky
95
97
  /// queue.
96
98
  sticky_attrs: Option<StickyExecutionAttributes>,
@@ -103,13 +105,15 @@ pub(super) struct WorkflowBasics {
103
105
  pub max_outstanding_wfts: usize,
104
106
  pub shutdown_token: CancellationToken,
105
107
  pub metrics: MetricsContext,
108
+ pub namespace: String,
109
+ pub task_queue: String,
106
110
  }
107
111
 
108
112
  impl Workflows {
109
113
  pub(super) fn new(
110
114
  basics: WorkflowBasics,
111
115
  sticky_attrs: Option<StickyExecutionAttributes>,
112
- client: Arc<WorkerClientBag>,
116
+ client: Arc<dyn WorkerClient>,
113
117
  wft_stream: impl Stream<Item = Result<ValidPollWFTQResponse, tonic::Status>> + Send + 'static,
114
118
  local_activity_request_sink: impl Fn(Vec<LocalActRequest>) -> Vec<LocalActivityResolution>
115
119
  + Send
@@ -119,6 +123,7 @@ impl Workflows {
119
123
  ) -> Self {
120
124
  let (local_tx, local_rx) = unbounded_channel();
121
125
  let shutdown_tok = basics.shutdown_token.clone();
126
+ let task_queue = basics.task_queue.clone();
122
127
  let mut stream = WFStream::build(
123
128
  basics,
124
129
  wft_stream,
@@ -151,6 +156,7 @@ impl Workflows {
151
156
  }
152
157
  });
153
158
  Self {
159
+ task_queue,
154
160
  local_tx,
155
161
  processing_task: tokio::sync::Mutex::new(Some(processing_task)),
156
162
  activation_stream: tokio::sync::Mutex::new((
@@ -263,14 +269,14 @@ impl Workflows {
263
269
  );
264
270
  Ok(())
265
271
  })
266
- .await?;
272
+ .await;
267
273
  true
268
274
  }
269
275
  ServerCommandsWithWorkflowInfo {
270
276
  task_token,
271
277
  action: ActivationAction::RespondLegacyQuery { result },
272
278
  } => {
273
- self.respond_legacy_query(task_token, result).await?;
279
+ self.respond_legacy_query(task_token, *result).await;
274
280
  true
275
281
  }
276
282
  },
@@ -282,13 +288,13 @@ impl Workflows {
282
288
  .fail_workflow_task(tt, cause, failure.failure.map(Into::into))
283
289
  .await
284
290
  })
285
- .await?;
291
+ .await;
286
292
  true
287
293
  }
288
294
  FailedActivationWFTReport::ReportLegacyQueryFailure(task_token, failure) => {
289
295
  warn!(run_id=%run_id, failure=?failure, "Failing legacy query request");
290
296
  self.respond_legacy_query(task_token, legacy_query_failure(failure))
291
- .await?;
297
+ .await;
292
298
  true
293
299
  }
294
300
  },
@@ -350,47 +356,34 @@ impl Workflows {
350
356
  self.send_local(msg);
351
357
  }
352
358
 
353
- /// Handle server errors from either completing or failing a workflow task. Returns any errors
354
- /// that can't be automatically handled.
355
- async fn handle_wft_reporting_errs<T, Fut>(
356
- &self,
357
- run_id: &str,
358
- completer: impl FnOnce() -> Fut,
359
- ) -> Result<(), CompleteWfError>
359
+ /// Handle server errors from either completing or failing a workflow task. Un-handleable errors
360
+ /// trigger a workflow eviction and are logged.
361
+ async fn handle_wft_reporting_errs<T, Fut>(&self, run_id: &str, completer: impl FnOnce() -> Fut)
360
362
  where
361
363
  Fut: Future<Output = Result<T, tonic::Status>>,
362
364
  {
363
365
  let mut should_evict = None;
364
- let res = match completer().await {
365
- Err(err) => {
366
- if should_swallow_net_error(&err) {
366
+ if let Err(err) = completer().await {
367
+ match err.code() {
368
+ // Silence unhandled command errors since the lang SDK cannot do anything
369
+ // about them besides poll again, which it will do anyway.
370
+ tonic::Code::InvalidArgument if err.message() == "UnhandledCommand" => {
371
+ debug!(error = %err, run_id, "Unhandled command response when completing");
372
+ should_evict = Some(EvictionReason::UnhandledCommand);
373
+ }
374
+ tonic::Code::NotFound => {
375
+ warn!(error = %err, run_id, "Task not found when completing");
376
+ should_evict = Some(EvictionReason::TaskNotFound);
377
+ }
378
+ _ => {
367
379
  warn!(error= %err, "Network error while completing workflow activation");
368
380
  should_evict = Some(EvictionReason::Fatal);
369
- Ok(())
370
- } else {
371
- match err.code() {
372
- // Silence unhandled command errors since the lang SDK cannot do anything
373
- // about them besides poll again, which it will do anyway.
374
- tonic::Code::InvalidArgument if err.message() == "UnhandledCommand" => {
375
- debug!(error = %err, run_id, "Unhandled command response when completing");
376
- should_evict = Some(EvictionReason::UnhandledCommand);
377
- Ok(())
378
- }
379
- tonic::Code::NotFound => {
380
- warn!(error = %err, run_id, "Task not found when completing");
381
- should_evict = Some(EvictionReason::TaskNotFound);
382
- Ok(())
383
- }
384
- _ => Err(err),
385
- }
386
381
  }
387
382
  }
388
- _ => Ok(()),
389
- };
383
+ }
390
384
  if let Some(reason) = should_evict {
391
385
  self.request_eviction(run_id, "Error reporting WFT to server", reason);
392
386
  }
393
- res.map_err(Into::into)
394
387
  }
395
388
 
396
389
  /// Sends a message to the workflow processing stream. Returns true if the message was sent
@@ -471,10 +464,20 @@ impl Workflows {
471
464
  {
472
465
  // If request_eager_execution was already false, that means lang explicitly
473
466
  // told us it didn't want to eagerly execute for some reason. So, we only
474
- // ever turn *off* eager execution if a slot is not available.
467
+ // ever turn *off* eager execution if a slot is not available or the activity
468
+ // is scheduled on a different task queue.
475
469
  if attrs.request_eager_execution {
476
- if let Some(p) = at_handle.reserve_slot() {
477
- reserved.push(p);
470
+ let same_task_queue = attrs
471
+ .task_queue
472
+ .as_ref()
473
+ .map(|q| q.name == self.task_queue)
474
+ .unwrap_or_default();
475
+ if same_task_queue {
476
+ if let Some(p) = at_handle.reserve_slot() {
477
+ reserved.push(p);
478
+ } else {
479
+ attrs.request_eager_execution = false;
480
+ }
478
481
  } else {
479
482
  attrs.request_eager_execution = false;
480
483
  }
@@ -486,22 +489,15 @@ impl Workflows {
486
489
  }
487
490
 
488
491
  /// Wraps responding to legacy queries. Handles ignore-able failures.
489
- async fn respond_legacy_query(
490
- &self,
491
- tt: TaskToken,
492
- res: QueryResult,
493
- ) -> Result<(), tonic::Status> {
492
+ async fn respond_legacy_query(&self, tt: TaskToken, res: QueryResult) {
494
493
  match self.client.respond_legacy_query(tt, res).await {
495
- Ok(_) => Ok(()),
496
- Err(e) if should_swallow_net_error(&e) => {
497
- warn!(error= %e, "Network error while responding to legacy query");
498
- Ok(())
499
- }
494
+ Ok(_) => {}
500
495
  Err(e) if e.code() == tonic::Code::NotFound => {
501
496
  warn!(error=?e, "Query not found when attempting to respond to it");
502
- Ok(())
503
497
  }
504
- Err(e) => Err(e),
498
+ Err(e) => {
499
+ warn!(error= %e, "Network error while responding to legacy query");
500
+ }
505
501
  }
506
502
  }
507
503
  }
@@ -794,7 +790,7 @@ pub(crate) enum ActivationAction {
794
790
  force_new_wft: bool,
795
791
  },
796
792
  /// We should respond to a legacy query request
797
- RespondLegacyQuery { result: QueryResult },
793
+ RespondLegacyQuery { result: Box<QueryResult> },
798
794
  }
799
795
 
800
796
  #[derive(Debug, Eq, PartialEq, Hash)]
@@ -847,6 +843,7 @@ struct ActivationCompleteResult {
847
843
  }
848
844
  /// What needs to be done after calling [Workflows::activation_completed]
849
845
  #[derive(Debug)]
846
+ #[allow(clippy::large_enum_variant)]
850
847
  enum ActivationCompleteOutcome {
851
848
  /// The WFT must be reported as successful to the server using the contained information.
852
849
  ReportWFTSuccess(ServerCommandsWithWorkflowInfo),
@@ -917,6 +914,7 @@ fn validate_completion(
917
914
  }
918
915
 
919
916
  #[derive(Debug)]
917
+ #[allow(clippy::large_enum_variant)]
920
918
  enum ValidatedCompletion {
921
919
  Success {
922
920
  run_id: String,
@@ -944,6 +942,7 @@ struct RunAction {
944
942
  trace_span: Span,
945
943
  }
946
944
  #[derive(Debug)]
945
+ #[allow(clippy::large_enum_variant)]
947
946
  enum RunActions {
948
947
  NewIncomingWFT(NewIncomingWFT),
949
948
  ActivationCompletion(RunActivationCompletion),
@@ -984,6 +983,7 @@ struct RunUpdateResponse {
984
983
  span: Span,
985
984
  }
986
985
  #[derive(Debug, derive_more::Display)]
986
+ #[allow(clippy::large_enum_variant)]
987
987
  enum RunUpdateResponseKind {
988
988
  Good(GoodRunUpdate),
989
989
  Fail(FailRunUpdate),
@@ -1068,7 +1068,7 @@ pub enum WFCommand {
1068
1068
  CancelWorkflow(CancelWorkflowExecution),
1069
1069
  SetPatchMarker(SetPatchMarker),
1070
1070
  AddChildWorkflow(StartChildWorkflowExecution),
1071
- CancelUnstartedChild(CancelUnstartedChildWorkflowExecution),
1071
+ CancelChild(CancelChildWorkflowExecution),
1072
1072
  RequestCancelExternalWorkflow(RequestCancelExternalWorkflowExecution),
1073
1073
  SignalExternalWorkflow(SignalExternalWorkflowExecution),
1074
1074
  CancelSignalWorkflow(CancelSignalWorkflow),
@@ -1106,9 +1106,7 @@ impl TryFrom<WorkflowCommand> for WFCommand {
1106
1106
  Ok(Self::SignalExternalWorkflow(s))
1107
1107
  }
1108
1108
  workflow_command::Variant::CancelSignalWorkflow(s) => Ok(Self::CancelSignalWorkflow(s)),
1109
- workflow_command::Variant::CancelUnstartedChildWorkflowExecution(s) => {
1110
- Ok(Self::CancelUnstartedChild(s))
1111
- }
1109
+ workflow_command::Variant::CancelChildWorkflowExecution(s) => Ok(Self::CancelChild(s)),
1112
1110
  workflow_command::Variant::ScheduleLocalActivity(s) => Ok(Self::AddLocalActivity(s)),
1113
1111
  workflow_command::Variant::RequestCancelLocalActivity(s) => {
1114
1112
  Ok(Self::RequestCancelLocalActivity(s))
@@ -1136,6 +1134,9 @@ enum CommandID {
1136
1134
  pub struct WorkflowStartedInfo {
1137
1135
  workflow_task_timeout: Option<Duration>,
1138
1136
  workflow_execution_timeout: Option<Duration>,
1137
+ memo: Option<Memo>,
1138
+ search_attrs: Option<SearchAttributes>,
1139
+ retry_policy: Option<RetryPolicy>,
1139
1140
  }
1140
1141
 
1141
1142
  type LocalActivityRequestSink =
@@ -7,7 +7,7 @@ use crate::{
7
7
  MetricsContext,
8
8
  };
9
9
  use lru::LruCache;
10
- use std::time::Instant;
10
+ use std::{num::NonZeroUsize, time::Instant};
11
11
  use tokio::sync::mpsc::UnboundedSender;
12
12
 
13
13
  pub(super) struct RunCache {
@@ -40,7 +40,9 @@ impl RunCache {
40
40
  max: max_cache_size,
41
41
  namespace,
42
42
  run_update_tx,
43
- runs: LruCache::new(lru_size),
43
+ runs: LruCache::new(
44
+ NonZeroUsize::new(lru_size).expect("LRU size is guaranteed positive"),
45
+ ),
44
46
  local_activity_request_sink,
45
47
  metrics,
46
48
  }
@@ -132,7 +134,7 @@ impl RunCache {
132
134
  self.runs.iter().map(|(_, v)| v)
133
135
  }
134
136
  pub fn is_full(&self) -> bool {
135
- self.runs.cap() == self.runs.len()
137
+ self.runs.cap().get() == self.runs.len()
136
138
  }
137
139
  pub fn len(&self) -> usize {
138
140
  self.runs.len()
@@ -6,7 +6,7 @@ use crate::{
6
6
  workflow::{history_update::NextPageToken, run_cache::RunCache, *},
7
7
  LocalActRequest, LocalActivityResolution, LEGACY_QUERY_ID,
8
8
  },
9
- MetricsContext, WorkerClientBag,
9
+ MetricsContext,
10
10
  };
11
11
  use futures::{stream, stream::PollNext, Stream, StreamExt};
12
12
  use std::{collections::VecDeque, fmt::Debug, future, sync::Arc, time::Instant};
@@ -36,7 +36,7 @@ pub(crate) struct WFStream {
36
36
  buffered_polls_need_cache_slot: VecDeque<PermittedWFT>,
37
37
 
38
38
  /// Client for accessing server for history pagination etc.
39
- client: Arc<WorkerClientBag>,
39
+ client: Arc<dyn WorkerClient>,
40
40
 
41
41
  /// Ensures we stay at or below this worker's maximum concurrent workflow task limit
42
42
  wft_semaphore: MeteredSemaphore,
@@ -118,7 +118,7 @@ impl WFStream {
118
118
  basics: WorkflowBasics,
119
119
  external_wfts: impl Stream<Item = Result<ValidPollWFTQResponse, tonic::Status>> + Send + 'static,
120
120
  local_rx: impl Stream<Item = LocalInput> + Send + 'static,
121
- client: Arc<WorkerClientBag>,
121
+ client: Arc<dyn WorkerClient>,
122
122
  local_activity_request_sink: impl Fn(Vec<LocalActRequest>) -> Vec<LocalActivityResolution>
123
123
  + Send
124
124
  + Sync
@@ -157,7 +157,7 @@ impl WFStream {
157
157
  buffered_polls_need_cache_slot: Default::default(),
158
158
  runs: RunCache::new(
159
159
  basics.max_cached_workflows,
160
- client.namespace().to_string(),
160
+ basics.namespace.clone(),
161
161
  run_update_tx,
162
162
  Arc::new(local_activity_request_sink),
163
163
  basics.metrics.clone(),
@@ -539,7 +539,9 @@ impl WFStream {
539
539
  &run_id,
540
540
  ActivationCompleteOutcome::ReportWFTSuccess(ServerCommandsWithWorkflowInfo {
541
541
  task_token,
542
- action: ActivationAction::RespondLegacyQuery { result: qr },
542
+ action: ActivationAction::RespondLegacyQuery {
543
+ result: Box::new(qr),
544
+ },
543
545
  }),
544
546
  resp_chan,
545
547
  );
@@ -18,9 +18,9 @@ async-trait = "0.1"
18
18
  derive_builder = "0.11"
19
19
  log = "0.4"
20
20
  opentelemetry = "0.17"
21
- prost-types = "0.9"
21
+ prost-types = "0.11"
22
22
  thiserror = "1.0"
23
- tonic = "0.6"
23
+ tonic = "0.8"
24
24
 
25
25
  [dependencies.temporal-sdk-core-protos]
26
26
  path = "../sdk-core-protos"
@@ -1,6 +1,6 @@
1
1
  //! Error types exposed by public APIs
2
2
 
3
- use prost_types::TimestampOutOfSystemRangeError;
3
+ use prost_types::TimestampError;
4
4
  use temporal_sdk_core_protos::coresdk::{
5
5
  activity_result::ActivityExecutionResult,
6
6
  workflow_activation::remove_from_cache::EvictionReason,
@@ -50,10 +50,6 @@ pub enum CompleteWfError {
50
50
  /// The run associated with the completion
51
51
  run_id: String,
52
52
  },
53
- /// Unhandled error when calling the temporal server. Core will attempt to retry any non-fatal
54
- /// errors, so lang should consider this fatal.
55
- #[error("Unhandled grpc error when completing workflow task: {0:?}")]
56
- TonicError(#[from] tonic::Status),
57
53
  }
58
54
 
59
55
  /// Errors thrown by [crate::Worker::complete_activity_task]
@@ -67,10 +63,6 @@ pub enum CompleteActivityError {
67
63
  /// The completion, which may not be included to avoid unnecessary copies.
68
64
  completion: Option<ActivityExecutionResult>,
69
65
  },
70
- /// Unhandled error when calling the temporal server. Core will attempt to retry any non-fatal
71
- /// errors, so lang should consider this fatal.
72
- #[error("Unhandled grpc error when completing activity: {0:?}")]
73
- TonicError(#[from] tonic::Status),
74
66
  }
75
67
 
76
68
  /// Errors thrown inside of workflow machines
@@ -96,8 +88,8 @@ impl WFMachinesError {
96
88
  }
97
89
  }
98
90
 
99
- impl From<TimestampOutOfSystemRangeError> for WFMachinesError {
100
- fn from(_: TimestampOutOfSystemRangeError) -> Self {
91
+ impl From<TimestampError> for WFMachinesError {
92
+ fn from(_: TimestampError) -> Self {
101
93
  Self::Fatal("Could not decode timestamp".to_string())
102
94
  }
103
95
  }
@@ -88,6 +88,13 @@ pub struct WorkerConfig {
88
88
  /// the options to fail.
89
89
  #[builder(default)]
90
90
  pub max_worker_activities_per_second: Option<f64>,
91
+
92
+ /// # UNDER DEVELOPMENT
93
+ /// If set to true this worker will opt-in to the whole-worker versioning feature.
94
+ /// `worker_build_id` will be used as the version.
95
+ /// todo: link to feature docs
96
+ #[builder(default = "false")]
97
+ pub use_worker_versioning: bool,
91
98
  }
92
99
 
93
100
  impl WorkerConfig {
@@ -1,2 +1,2 @@
1
- FROM temporalio/base-ci-builder:1.0.0
1
+ FROM temporalio/base-ci-builder:1.5.0
2
2
  WORKDIR /temporal
@@ -1,4 +1,4 @@
1
1
  # Syntax is here:
2
2
  # https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#codeowners-syntax
3
3
 
4
- * @temporalio/core
4
+ * @temporalio/server @temporalio/sdk
@@ -6,10 +6,6 @@
6
6
  **Why?**
7
7
 
8
8
 
9
- <!-- How have you verified this change? Tested locally? Added a unit test? Checked in staging env? -->
10
- **How did you test it?**
11
-
12
-
13
- <!-- Assuming the worst case, what can be broken when deploying this change to production? -->
14
- **Potential risks**
9
+ <!-- Are there any breaking changes on binary or code level? -->
10
+ **Breaking changes**
15
11
 
@@ -0,0 +1,29 @@
1
+ name: 'Trigger api-go Update'
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ notify:
11
+ name: 'Trigger api-go update'
12
+ runs-on: ubuntu-latest
13
+
14
+ defaults:
15
+ run:
16
+ shell: bash
17
+
18
+ steps:
19
+ - name: Dispatch api-go Github Action
20
+ env:
21
+ PAT: ${{ secrets.COMMANDER_DATA_TOKEN }}
22
+ PARENT_REPO: temporalio/api-go
23
+ PARENT_BRANCH: ${{ toJSON('master') }}
24
+ WORKFLOW_ID: update-proto.yml
25
+ COMMIT_AUTHOR: ${{ toJSON(github.event.head_commit.author.name) }}
26
+ COMMIT_AUTHOR_EMAIL: ${{ toJSON(github.event.head_commit.author.email) }}
27
+ COMMIT_MESSAGE: ${{ toJSON(github.event.head_commit.message) }}
28
+ run: |
29
+ curl -fL -X POST -H "Accept: application/vnd.github.v3+json" -H "Authorization: token ${{ env.PAT }}" https://api.github.com/repos/${{ env.PARENT_REPO }}/actions/workflows/${{ env.WORKFLOW_ID }}/dispatches -d '{"ref":'"$PARENT_BRANCH"', "inputs":{"commit_author":'"$COMMIT_AUTHOR"', "commit_author_email":'"$COMMIT_AUTHOR_EMAIL"', "commit_message":'"$COMMIT_MESSAGE"'}}'
@@ -33,11 +33,11 @@ grpc: buf-lint api-linter buf-breaking gogo-grpc fix-path
33
33
 
34
34
  go-grpc: clean $(PROTO_OUT)
35
35
  printf $(COLOR) "Compile for go-gRPC..."
36
- $(foreach PROTO_DIR,$(PROTO_DIRS),protoc $(PROTO_IMPORTS) --go_out=plugins=grpc,paths=source_relative:$(PROTO_OUT) $(PROTO_DIR)*.proto;)
36
+ $(foreach PROTO_DIR,$(PROTO_DIRS),protoc --fatal_warnings $(PROTO_IMPORTS) --go_out=plugins=grpc,paths=source_relative:$(PROTO_OUT) $(PROTO_DIR)*.proto;)
37
37
 
38
38
  gogo-grpc: clean $(PROTO_OUT)
39
39
  printf $(COLOR) "Compile for gogo-gRPC..."
40
- $(foreach PROTO_DIR,$(PROTO_DIRS),protoc $(PROTO_IMPORTS) --gogoslick_out=Mgoogle/protobuf/wrappers.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/duration.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/descriptor.proto=github.com/golang/protobuf/protoc-gen-go/descriptor,Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types,plugins=grpc,paths=source_relative:$(PROTO_OUT) $(PROTO_DIR)*.proto;)
40
+ $(foreach PROTO_DIR,$(PROTO_DIRS),protoc --fatal_warnings $(PROTO_IMPORTS) --gogoslick_out=Mgoogle/protobuf/wrappers.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/duration.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/descriptor.proto=github.com/golang/protobuf/protoc-gen-go/descriptor,Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types,plugins=grpc,paths=source_relative:$(PROTO_OUT) $(PROTO_DIR)*.proto;)
41
41
 
42
42
  fix-path:
43
43
  mv -f $(PROTO_OUT)/temporal/api/* $(PROTO_OUT) && rm -rf $(PROTO_OUT)/temporal
@@ -2,6 +2,7 @@ version: v1
2
2
  breaking:
3
3
  ignore:
4
4
  - temporal/api/schedule/v1
5
+ - temporal/api/update/v1
5
6
  use:
6
7
  - PACKAGE
7
8
  lint:
@@ -0,0 +1,86 @@
1
+ // The MIT License
2
+ //
3
+ // Copyright (c) 2020 Temporal Technologies Inc. All rights reserved.
4
+ //
5
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ // of this software and associated documentation files (the "Software"), to deal
7
+ // in the Software without restriction, including without limitation the rights
8
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ // copies of the Software, and to permit persons to whom the Software is
10
+ // furnished to do so, subject to the following conditions:
11
+ //
12
+ // The above copyright notice and this permission notice shall be included in
13
+ // all copies or substantial portions of the Software.
14
+ //
15
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ // THE SOFTWARE.
22
+
23
+ syntax = "proto3";
24
+
25
+ package temporal.api.batch.v1;
26
+
27
+ option go_package = "go.temporal.io/api/batch/v1;batch";
28
+ option java_package = "io.temporal.api.batch.v1";
29
+ option java_multiple_files = true;
30
+ option java_outer_classname = "MessageProto";
31
+ option ruby_package = "Temporal::Api::Batch::V1";
32
+ option csharp_namespace = "Temporal.Api.Batch.V1";
33
+
34
+ import "dependencies/gogoproto/gogo.proto";
35
+ import "google/protobuf/timestamp.proto";
36
+
37
+
38
+ import "temporal/api/common/v1/message.proto";
39
+ import "temporal/api/enums/v1/batch_operation.proto";
40
+
41
+ message BatchOperationInfo {
42
+ // Batch job ID
43
+ string job_id = 1;
44
+ // Batch operation state
45
+ temporal.api.enums.v1.BatchOperationState state = 2;
46
+ // Batch operation start time
47
+ google.protobuf.Timestamp start_time = 3 [(gogoproto.stdtime) = true];
48
+ // Batch operation close time
49
+ google.protobuf.Timestamp close_time = 4 [(gogoproto.stdtime) = true];
50
+ }
51
+
52
+ // BatchOperationTermination sends terminate requests to batch workflows.
53
+ // Keep the parameter in sync with temporal.api.workflowservice.v1.TerminateWorkflowExecutionRequest.
54
+ // Ignore first_execution_run_id because this is used for single workflow operation.
55
+ message BatchOperationTermination {
56
+ // Reason of terminate workflows
57
+ string reason = 1;
58
+ // Serialized value(s) to provide to the termination event
59
+ temporal.api.common.v1.Payloads details = 2;
60
+ // The identity of the worker/client
61
+ string identity = 3;
62
+ }
63
+
64
+ // BatchOperationSignal sends signals to batch workflows.
65
+ // Keep the parameter in sync with temporal.api.workflowservice.v1.SignalWorkflowExecutionRequest.
66
+ message BatchOperationSignal {
67
+ // The workflow author-defined name of the signal to send to the workflow
68
+ string signal = 1;
69
+ // Serialized value(s) to provide with the signal
70
+ temporal.api.common.v1.Payloads input = 2;
71
+ // Headers that are passed with the signal to the processing workflow.
72
+ // These can include things like auth or tracing tokens.
73
+ temporal.api.common.v1.Header header = 3;
74
+ // The identity of the worker/client
75
+ string identity = 4;
76
+ }
77
+
78
+ // BatchOperationCancellation sends cancel requests to batch workflows.
79
+ // Keep the parameter in sync with temporal.api.workflowservice.v1.RequestCancelWorkflowExecutionRequest.
80
+ // Ignore first_execution_run_id because this is used for single workflow operation.
81
+ message BatchOperationCancellation {
82
+ // Reason of cancel workflows
83
+ string reason = 1;
84
+ // The identity of the worker/client
85
+ string identity = 2;
86
+ }
@@ -37,6 +37,7 @@ import "dependencies/gogoproto/gogo.proto";
37
37
 
38
38
  import "temporal/api/enums/v1/workflow.proto";
39
39
  import "temporal/api/enums/v1/command_type.proto";
40
+ import "temporal/api/enums/v1/update.proto";
40
41
  import "temporal/api/common/v1/message.proto";
41
42
  import "temporal/api/failure/v1/message.proto";
42
43
  import "temporal/api/taskqueue/v1/message.proto";
@@ -213,6 +214,29 @@ message StartChildWorkflowExecutionCommandAttributes {
213
214
  temporal.api.common.v1.SearchAttributes search_attributes = 16;
214
215
  }
215
216
 
217
+ message AcceptWorkflowUpdateCommandAttributes {
218
+ // A unique identifier for an update within a given workflow context
219
+ string update_id = 1;
220
+ }
221
+
222
+ message CompleteWorkflowUpdateCommandAttributes {
223
+ // A unique identifier for an update within a given workflow context
224
+ string update_id = 1;
225
+
226
+ // Whether the server should attempt to bypass making this update rejection
227
+ // durable in history. This field is only consulted when the result field
228
+ // indicates failure. Leaving this field in its default state (i.e.
229
+ // UPDATE_WORKFLOW_REJECTION_DURABILITY_PREFERENCE_UNSPECIFIED) will result
230
+ // in making the rejection durable.
231
+ temporal.api.enums.v1.WorkflowUpdateDurabilityPreference durability_preference = 2;
232
+
233
+ // The success or failure output of the update
234
+ oneof result {
235
+ temporal.api.common.v1.Payloads success = 3;
236
+ temporal.api.failure.v1.Failure failure = 4;
237
+ }
238
+ }
239
+
216
240
  message Command {
217
241
  temporal.api.enums.v1.CommandType command_type = 1;
218
242
  oneof attributes {
@@ -229,5 +253,7 @@ message Command {
229
253
  StartChildWorkflowExecutionCommandAttributes start_child_workflow_execution_command_attributes = 12;
230
254
  SignalExternalWorkflowExecutionCommandAttributes signal_external_workflow_execution_command_attributes = 13;
231
255
  UpsertWorkflowSearchAttributesCommandAttributes upsert_workflow_search_attributes_command_attributes = 14;
256
+ AcceptWorkflowUpdateCommandAttributes accept_workflow_update_command_attributes = 15;
257
+ CompleteWorkflowUpdateCommandAttributes complete_workflow_update_command_attributes = 16;
232
258
  }
233
259
  }