@temporalio/core-bridge 1.1.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/Cargo.lock +765 -128
  2. package/Cargo.toml +2 -2
  3. package/common.js +7 -3
  4. package/index.d.ts +118 -5
  5. package/index.js +2 -6
  6. package/package.json +2 -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/.buildkite/pipeline.yml +2 -0
  15. package/sdk-core/.cargo/config.toml +1 -1
  16. package/sdk-core/ARCHITECTURE.md +2 -2
  17. package/sdk-core/README.md +12 -0
  18. package/sdk-core/bridge-ffi/Cargo.toml +2 -2
  19. package/sdk-core/bridge-ffi/src/lib.rs +2 -2
  20. package/sdk-core/client/Cargo.toml +7 -5
  21. package/sdk-core/client/src/lib.rs +354 -226
  22. package/sdk-core/client/src/metrics.rs +13 -11
  23. package/sdk-core/client/src/raw.rs +352 -107
  24. package/sdk-core/client/src/retry.rs +188 -147
  25. package/sdk-core/client/src/workflow_handle/mod.rs +1 -1
  26. package/sdk-core/core/Cargo.toml +28 -15
  27. package/sdk-core/core/src/core_tests/activity_tasks.rs +98 -33
  28. package/sdk-core/core/src/core_tests/child_workflows.rs +125 -3
  29. package/sdk-core/core/src/core_tests/local_activities.rs +6 -6
  30. package/sdk-core/core/src/core_tests/workers.rs +3 -2
  31. package/sdk-core/core/src/core_tests/workflow_tasks.rs +70 -2
  32. package/sdk-core/core/src/ephemeral_server/mod.rs +515 -0
  33. package/sdk-core/core/src/lib.rs +62 -28
  34. package/sdk-core/core/src/pollers/mod.rs +2 -0
  35. package/sdk-core/core/src/pollers/poll_buffer.rs +4 -4
  36. package/sdk-core/core/src/replay/mod.rs +3 -3
  37. package/sdk-core/core/src/retry_logic.rs +10 -9
  38. package/sdk-core/core/src/telemetry/metrics.rs +48 -39
  39. package/sdk-core/core/src/telemetry/mod.rs +46 -12
  40. package/sdk-core/core/src/telemetry/prometheus_server.rs +17 -13
  41. package/sdk-core/core/src/test_help/mod.rs +18 -8
  42. package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +10 -10
  43. package/sdk-core/core/src/worker/activities/local_activities.rs +13 -13
  44. package/sdk-core/core/src/worker/activities.rs +6 -12
  45. package/sdk-core/core/src/worker/client/mocks.rs +1 -0
  46. package/sdk-core/core/src/worker/client.rs +193 -64
  47. package/sdk-core/core/src/worker/mod.rs +14 -19
  48. package/sdk-core/core/src/worker/workflow/driven_workflow.rs +3 -0
  49. package/sdk-core/core/src/worker/workflow/history_update.rs +5 -5
  50. package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +133 -85
  51. package/sdk-core/core/src/worker/workflow/machines/mod.rs +3 -2
  52. package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +160 -105
  53. package/sdk-core/core/src/worker/workflow/managed_run.rs +2 -1
  54. package/sdk-core/core/src/worker/workflow/mod.rs +62 -58
  55. package/sdk-core/core/src/worker/workflow/run_cache.rs +5 -3
  56. package/sdk-core/core/src/worker/workflow/workflow_stream.rs +7 -5
  57. package/sdk-core/core-api/Cargo.toml +3 -3
  58. package/sdk-core/core-api/src/errors.rs +3 -11
  59. package/sdk-core/core-api/src/worker.rs +7 -0
  60. package/sdk-core/protos/api_upstream/.buildkite/Dockerfile +1 -1
  61. package/sdk-core/protos/api_upstream/.github/CODEOWNERS +1 -1
  62. package/sdk-core/protos/api_upstream/.github/PULL_REQUEST_TEMPLATE.md +2 -6
  63. package/sdk-core/protos/api_upstream/.github/workflows/trigger-api-go-update.yml +29 -0
  64. package/sdk-core/protos/api_upstream/Makefile +2 -2
  65. package/sdk-core/protos/api_upstream/buf.yaml +1 -0
  66. package/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +86 -0
  67. package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +26 -0
  68. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +46 -0
  69. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +7 -0
  70. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +14 -0
  71. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +51 -0
  72. package/sdk-core/protos/api_upstream/temporal/api/failure/v1/message.proto +18 -0
  73. package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +57 -1
  74. package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +1 -3
  75. package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +4 -2
  76. package/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +11 -0
  77. package/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +23 -0
  78. package/sdk-core/protos/api_upstream/temporal/api/update/v1/message.proto +46 -0
  79. package/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +1 -0
  80. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +172 -0
  81. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +30 -0
  82. package/sdk-core/protos/grpc/health/v1/health.proto +63 -0
  83. package/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +18 -15
  84. package/sdk-core/protos/testsrv_upstream/Makefile +80 -0
  85. package/sdk-core/protos/testsrv_upstream/api-linter.yaml +38 -0
  86. package/sdk-core/protos/testsrv_upstream/buf.yaml +13 -0
  87. package/sdk-core/protos/testsrv_upstream/dependencies/gogoproto/gogo.proto +141 -0
  88. package/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +63 -0
  89. package/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +90 -0
  90. package/sdk-core/sdk/Cargo.toml +2 -2
  91. package/sdk-core/sdk/src/lib.rs +2 -2
  92. package/sdk-core/sdk/src/workflow_context/options.rs +36 -8
  93. package/sdk-core/sdk/src/workflow_context.rs +30 -6
  94. package/sdk-core/sdk/src/workflow_future.rs +4 -4
  95. package/sdk-core/sdk-core-protos/Cargo.toml +5 -5
  96. package/sdk-core/sdk-core-protos/build.rs +9 -1
  97. package/sdk-core/sdk-core-protos/src/history_builder.rs +6 -1
  98. package/sdk-core/sdk-core-protos/src/lib.rs +93 -32
  99. package/sdk-core/test-utils/Cargo.toml +3 -3
  100. package/sdk-core/test-utils/src/canned_histories.rs +58 -0
  101. package/sdk-core/test-utils/src/lib.rs +35 -12
  102. package/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +128 -0
  103. package/sdk-core/tests/integ_tests/heartbeat_tests.rs +55 -5
  104. package/sdk-core/tests/integ_tests/polling_tests.rs +2 -1
  105. package/sdk-core/tests/integ_tests/queries_tests.rs +5 -5
  106. package/sdk-core/tests/integ_tests/visibility_tests.rs +93 -0
  107. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +93 -10
  108. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +1 -1
  109. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +14 -14
  110. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +2 -6
  111. package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +12 -12
  112. package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +12 -1
  113. package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +3 -3
  114. package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +8 -2
  115. package/sdk-core/tests/integ_tests/workflow_tests.rs +19 -4
  116. package/sdk-core/tests/load_tests.rs +2 -1
  117. package/sdk-core/tests/main.rs +17 -0
  118. package/sdk-core/tests/runner.rs +93 -0
  119. package/src/conversions.rs +157 -94
  120. package/src/helpers.rs +190 -0
  121. package/src/lib.rs +10 -912
  122. package/src/runtime.rs +436 -0
  123. package/src/testing.rs +67 -0
  124. 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,
