@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.
- package/Cargo.lock +786 -54
- package/Cargo.toml +2 -2
- package/common.js +7 -3
- package/index.d.ts +110 -3
- package/index.js +2 -6
- package/package.json +3 -3
- package/releases/aarch64-apple-darwin/index.node +0 -0
- package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
- package/releases/x86_64-apple-darwin/index.node +0 -0
- package/releases/x86_64-pc-windows-msvc/index.node +0 -0
- package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
- package/scripts/build.js +4 -3
- package/sdk-core/.buildkite/docker/Dockerfile +2 -1
- package/sdk-core/ARCHITECTURE.md +2 -2
- package/sdk-core/README.md +12 -0
- package/sdk-core/bridge-ffi/Cargo.toml +2 -2
- package/sdk-core/client/Cargo.toml +6 -4
- package/sdk-core/client/src/lib.rs +338 -215
- package/sdk-core/client/src/raw.rs +352 -106
- package/sdk-core/client/src/retry.rs +159 -133
- package/sdk-core/client/src/workflow_handle/mod.rs +1 -1
- package/sdk-core/core/Cargo.toml +18 -9
- package/sdk-core/core/src/core_tests/activity_tasks.rs +63 -23
- package/sdk-core/core/src/core_tests/child_workflows.rs +125 -3
- package/sdk-core/core/src/core_tests/local_activities.rs +6 -6
- package/sdk-core/core/src/core_tests/workers.rs +3 -2
- package/sdk-core/core/src/core_tests/workflow_tasks.rs +70 -2
- package/sdk-core/core/src/ephemeral_server/mod.rs +499 -0
- package/sdk-core/core/src/lib.rs +60 -26
- package/sdk-core/core/src/pollers/poll_buffer.rs +4 -4
- package/sdk-core/core/src/replay/mod.rs +3 -3
- package/sdk-core/core/src/retry_logic.rs +10 -9
- package/sdk-core/core/src/telemetry/mod.rs +10 -7
- package/sdk-core/core/src/test_help/mod.rs +18 -8
- package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +10 -10
- package/sdk-core/core/src/worker/activities/local_activities.rs +13 -13
- package/sdk-core/core/src/worker/activities.rs +6 -12
- package/sdk-core/core/src/worker/client.rs +193 -64
- package/sdk-core/core/src/worker/mod.rs +14 -19
- package/sdk-core/core/src/worker/workflow/driven_workflow.rs +3 -0
- package/sdk-core/core/src/worker/workflow/history_update.rs +5 -5
- package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +133 -85
- package/sdk-core/core/src/worker/workflow/machines/mod.rs +3 -2
- package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +160 -105
- package/sdk-core/core/src/worker/workflow/managed_run.rs +2 -1
- package/sdk-core/core/src/worker/workflow/mod.rs +59 -58
- package/sdk-core/core/src/worker/workflow/run_cache.rs +5 -3
- package/sdk-core/core/src/worker/workflow/workflow_stream.rs +7 -5
- package/sdk-core/core-api/Cargo.toml +2 -2
- package/sdk-core/core-api/src/errors.rs +3 -11
- package/sdk-core/core-api/src/worker.rs +7 -0
- package/sdk-core/protos/api_upstream/.buildkite/Dockerfile +1 -1
- package/sdk-core/protos/api_upstream/.github/CODEOWNERS +1 -1
- package/sdk-core/protos/api_upstream/.github/PULL_REQUEST_TEMPLATE.md +2 -6
- package/sdk-core/protos/api_upstream/.github/workflows/trigger-api-go-update.yml +29 -0
- package/sdk-core/protos/api_upstream/Makefile +2 -2
- package/sdk-core/protos/api_upstream/buf.yaml +1 -0
- package/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +86 -0
- package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +26 -0
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +46 -0
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +7 -0
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +14 -0
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +51 -0
- package/sdk-core/protos/api_upstream/temporal/api/failure/v1/message.proto +18 -0
- package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +57 -1
- package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +1 -3
- package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +4 -2
- package/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +11 -0
- package/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +23 -0
- package/sdk-core/protos/api_upstream/temporal/api/update/v1/message.proto +46 -0
- package/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +1 -0
- package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +172 -0
- package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +30 -0
- package/sdk-core/protos/grpc/health/v1/health.proto +63 -0
- package/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +18 -15
- package/sdk-core/protos/testsrv_upstream/Makefile +80 -0
- package/sdk-core/protos/testsrv_upstream/api-linter.yaml +38 -0
- package/sdk-core/protos/testsrv_upstream/buf.yaml +13 -0
- package/sdk-core/protos/testsrv_upstream/dependencies/gogoproto/gogo.proto +141 -0
- package/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +63 -0
- package/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +90 -0
- package/sdk-core/sdk/Cargo.toml +2 -2
- package/sdk-core/sdk/src/lib.rs +2 -2
- package/sdk-core/sdk/src/workflow_context/options.rs +36 -8
- package/sdk-core/sdk/src/workflow_context.rs +30 -6
- package/sdk-core/sdk/src/workflow_future.rs +4 -4
- package/sdk-core/sdk-core-protos/Cargo.toml +5 -5
- package/sdk-core/sdk-core-protos/build.rs +9 -1
- package/sdk-core/sdk-core-protos/src/history_builder.rs +6 -1
- package/sdk-core/sdk-core-protos/src/lib.rs +93 -32
- package/sdk-core/test-utils/Cargo.toml +3 -3
- package/sdk-core/test-utils/src/canned_histories.rs +58 -0
- package/sdk-core/test-utils/src/lib.rs +14 -10
- package/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +141 -0
- package/sdk-core/tests/integ_tests/heartbeat_tests.rs +55 -5
- package/sdk-core/tests/integ_tests/polling_tests.rs +1 -1
- package/sdk-core/tests/integ_tests/queries_tests.rs +4 -4
- package/sdk-core/tests/integ_tests/visibility_tests.rs +93 -0
- package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +93 -10
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +14 -14
- package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +12 -12
- package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +12 -1
- package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +3 -3
- package/sdk-core/tests/integ_tests/workflow_tests.rs +19 -4
- package/sdk-core/tests/load_tests.rs +2 -1
- package/sdk-core/tests/main.rs +10 -0
- package/src/conversions.rs +138 -91
- package/src/helpers.rs +190 -0
- package/src/lib.rs +10 -912
- package/src/runtime.rs +436 -0
- package/src/testing.rs +67 -0
- 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::
|
|
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,
|
|
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<
|
|
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<
|
|
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.
|
|
354
|
-
///
|
|
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
|
|
365
|
-
|
|
366
|
-
|
|
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
|
-
|
|
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
|
-
|
|
477
|
-
|
|
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(_) =>
|
|
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) =>
|
|
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
|
-
|
|
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::
|
|
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(
|
|
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,
|
|
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<
|
|
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<
|
|
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
|
-
|
|
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 {
|
|
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.
|
|
21
|
+
prost-types = "0.11"
|
|
22
22
|
thiserror = "1.0"
|
|
23
|
-
tonic = "0.
|
|
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::
|
|
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<
|
|
100
|
-
fn from(_:
|
|
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.
|
|
1
|
+
FROM temporalio/base-ci-builder:1.5.0
|
|
2
2
|
WORKDIR /temporal
|
|
@@ -6,10 +6,6 @@
|
|
|
6
6
|
**Why?**
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
<!--
|
|
10
|
-
**
|
|
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
|
|
@@ -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
|
}
|