@@ -77,12 +78,14 @@ use tokio_util::sync::CancellationToken;
77
78
  use tracing::Span;
78
79
 
79
80
  pub(crate) const LEGACY_QUERY_ID: &str = "legacy_query";
81
+ const MAX_EAGER_ACTIVITY_RESERVATIONS_PER_WORKFLOW_TASK: usize = 3;
80
82
 
81
83
  type Result<T, E = WFMachinesError> = result::Result<T, E>;
82
84
  type BoxedActivationStream = BoxStream<'static, Result<ActivationOrAuto, PollWfError>>;
83
85
 
84
86
  /// Centralizes all state related to workflows and workflow tasks
85
87
  pub(crate) struct Workflows {
88
+ task_queue: String,
86
89
  local_tx: UnboundedSender<LocalInput>,
87
90
  processing_task: tokio::sync::Mutex<Option<JoinHandle<()>>>,
88
91
  activation_stream: tokio::sync::Mutex<(
@@ -90,7 +93,7 @@ pub(crate) struct Workflows {
90
93
  // Used to indicate polling may begin
91
94
  Option<oneshot::Sender<()>>,
92
95
  )>,
93
- client: Arc<WorkerClientBag>,
96
+ client: Arc<dyn WorkerClient>,
94
97
  /// Will be populated when this worker is using a cache and should complete WFTs with a sticky
95
98
  /// queue.
96
99
  sticky_attrs: Option<StickyExecutionAttributes>,
@@ -103,13 +106,15 @@ pub(super) struct WorkflowBasics {
103
106
  pub max_outstanding_wfts: usize,
104
107
  pub shutdown_token: CancellationToken,
105
108
  pub metrics: MetricsContext,
109
+ pub namespace: String,
110
+ pub task_queue: String,
106
111
  }
107
112
 
108
113
  impl Workflows {
109
114
  pub(super) fn new(
110
115
  basics: WorkflowBasics,
111
116
  sticky_attrs: Option<StickyExecutionAttributes>,
112
- client: Arc<WorkerClientBag>,
117
+ client: Arc<dyn WorkerClient>,
113
118
  wft_stream: impl Stream<Item = Result<ValidPollWFTQResponse, tonic::Status>> + Send + 'static,
114
119
  local_activity_request_sink: impl Fn(Vec<LocalActRequest>) -> Vec<LocalActivityResolution>
115
120
  + Send
@@ -119,6 +124,7 @@ impl Workflows {
119
124
  ) -> Self {
120
125
  let (local_tx, local_rx) = unbounded_channel();
121
126
  let shutdown_tok = basics.shutdown_token.clone();
127
+ let task_queue = basics.task_queue.clone();
122
128
  let mut stream = WFStream::build(
123
129
  basics,
124
130
  wft_stream,
@@ -151,6 +157,7 @@ impl Workflows {
151
157
  }
152
158
  });
153
159
  Self {
160
+ task_queue,
154
161
  local_tx,
155
162
  processing_task: tokio::sync::Mutex::new(Some(processing_task)),
156
163
  activation_stream: tokio::sync::Mutex::new((
@@ -263,14 +270,14 @@ impl Workflows {
263
270
  );
264
271
  Ok(())
265
272
  })
266
- .await?;
273
+ .await;
267
274
  true
268
275
  }
269
276
  ServerCommandsWithWorkflowInfo {
270
277
  task_token,
271
278
  action: ActivationAction::RespondLegacyQuery { result },
272
279
  } => {
273
- self.respond_legacy_query(task_token, result).await?;
280
+ self.respond_legacy_query(task_token, *result).await;
274
281
  true
275
282
  }
276
283
  },
@@ -282,13 +289,13 @@ impl Workflows {
282
289
  .fail_workflow_task(tt, cause, failure.failure.map(Into::into))
283
290
  .await
284
291
  })
285
- .await?;
292
+ .await;
286
293
  true
287
294
  }
288
295
  FailedActivationWFTReport::ReportLegacyQueryFailure(task_token, failure) => {
289
296
  warn!(run_id=%run_id, failure=?failure, "Failing legacy query request");
290
297
  self.respond_legacy_query(task_token, legacy_query_failure(failure))
291
- .await?;
298
+ .await;
292
299
  true
293
300
  }
294
301
  },
@@ -350,47 +357,34 @@ impl Workflows {
350
357
  self.send_local(msg);
351
358
  }
352
359
 
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>
360
+ /// Handle server errors from either completing or failing a workflow task. Un-handleable errors
361
+ /// trigger a workflow eviction and are logged.
362
+ async fn handle_wft_reporting_errs<T, Fut>(&self, run_id: &str, completer: impl FnOnce() -> Fut)
360
363
  where
361
364
  Fut: Future<Output = Result<T, tonic::Status>>,
362
365
  {
363
366
  let mut should_evict = None;
364
- let res = match completer().await {
365
- Err(err) => {
366
- if should_swallow_net_error(&err) {
367
+ if let Err(err) = completer().await {
368
+ match err.code() {
369
+ // Silence unhandled command errors since the lang SDK cannot do anything
370
+ // about them besides poll again, which it will do anyway.
371
+ tonic::Code::InvalidArgument if err.message() == "UnhandledCommand" => {
372
+ debug!(error = %err, run_id, "Unhandled command response when completing");
373
+ should_evict = Some(EvictionReason::UnhandledCommand);
374
+ }
375
+ tonic::Code::NotFound => {
376
+ warn!(error = %err, run_id, "Task not found when completing");
377
+ should_evict = Some(EvictionReason::TaskNotFound);
378
+ }
379
+ _ => {
367
380
  warn!(error= %err, "Network error while completing workflow activation");
368
381
  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
382
  }
387
383
  }
388
- _ => Ok(()),
389
- };
384
+ }
390
385
  if let Some(reason) = should_evict {
391
386
  self.request_eviction(run_id, "Error reporting WFT to server", reason);
392
387
  }
393
- res.map_err(Into::into)
394
388
  }
395
389
 
396
390
  /// Sends a message to the workflow processing stream. Returns true if the message was sent
@@ -471,10 +465,22 @@ impl Workflows {
471
465
  {
472
466
  // If request_eager_execution was already false, that means lang explicitly
473
467
  // 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.
468
+ // ever turn *off* eager execution if a slot is not available or the activity
469
+ // is scheduled on a different task queue.
475
470
  if attrs.request_eager_execution {
476
- if let Some(p) = at_handle.reserve_slot() {
477
- reserved.push(p);
471
+ let same_task_queue = attrs
472
+ .task_queue
473
+ .as_ref()
474
+ .map(|q| q.name == self.task_queue)
475
+ .unwrap_or_default();
476
+ if same_task_queue
477
+ && reserved.len() < MAX_EAGER_ACTIVITY_RESERVATIONS_PER_WORKFLOW_TASK
478
+ {
479
+ if let Some(p) = at_handle.reserve_slot() {
480
+ reserved.push(p);
481
+ } else {
482
+ attrs.request_eager_execution = false;
483
+ }
478
484
  } else {
479
485
  attrs.request_eager_execution = false;
480
486
  }
@@ -486,22 +492,15 @@ impl Workflows {
486
492
  }
487
493
 
488
494
  /// 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> {
495
+ async fn respond_legacy_query(&self, tt: TaskToken, res: QueryResult) {
494
496
  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
- }
497
+ Ok(_) => {}
500
498
  Err(e) if e.code() == tonic::Code::NotFound => {
501
499
  warn!(error=?e, "Query not found when attempting to respond to it");
502
- Ok(())
503
500
  }
504
- Err(e) => Err(e),
501
+ Err(e) => {
502
+ warn!(error= %e, "Network error while responding to legacy query");
503
+ }
505
504
  }
506
505
  }
507
506
  }
@@ -794,7 +793,7 @@ pub(crate) enum ActivationAction {
794
793
  force_new_wft: bool,
795
794
  },
796
795
  /// We should respond to a legacy query request
797
- RespondLegacyQuery { result: QueryResult },
796
+ RespondLegacyQuery { result: Box<QueryResult> },
798
797
  }
799
798
 
800
799
  #[derive(Debug, Eq, PartialEq, Hash)]
@@ -847,6 +846,7 @@ struct ActivationCompleteResult {
847
846
  }
848
847
  /// What needs to be done after calling [Workflows::activation_completed]
849
848
  #[derive(Debug)]
849
+ #[allow(clippy::large_enum_variant)]
850
850
  enum ActivationCompleteOutcome {
851
851
  /// The WFT must be reported as successful to the server using the contained information.
852
852
  ReportWFTSuccess(ServerCommandsWithWorkflowInfo),
@@ -917,6 +917,7 @@ fn validate_completion(
917
917
  }
918
918
 
919
919
  #[derive(Debug)]
920
+ #[allow(clippy::large_enum_variant)]
920
921
  enum ValidatedCompletion {
921
922
  Success {
922
923
  run_id: String,
@@ -944,6 +945,7 @@ struct RunAction {
944
945
  trace_span: Span,
945
946
  }
946
947
  #[derive(Debug)]
948
+ #[allow(clippy::large_enum_variant)]
947
949
  enum RunActions {
948
950
  NewIncomingWFT(NewIncomingWFT),
949
951
  ActivationCompletion(RunActivationCompletion),
@@ -984,6 +986,7 @@ struct RunUpdateResponse {
984
986
  span: Span,
985
987
  }
986
988
  #[derive(Debug, derive_more::Display)]
989
+ #[allow(clippy::large_enum_variant)]
987
990
  enum RunUpdateResponseKind {
988
991
  Good(GoodRunUpdate),
989
992
  Fail(FailRunUpdate),
@@ -1068,7 +1071,7 @@ pub enum WFCommand {
1068
1071
  CancelWorkflow(CancelWorkflowExecution),
1069
1072
  SetPatchMarker(SetPatchMarker),
1070
1073
  AddChildWorkflow(StartChildWorkflowExecution),
1071
- CancelUnstartedChild(CancelUnstartedChildWorkflowExecution),
1074
+ CancelChild(CancelChildWorkflowExecution),
1072
1075
  RequestCancelExternalWorkflow(RequestCancelExternalWorkflowExecution),
1073
1076
  SignalExternalWorkflow(SignalExternalWorkflowExecution),
1074
1077
  CancelSignalWorkflow(CancelSignalWorkflow),
@@ -1106,9 +1109,7 @@ impl TryFrom<WorkflowCommand> for WFCommand {
1106
1109
  Ok(Self::SignalExternalWorkflow(s))
1107
1110
  }
1108
1111
  workflow_command::Variant::CancelSignalWorkflow(s) => Ok(Self::CancelSignalWorkflow(s)),
1109
- workflow_command::Variant::CancelUnstartedChildWorkflowExecution(s) => {
1110
- Ok(Self::CancelUnstartedChild(s))
1111
- }
1112
+ workflow_command::Variant::CancelChildWorkflowExecution(s) => Ok(Self::CancelChild(s)),
1112
1113
  workflow_command::Variant::ScheduleLocalActivity(s) => Ok(Self::AddLocalActivity(s)),
1113
1114
  workflow_command::Variant::RequestCancelLocalActivity(s) => {
1114
1115
  Ok(Self::RequestCancelLocalActivity(s))
@@ -1136,6 +1137,9 @@ enum CommandID {
1136
1137
  pub struct WorkflowStartedInfo {
1137
1138
  workflow_task_timeout: Option<Duration>,
1138
1139
  workflow_execution_timeout: Option<Duration>,
1140
+ memo: Option<Memo>,
1141
+ search_attrs: Option<SearchAttributes>,
1142
+ retry_policy: Option<RetryPolicy>,
1139
1143
  }
1140
1144
 
1141
1145
  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
  );
@@ -17,10 +17,10 @@ anyhow = "1.0"
17
17
  async-trait = "0.1"
18
18
  derive_builder = "0.11"
19
19
  log = "0.4"
20
- opentelemetry = "0.17"
21
- prost-types = "0.9"
20
+ opentelemetry = "0.18"
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
  }