@temporalio/core-bridge 1.8.5 → 1.9.0-rc.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.
- package/Cargo.lock +189 -152
- package/Cargo.toml +1 -0
- package/lib/index.d.ts +17 -44
- package/lib/index.js.map +1 -1
- package/package.json +3 -4
- 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/sdk-core/.github/workflows/heavy.yml +4 -0
- package/sdk-core/.github/workflows/per-pr.yml +96 -0
- package/sdk-core/ARCHITECTURE.md +1 -1
- package/sdk-core/Cargo.toml +6 -0
- package/sdk-core/README.md +37 -21
- package/sdk-core/client/Cargo.toml +6 -3
- package/sdk-core/client/src/lib.rs +272 -138
- package/sdk-core/client/src/metrics.rs +68 -57
- package/sdk-core/client/src/raw.rs +191 -45
- package/sdk-core/client/src/retry.rs +20 -0
- package/sdk-core/client/src/worker_registry/mod.rs +264 -0
- package/sdk-core/client/src/workflow_handle/mod.rs +2 -1
- package/sdk-core/core/Cargo.toml +16 -18
- package/sdk-core/core/src/core_tests/child_workflows.rs +7 -7
- package/sdk-core/core/src/core_tests/mod.rs +1 -0
- package/sdk-core/core/src/core_tests/replay_flag.rs +29 -39
- package/sdk-core/core/src/core_tests/updates.rs +73 -0
- package/sdk-core/core/src/core_tests/workflow_tasks.rs +52 -1
- package/sdk-core/core/src/ephemeral_server/mod.rs +34 -11
- package/sdk-core/core/src/internal_flags.rs +7 -1
- package/sdk-core/core/src/lib.rs +19 -36
- package/sdk-core/core/src/protosext/mod.rs +11 -3
- package/sdk-core/core/src/protosext/protocol_messages.rs +102 -0
- package/sdk-core/core/src/replay/mod.rs +100 -48
- package/sdk-core/core/src/telemetry/log_export.rs +161 -28
- package/sdk-core/core/src/telemetry/metrics.rs +869 -248
- package/sdk-core/core/src/telemetry/mod.rs +135 -239
- package/sdk-core/core/src/telemetry/prometheus_server.rs +36 -31
- package/sdk-core/core/src/test_help/mod.rs +63 -4
- package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +12 -2
- package/sdk-core/core/src/worker/activities.rs +276 -10
- package/sdk-core/core/src/worker/client/mocks.rs +18 -0
- package/sdk-core/core/src/worker/client.rs +16 -3
- package/sdk-core/core/src/worker/mod.rs +50 -19
- package/sdk-core/core/src/worker/slot_provider.rs +175 -0
- package/sdk-core/core/src/worker/workflow/driven_workflow.rs +27 -34
- package/sdk-core/core/src/worker/workflow/history_update.rs +4 -1
- package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +36 -94
- package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +34 -22
- package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +50 -34
- package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +106 -92
- package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +22 -21
- package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +386 -499
- package/sdk-core/core/src/worker/workflow/machines/mod.rs +12 -2
- package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +33 -26
- package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +198 -215
- package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +66 -62
- package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +88 -119
- package/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +3 -1
- package/sdk-core/core/src/worker/workflow/machines/update_state_machine.rs +411 -0
- package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +26 -25
- package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +302 -85
- package/sdk-core/core/src/worker/workflow/managed_run.rs +179 -132
- package/sdk-core/core/src/worker/workflow/mod.rs +121 -46
- package/sdk-core/core/src/worker/workflow/run_cache.rs +8 -12
- package/sdk-core/core/src/worker/workflow/workflow_stream.rs +45 -38
- package/sdk-core/core-api/Cargo.toml +7 -6
- package/sdk-core/core-api/src/lib.rs +4 -12
- package/sdk-core/core-api/src/telemetry/metrics.rs +334 -0
- package/sdk-core/core-api/src/telemetry.rs +53 -42
- package/sdk-core/core-api/src/worker.rs +7 -0
- package/sdk-core/{.buildkite/docker → docker}/docker-compose.yaml +1 -1
- package/sdk-core/etc/dynamic-config.yaml +11 -1
- package/sdk-core/fsm/rustfsm_procmacro/Cargo.toml +1 -1
- package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +1 -3
- package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +2 -2
- package/sdk-core/sdk/Cargo.toml +1 -1
- package/sdk-core/sdk/src/lib.rs +85 -7
- package/sdk-core/sdk/src/workflow_context/options.rs +4 -0
- package/sdk-core/sdk/src/workflow_context.rs +43 -15
- package/sdk-core/sdk/src/workflow_future.rs +334 -204
- package/sdk-core/sdk-core-protos/Cargo.toml +2 -2
- package/sdk-core/sdk-core-protos/build.rs +14 -14
- package/sdk-core/sdk-core-protos/protos/api_upstream/.buildkite/Dockerfile +2 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/Makefile +99 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/api-linter.yaml +56 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/buf.gen.yaml +20 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/buf.lock +11 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/buf.yaml +18 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/google/api/annotations.proto +31 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/google/api/http.proto +379 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/any.proto +162 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/descriptor.proto +1212 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/duration.proto +115 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/empty.proto +51 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/timestamp.proto +144 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/wrappers.proto +123 -0
- package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/batch/v1/message.proto +3 -5
- package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/command/v1/message.proto +11 -13
- package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/common/v1/message.proto +2 -4
- package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/failed_cause.proto +2 -0
- package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/reset.proto +1 -1
- package/sdk-core/{protos/api_upstream/build/tools.go → sdk-core-protos/protos/api_upstream/temporal/api/export/v1/message.proto} +22 -6
- package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/filter/v1/message.proto +2 -4
- package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/history/v1/message.proto +21 -23
- package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/namespace/v1/message.proto +2 -4
- package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/operatorservice/v1/request_response.proto +2 -0
- package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/operatorservice/v1/service.proto +4 -0
- package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/replication/v1/message.proto +1 -3
- package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/schedule/v1/message.proto +36 -20
- package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +13 -0
- package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/taskqueue/v1/message.proto +2 -4
- package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/update/v1/message.proto +1 -1
- package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/version/v1/message.proto +2 -3
- package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/workflow/v1/message.proto +18 -20
- package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/workflowservice/v1/request_response.proto +84 -32
- package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/workflowservice/v1/service.proto +205 -47
- package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +57 -0
- package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +27 -0
- package/sdk-core/sdk-core-protos/src/history_builder.rs +67 -2
- package/sdk-core/sdk-core-protos/src/lib.rs +75 -2
- package/sdk-core/sdk-core-protos/src/utilities.rs +14 -0
- package/sdk-core/test-utils/Cargo.toml +5 -1
- package/sdk-core/test-utils/src/canned_histories.rs +3 -57
- package/sdk-core/test-utils/src/interceptors.rs +46 -0
- package/sdk-core/test-utils/src/lib.rs +106 -38
- package/sdk-core/tests/integ_tests/metrics_tests.rs +110 -15
- package/sdk-core/tests/integ_tests/queries_tests.rs +174 -3
- package/sdk-core/tests/integ_tests/update_tests.rs +908 -0
- package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +44 -1
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +4 -4
- package/sdk-core/tests/integ_tests/workflow_tests/eager.rs +61 -0
- package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +27 -2
- package/sdk-core/tests/integ_tests/workflow_tests.rs +1 -0
- package/sdk-core/tests/main.rs +2 -1
- package/sdk-core/tests/runner.rs +15 -2
- package/src/conversions.rs +75 -89
- package/src/helpers.rs +74 -0
- package/src/runtime.rs +17 -6
- package/src/worker.rs +14 -61
- package/ts/index.ts +21 -52
- package/sdk-core/.buildkite/docker/Dockerfile +0 -9
- package/sdk-core/.buildkite/docker/build.sh +0 -5
- package/sdk-core/.buildkite/docker/docker-compose-ci.yaml +0 -27
- package/sdk-core/.buildkite/pipeline.yml +0 -57
- package/sdk-core/.github/workflows/semgrep.yml +0 -25
- package/sdk-core/core/src/worker/workflow/bridge.rs +0 -35
- package/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +0 -215
- package/sdk-core/protos/api_upstream/.buildkite/Dockerfile +0 -2
- package/sdk-core/protos/api_upstream/Makefile +0 -80
- package/sdk-core/protos/api_upstream/api-linter.yaml +0 -40
- package/sdk-core/protos/api_upstream/buf.yaml +0 -9
- package/sdk-core/protos/api_upstream/build/go.mod +0 -7
- package/sdk-core/protos/api_upstream/build/go.sum +0 -5
- package/sdk-core/protos/api_upstream/go.mod +0 -6
- package/sdk-core/protos/testsrv_upstream/dependencies/gogoproto/gogo.proto +0 -141
- /package/sdk-core/{.buildkite/docker → docker}/docker-compose-telem.yaml +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.buildkite/docker-compose.yml +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.buildkite/pipeline.yml +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.github/CODEOWNERS +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.github/workflows/publish-docs.yml +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.github/workflows/trigger-api-go-update.yml +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/LICENSE +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/README.md +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/batch_operation.proto +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/command_type.proto +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/common.proto +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/event_type.proto +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/namespace.proto +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/query.proto +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/schedule.proto +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/task_queue.proto +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/update.proto +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/workflow.proto +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/errordetails/v1/message.proto +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/failure/v1/message.proto +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/protocol/v1/message.proto +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/query/v1/message.proto +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/google/rpc/status.proto +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/grpc/health/v1/health.proto +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/activity_result/activity_result.proto +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/activity_task/activity_task.proto +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/child_workflow/child_workflow.proto +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/common/common.proto +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/core_interface.proto +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/external_data/external_data.proto +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/Makefile +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/api-linter.yaml +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/buf.yaml +0 -0
- /package/sdk-core/{protos/api_upstream → sdk-core-protos/protos/testsrv_upstream}/dependencies/gogoproto/gogo.proto +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +0 -0
- /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/temporal/api/testservice/v1/service.proto +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
//! Worker-specific client needs
|
|
2
2
|
|
|
3
3
|
pub(crate) mod mocks;
|
|
4
|
-
|
|
5
|
-
use temporal_client::{Client, RetryClient, WorkflowService};
|
|
4
|
+
use std::sync::Arc;
|
|
5
|
+
use temporal_client::{Client, RetryClient, SlotManager, WorkflowService};
|
|
6
6
|
use temporal_sdk_core_protos::{
|
|
7
7
|
coresdk::workflow_commands::QueryResult,
|
|
8
8
|
temporal::api::{
|
|
@@ -13,6 +13,7 @@ use temporal_sdk_core_protos::{
|
|
|
13
13
|
},
|
|
14
14
|
enums::v1::{TaskQueueKind, WorkflowTaskFailedCause},
|
|
15
15
|
failure::v1::Failure,
|
|
16
|
+
protocol::v1::Message as ProtocolMessage,
|
|
16
17
|
query::v1::WorkflowQueryResult,
|
|
17
18
|
sdk::v1::WorkflowTaskCompletedMetadata,
|
|
18
19
|
taskqueue::v1::{StickyExecutionAttributes, TaskQueue, TaskQueueMetadata},
|
|
@@ -143,6 +144,8 @@ pub(crate) trait WorkerClient: Sync + Send {
|
|
|
143
144
|
|
|
144
145
|
#[allow(clippy::needless_lifetimes)] // Clippy is wrong here
|
|
145
146
|
fn capabilities<'a>(&'a self) -> Option<&'a get_system_info_response::Capabilities>;
|
|
147
|
+
fn workers(&self) -> Arc<SlotManager>;
|
|
148
|
+
fn is_mock(&self) -> bool;
|
|
146
149
|
}
|
|
147
150
|
|
|
148
151
|
#[async_trait::async_trait]
|
|
@@ -201,12 +204,12 @@ impl WorkerClient for WorkerClientBag {
|
|
|
201
204
|
let request = RespondWorkflowTaskCompletedRequest {
|
|
202
205
|
task_token: request.task_token.into(),
|
|
203
206
|
commands: request.commands,
|
|
207
|
+
messages: request.messages,
|
|
204
208
|
identity: self.identity.clone(),
|
|
205
209
|
sticky_attributes: request.sticky_attributes,
|
|
206
210
|
return_new_workflow_task: request.return_new_workflow_task,
|
|
207
211
|
force_create_new_workflow_task: request.force_create_new_workflow_task,
|
|
208
212
|
worker_version_stamp: self.worker_version_stamp(),
|
|
209
|
-
messages: vec![],
|
|
210
213
|
binary_checksum: self.binary_checksum(),
|
|
211
214
|
query_results: request
|
|
212
215
|
.query_responses
|
|
@@ -381,6 +384,14 @@ impl WorkerClient for WorkerClientBag {
|
|
|
381
384
|
fn capabilities(&self) -> Option<&Capabilities> {
|
|
382
385
|
self.client.get_client().inner().capabilities()
|
|
383
386
|
}
|
|
387
|
+
|
|
388
|
+
fn workers(&self) -> Arc<SlotManager> {
|
|
389
|
+
self.client.get_client().inner().workers()
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
fn is_mock(&self) -> bool {
|
|
393
|
+
false
|
|
394
|
+
}
|
|
384
395
|
}
|
|
385
396
|
|
|
386
397
|
/// A version of [RespondWorkflowTaskCompletedRequest] that will finish being filled out by the
|
|
@@ -391,6 +402,8 @@ pub(crate) struct WorkflowTaskCompletion {
|
|
|
391
402
|
pub task_token: TaskToken,
|
|
392
403
|
/// A list of new commands to send to the server, such as starting a timer.
|
|
393
404
|
pub commands: Vec<Command>,
|
|
405
|
+
/// A list of protocol messages to send to the server.
|
|
406
|
+
pub messages: Vec<ProtocolMessage>,
|
|
394
407
|
/// If set, indicate that next task should be queued on sticky queue with given attributes.
|
|
395
408
|
pub sticky_attributes: Option<StickyExecutionAttributes>,
|
|
396
409
|
/// Responses to queries in the `queries` field of the workflow task.
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
mod activities;
|
|
2
2
|
pub(crate) mod client;
|
|
3
|
+
mod slot_provider;
|
|
3
4
|
mod workflow;
|
|
4
5
|
|
|
5
6
|
pub use temporal_sdk_core_api::worker::{WorkerConfig, WorkerConfigBuilder};
|
|
@@ -12,13 +13,14 @@ pub(crate) use activities::{
|
|
|
12
13
|
};
|
|
13
14
|
pub(crate) use workflow::{wft_poller::new_wft_poller, LEGACY_QUERY_ID};
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
pub(crate) use workflow::ManagedWFFunc;
|
|
16
|
+
use temporal_client::WorkerKey;
|
|
17
17
|
|
|
18
18
|
use crate::{
|
|
19
|
-
abstractions::MeteredSemaphore,
|
|
19
|
+
abstractions::{dbg_panic, MeteredSemaphore},
|
|
20
20
|
errors::CompleteWfError,
|
|
21
|
-
pollers::{
|
|
21
|
+
pollers::{
|
|
22
|
+
new_activity_task_buffer, new_workflow_task_buffer, BoxedActPoller, WorkflowTaskPoller,
|
|
23
|
+
},
|
|
22
24
|
protosext::validate_activity_completion,
|
|
23
25
|
telemetry::{
|
|
24
26
|
metrics::{
|
|
@@ -35,6 +37,8 @@ use crate::{
|
|
|
35
37
|
ActivityHeartbeat, CompleteActivityError, PollActivityError, PollWfError, WorkerTrait,
|
|
36
38
|
};
|
|
37
39
|
use activities::WorkerActivityTasks;
|
|
40
|
+
use futures_util::{stream, StreamExt};
|
|
41
|
+
use slot_provider::SlotProvider;
|
|
38
42
|
use std::{
|
|
39
43
|
convert::TryInto,
|
|
40
44
|
future,
|
|
@@ -59,9 +63,9 @@ use temporal_sdk_core_protos::{
|
|
|
59
63
|
TaskToken,
|
|
60
64
|
};
|
|
61
65
|
use tokio::sync::mpsc::unbounded_channel;
|
|
66
|
+
use tokio_stream::wrappers::UnboundedReceiverStream;
|
|
62
67
|
use tokio_util::sync::CancellationToken;
|
|
63
68
|
|
|
64
|
-
use crate::{abstractions::dbg_panic, pollers::BoxedActPoller};
|
|
65
69
|
#[cfg(test)]
|
|
66
70
|
use {
|
|
67
71
|
crate::{
|
|
@@ -69,7 +73,6 @@ use {
|
|
|
69
73
|
protosext::ValidPollWFTQResponse,
|
|
70
74
|
},
|
|
71
75
|
futures::stream::BoxStream,
|
|
72
|
-
futures_util::StreamExt,
|
|
73
76
|
temporal_sdk_core_protos::temporal::api::workflowservice::v1::PollActivityTaskQueueResponse,
|
|
74
77
|
};
|
|
75
78
|
|
|
@@ -77,7 +80,8 @@ use {
|
|
|
77
80
|
pub struct Worker {
|
|
78
81
|
config: WorkerConfig,
|
|
79
82
|
wf_client: Arc<dyn WorkerClient>,
|
|
80
|
-
|
|
83
|
+
/// Registration key to enable eager workflow start for this worker
|
|
84
|
+
worker_key: Option<WorkerKey>,
|
|
81
85
|
/// Manages all workflows and WFT processing
|
|
82
86
|
workflows: Workflows,
|
|
83
87
|
/// Manages activity tasks for this worker/task queue
|
|
@@ -98,7 +102,15 @@ pub struct Worker {
|
|
|
98
102
|
#[async_trait::async_trait]
|
|
99
103
|
impl WorkerTrait for Worker {
|
|
100
104
|
async fn poll_workflow_activation(&self) -> Result<WorkflowActivation, PollWfError> {
|
|
101
|
-
self.next_workflow_activation().await
|
|
105
|
+
self.next_workflow_activation().await.map(|mut a| {
|
|
106
|
+
// Attach this worker's Build ID to the activation if appropriate. This is done here
|
|
107
|
+
// to avoid cloning the ID for every workflow instance. Can be lowered when
|
|
108
|
+
// https://github.com/temporalio/sdk-core/issues/567 is done
|
|
109
|
+
if !a.is_replaying {
|
|
110
|
+
a.build_id_for_current_task = self.config.worker_build_id.clone();
|
|
111
|
+
}
|
|
112
|
+
a
|
|
113
|
+
})
|
|
102
114
|
}
|
|
103
115
|
|
|
104
116
|
#[instrument(skip(self))]
|
|
@@ -164,7 +176,11 @@ impl WorkerTrait for Worker {
|
|
|
164
176
|
);
|
|
165
177
|
}
|
|
166
178
|
self.shutdown_token.cancel();
|
|
167
|
-
// First,
|
|
179
|
+
// First, disable Eager Workflow Start
|
|
180
|
+
if let Some(key) = self.worker_key {
|
|
181
|
+
self.wf_client.workers().unregister(key);
|
|
182
|
+
}
|
|
183
|
+
// Second, we want to stop polling of both activity and workflow tasks
|
|
168
184
|
if let Some(atm) = self.at_task_mgr.as_ref() {
|
|
169
185
|
atm.initiate_shutdown();
|
|
170
186
|
}
|
|
@@ -194,20 +210,12 @@ impl Worker {
|
|
|
194
210
|
telem_instance: Option<&TelemetryInstance>,
|
|
195
211
|
) -> Self {
|
|
196
212
|
info!(task_queue=%config.task_queue, namespace=%config.namespace, "Initializing worker");
|
|
197
|
-
let metrics = if let Some(ti) = telem_instance {
|
|
198
|
-
MetricsContext::top_level(config.namespace.clone(), ti)
|
|
199
|
-
.with_task_q(config.task_queue.clone())
|
|
200
|
-
} else {
|
|
201
|
-
MetricsContext::no_op()
|
|
202
|
-
};
|
|
203
|
-
metrics.worker_registered();
|
|
204
213
|
|
|
205
214
|
Self::new_with_pollers(
|
|
206
215
|
config,
|
|
207
216
|
sticky_queue_name,
|
|
208
217
|
client,
|
|
209
218
|
TaskPollers::Real,
|
|
210
|
-
metrics,
|
|
211
219
|
telem_instance,
|
|
212
220
|
)
|
|
213
221
|
}
|
|
@@ -223,9 +231,14 @@ impl Worker {
|
|
|
223
231
|
sticky_queue_name: Option<String>,
|
|
224
232
|
client: Arc<dyn WorkerClient>,
|
|
225
233
|
task_pollers: TaskPollers,
|
|
226
|
-
metrics: MetricsContext,
|
|
227
234
|
telem_instance: Option<&TelemetryInstance>,
|
|
228
235
|
) -> Self {
|
|
236
|
+
let metrics = if let Some(ti) = telem_instance {
|
|
237
|
+
MetricsContext::top_level(config.namespace.clone(), config.task_queue.clone(), ti)
|
|
238
|
+
} else {
|
|
239
|
+
MetricsContext::no_op()
|
|
240
|
+
};
|
|
241
|
+
metrics.worker_registered();
|
|
229
242
|
let shutdown_token = CancellationToken::new();
|
|
230
243
|
let wft_semaphore = Arc::new(MeteredSemaphore::new(
|
|
231
244
|
config.max_outstanding_workflow_tasks,
|
|
@@ -237,7 +250,7 @@ impl Worker {
|
|
|
237
250
|
metrics.with_new_attrs([activity_worker_type()]),
|
|
238
251
|
MetricsContext::available_task_slots,
|
|
239
252
|
));
|
|
240
|
-
|
|
253
|
+
let (external_wft_tx, external_wft_rx) = unbounded_channel();
|
|
241
254
|
let (wft_stream, act_poller) = match task_pollers {
|
|
242
255
|
TaskPollers::Real => {
|
|
243
256
|
let max_nonsticky_polls = if sticky_queue_name.is_some() {
|
|
@@ -299,6 +312,15 @@ impl Worker {
|
|
|
299
312
|
sticky_queue_poller,
|
|
300
313
|
));
|
|
301
314
|
let wft_stream = new_wft_poller(wf_task_poll_buffer, metrics.clone());
|
|
315
|
+
let wft_stream = if !client.is_mock() {
|
|
316
|
+
// Some replay tests combine a mock client with real pollers,
|
|
317
|
+
// and they don't need to use the external stream
|
|
318
|
+
stream::select(wft_stream, UnboundedReceiverStream::new(external_wft_rx))
|
|
319
|
+
.left_stream()
|
|
320
|
+
} else {
|
|
321
|
+
wft_stream.right_stream()
|
|
322
|
+
};
|
|
323
|
+
|
|
302
324
|
#[cfg(test)]
|
|
303
325
|
let wft_stream = wft_stream.left_stream();
|
|
304
326
|
(wft_stream, act_poll_buffer)
|
|
@@ -342,6 +364,7 @@ impl Worker {
|
|
|
342
364
|
config.max_heartbeat_throttle_interval,
|
|
343
365
|
config.default_heartbeat_throttle_interval,
|
|
344
366
|
config.graceful_shutdown_period,
|
|
367
|
+
config.local_timeout_buffer_for_activities,
|
|
345
368
|
)
|
|
346
369
|
});
|
|
347
370
|
let poll_on_non_local_activities = at_task_mgr.is_some();
|
|
@@ -349,7 +372,15 @@ impl Worker {
|
|
|
349
372
|
info!("Activity polling is disabled for this worker");
|
|
350
373
|
};
|
|
351
374
|
let la_sink = LAReqSink::new(local_act_mgr.clone(), config.wf_state_inputs.clone());
|
|
375
|
+
let provider = SlotProvider::new(
|
|
376
|
+
config.namespace.clone(),
|
|
377
|
+
config.task_queue.clone(),
|
|
378
|
+
wft_semaphore.clone(),
|
|
379
|
+
external_wft_tx,
|
|
380
|
+
);
|
|
381
|
+
let worker_key = client.workers().register(Box::new(provider));
|
|
352
382
|
Self {
|
|
383
|
+
worker_key,
|
|
353
384
|
wf_client: client.clone(),
|
|
354
385
|
workflows: Workflows::new(
|
|
355
386
|
build_wf_basics(
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
//! This module implements traits defined in the client to dispatch a
|
|
2
|
+
//! WFT to a worker bypassing the server.
|
|
3
|
+
//! This enables latency optimizations such as Eager Workflow Start.
|
|
4
|
+
|
|
5
|
+
use crate::{
|
|
6
|
+
abstractions::{MeteredSemaphore, OwnedMeteredSemPermit},
|
|
7
|
+
protosext::ValidPollWFTQResponse,
|
|
8
|
+
worker::workflow::wft_poller::validate_wft,
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
use std::sync::Arc;
|
|
12
|
+
use temporal_client::{Slot as SlotTrait, SlotProvider as SlotProviderTrait};
|
|
13
|
+
use temporal_sdk_core_protos::temporal::api::workflowservice::v1::PollWorkflowTaskQueueResponse;
|
|
14
|
+
use tokio::sync::mpsc::UnboundedSender;
|
|
15
|
+
use tonic::Status;
|
|
16
|
+
|
|
17
|
+
type WFTStreamSender =
|
|
18
|
+
UnboundedSender<Result<(ValidPollWFTQResponse, OwnedMeteredSemPermit), Status>>;
|
|
19
|
+
|
|
20
|
+
pub struct Slot {
|
|
21
|
+
permit: OwnedMeteredSemPermit,
|
|
22
|
+
external_wft_tx: WFTStreamSender,
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
impl Slot {
|
|
26
|
+
fn new(permit: OwnedMeteredSemPermit, external_wft_tx: WFTStreamSender) -> Self {
|
|
27
|
+
Self {
|
|
28
|
+
permit,
|
|
29
|
+
external_wft_tx,
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
impl SlotTrait for Slot {
|
|
35
|
+
fn schedule_wft(
|
|
36
|
+
self: Box<Self>,
|
|
37
|
+
task: PollWorkflowTaskQueueResponse,
|
|
38
|
+
) -> Result<(), anyhow::Error> {
|
|
39
|
+
let wft = validate_wft(task)?;
|
|
40
|
+
self.external_wft_tx.send(Ok((wft, self.permit)))?;
|
|
41
|
+
Ok(())
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
#[derive(derive_more::DebugCustom)]
|
|
46
|
+
#[debug(fmt = "SlotProvider {{ namespace:{namespace}, task_queue: {task_queue} }}")]
|
|
47
|
+
pub struct SlotProvider {
|
|
48
|
+
namespace: String,
|
|
49
|
+
task_queue: String,
|
|
50
|
+
wft_semaphore: Arc<MeteredSemaphore>,
|
|
51
|
+
external_wft_tx: WFTStreamSender,
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
impl SlotProvider {
|
|
55
|
+
pub(crate) fn new(
|
|
56
|
+
namespace: String,
|
|
57
|
+
task_queue: String,
|
|
58
|
+
wft_semaphore: Arc<MeteredSemaphore>,
|
|
59
|
+
external_wft_tx: WFTStreamSender,
|
|
60
|
+
) -> Self {
|
|
61
|
+
Self {
|
|
62
|
+
namespace,
|
|
63
|
+
task_queue,
|
|
64
|
+
wft_semaphore,
|
|
65
|
+
external_wft_tx,
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
impl SlotProviderTrait for SlotProvider {
|
|
71
|
+
fn namespace(&self) -> &str {
|
|
72
|
+
&self.namespace
|
|
73
|
+
}
|
|
74
|
+
fn task_queue(&self) -> &str {
|
|
75
|
+
&self.task_queue
|
|
76
|
+
}
|
|
77
|
+
fn try_reserve_wft_slot(&self) -> Option<Box<dyn SlotTrait + Send>> {
|
|
78
|
+
match self.wft_semaphore.try_acquire_owned().ok() {
|
|
79
|
+
Some(permit) => Some(Box::new(Slot::new(permit, self.external_wft_tx.clone()))),
|
|
80
|
+
None => None,
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
#[cfg(test)]
|
|
86
|
+
mod tests {
|
|
87
|
+
use super::*;
|
|
88
|
+
|
|
89
|
+
use temporal_sdk_core_protos::temporal::api::{
|
|
90
|
+
common::v1::{WorkflowExecution, WorkflowType},
|
|
91
|
+
history::v1::History,
|
|
92
|
+
taskqueue::v1::TaskQueue,
|
|
93
|
+
};
|
|
94
|
+
use tokio::sync::mpsc::unbounded_channel;
|
|
95
|
+
|
|
96
|
+
// make validate_wft() happy
|
|
97
|
+
fn new_validatable_response() -> PollWorkflowTaskQueueResponse {
|
|
98
|
+
PollWorkflowTaskQueueResponse {
|
|
99
|
+
workflow_execution_task_queue: Some(TaskQueue::default()),
|
|
100
|
+
workflow_execution: Some(WorkflowExecution::default()),
|
|
101
|
+
workflow_type: Some(WorkflowType::default()),
|
|
102
|
+
history: Some(History::default()),
|
|
103
|
+
..Default::default()
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
#[tokio::test]
|
|
108
|
+
async fn slot_propagates_through_channel() {
|
|
109
|
+
let wft_semaphore = Arc::new(MeteredSemaphore::new(
|
|
110
|
+
2,
|
|
111
|
+
crate::MetricsContext::no_op(),
|
|
112
|
+
|_, _| {},
|
|
113
|
+
));
|
|
114
|
+
let (external_wft_tx, mut external_wft_rx) = unbounded_channel();
|
|
115
|
+
|
|
116
|
+
let provider = SlotProvider::new(
|
|
117
|
+
"my_namespace".to_string(),
|
|
118
|
+
"my_queue".to_string(),
|
|
119
|
+
wft_semaphore,
|
|
120
|
+
external_wft_tx,
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
let slot = provider
|
|
124
|
+
.try_reserve_wft_slot()
|
|
125
|
+
.expect("failed to reserver slot");
|
|
126
|
+
let p = slot.schedule_wft(new_validatable_response());
|
|
127
|
+
assert!(p.is_ok());
|
|
128
|
+
assert!(external_wft_rx.recv().await.is_some());
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
#[tokio::test]
|
|
132
|
+
async fn channel_closes_when_provider_drops() {
|
|
133
|
+
let (external_wft_tx, mut external_wft_rx) = unbounded_channel();
|
|
134
|
+
{
|
|
135
|
+
let external_wft_tx = external_wft_tx;
|
|
136
|
+
let wft_semaphore = Arc::new(MeteredSemaphore::new(
|
|
137
|
+
2,
|
|
138
|
+
crate::MetricsContext::no_op(),
|
|
139
|
+
|_, _| {},
|
|
140
|
+
));
|
|
141
|
+
let provider = SlotProvider::new(
|
|
142
|
+
"my_namespace".to_string(),
|
|
143
|
+
"my_queue".to_string(),
|
|
144
|
+
wft_semaphore,
|
|
145
|
+
external_wft_tx,
|
|
146
|
+
);
|
|
147
|
+
assert!(provider.try_reserve_wft_slot().is_some());
|
|
148
|
+
}
|
|
149
|
+
assert!(external_wft_rx.recv().await.is_none());
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
#[tokio::test]
|
|
153
|
+
async fn unused_slots_reclaimed() {
|
|
154
|
+
let wft_semaphore = Arc::new(MeteredSemaphore::new(
|
|
155
|
+
2,
|
|
156
|
+
crate::MetricsContext::no_op(),
|
|
157
|
+
|_, _| {},
|
|
158
|
+
));
|
|
159
|
+
{
|
|
160
|
+
let wft_semaphore = wft_semaphore.clone();
|
|
161
|
+
let (external_wft_tx, _) = unbounded_channel();
|
|
162
|
+
let provider = SlotProvider::new(
|
|
163
|
+
"my_namespace".to_string(),
|
|
164
|
+
"my_queue".to_string(),
|
|
165
|
+
wft_semaphore.clone(),
|
|
166
|
+
external_wft_tx,
|
|
167
|
+
);
|
|
168
|
+
let slot = provider.try_reserve_wft_slot();
|
|
169
|
+
assert!(slot.is_some());
|
|
170
|
+
assert_eq!(wft_semaphore.available_permits(), 1);
|
|
171
|
+
// drop slot without using it
|
|
172
|
+
}
|
|
173
|
+
assert_eq!(wft_semaphore.available_permits(), 2);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
@@ -1,34 +1,36 @@
|
|
|
1
|
-
use crate::
|
|
1
|
+
use crate::{
|
|
2
|
+
telemetry::VecDisplayer,
|
|
3
|
+
worker::workflow::{OutgoingJob, WFCommand, WorkflowStartedInfo},
|
|
4
|
+
};
|
|
2
5
|
use prost_types::Timestamp;
|
|
6
|
+
use std::sync::mpsc::{self, Receiver, Sender};
|
|
3
7
|
use temporal_sdk_core_protos::{
|
|
4
8
|
coresdk::workflow_activation::{start_workflow_from_attribs, WorkflowActivationJob},
|
|
5
9
|
temporal::api::history::v1::WorkflowExecutionStartedEventAttributes,
|
|
6
10
|
utilities::TryIntoOrNone,
|
|
7
11
|
};
|
|
8
12
|
|
|
9
|
-
///
|
|
10
|
-
///
|
|
13
|
+
/// Represents a connection to a lang side workflow that can have activations fed into it and
|
|
14
|
+
/// command responses pulled out.
|
|
11
15
|
pub struct DrivenWorkflow {
|
|
12
16
|
started_attrs: Option<WorkflowStartedInfo>,
|
|
13
|
-
|
|
17
|
+
incoming_commands: Receiver<Vec<WFCommand>>,
|
|
14
18
|
/// Outgoing activation jobs that need to be sent to the lang sdk
|
|
15
19
|
outgoing_wf_activation_jobs: Vec<OutgoingJob>,
|
|
16
20
|
}
|
|
17
21
|
|
|
18
|
-
impl<WF> From<Box<WF>> for DrivenWorkflow
|
|
19
|
-
where
|
|
20
|
-
WF: WorkflowFetcher + 'static,
|
|
21
|
-
{
|
|
22
|
-
fn from(wf: Box<WF>) -> Self {
|
|
23
|
-
Self {
|
|
24
|
-
started_attrs: None,
|
|
25
|
-
fetcher: wf,
|
|
26
|
-
outgoing_wf_activation_jobs: Default::default(),
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
22
|
impl DrivenWorkflow {
|
|
23
|
+
pub fn new() -> (Self, Sender<Vec<WFCommand>>) {
|
|
24
|
+
let (tx, rx) = mpsc::channel();
|
|
25
|
+
(
|
|
26
|
+
Self {
|
|
27
|
+
started_attrs: None,
|
|
28
|
+
incoming_commands: rx,
|
|
29
|
+
outgoing_wf_activation_jobs: vec![],
|
|
30
|
+
},
|
|
31
|
+
tx,
|
|
32
|
+
)
|
|
33
|
+
}
|
|
32
34
|
/// Start the workflow
|
|
33
35
|
pub fn start(
|
|
34
36
|
&mut self,
|
|
@@ -72,24 +74,15 @@ impl DrivenWorkflow {
|
|
|
72
74
|
.map(Into::into)
|
|
73
75
|
.collect()
|
|
74
76
|
}
|
|
75
|
-
}
|
|
76
77
|
|
|
77
|
-
impl WorkflowFetcher for DrivenWorkflow {
|
|
78
|
-
fn fetch_workflow_iteration_output(&mut self) -> Vec<WFCommand> {
|
|
79
|
-
self.fetcher.fetch_workflow_iteration_output()
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/// Implementors of this trait represent a way to fetch output from executing/iterating some
|
|
84
|
-
/// workflow code (or a mocked workflow).
|
|
85
|
-
pub trait WorkflowFetcher: Send {
|
|
86
78
|
/// Obtain any output from the workflow's recent execution(s). Because the lang sdk is
|
|
87
79
|
/// responsible for calling workflow code as a result of receiving tasks from
|
|
88
|
-
/// [crate::Core::poll_task], we cannot directly iterate it here.
|
|
89
|
-
///
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
80
|
+
/// [crate::Core::poll_task], we cannot directly iterate it here. Commands are simply pulled
|
|
81
|
+
/// from a buffer that the language side sinks into when it calls [crate::Core::complete_task]
|
|
82
|
+
pub fn fetch_workflow_iteration_output(&mut self) -> Vec<WFCommand> {
|
|
83
|
+
let in_cmds = self.incoming_commands.try_recv();
|
|
84
|
+
let in_cmds = in_cmds.unwrap_or_else(|_| vec![WFCommand::NoCommandsFromLang]);
|
|
85
|
+
debug!(in_cmds = %in_cmds.display(), "wf bridge iteration fetch");
|
|
86
|
+
in_cmds
|
|
87
|
+
}
|
|
95
88
|
}
|
|
@@ -55,8 +55,10 @@ impl Debug for HistoryUpdate {
|
|
|
55
55
|
if self.is_real() {
|
|
56
56
|
write!(
|
|
57
57
|
f,
|
|
58
|
-
"HistoryUpdate(previous_started_event_id: {},
|
|
58
|
+
"HistoryUpdate(previous_started_event_id: {}, started_id: {}, \
|
|
59
|
+
length: {}, first_event_id: {:?})",
|
|
59
60
|
self.previous_wft_started_id,
|
|
61
|
+
self.wft_started_id,
|
|
60
62
|
self.events.len(),
|
|
61
63
|
self.events.first().map(|e| e.event_id)
|
|
62
64
|
)
|
|
@@ -164,6 +166,7 @@ impl HistoryPaginator {
|
|
|
164
166
|
legacy_query: wft.legacy_query,
|
|
165
167
|
query_requests: wft.query_requests,
|
|
166
168
|
update,
|
|
169
|
+
messages: wft.messages,
|
|
167
170
|
};
|
|
168
171
|
Ok((paginator, prepared))
|
|
169
172
|
}
|
|
@@ -804,87 +804,17 @@ fn convert_payloads(
|
|
|
804
804
|
mod test {
|
|
805
805
|
use super::*;
|
|
806
806
|
use crate::{
|
|
807
|
-
internal_flags::InternalFlags,
|
|
808
|
-
|
|
807
|
+
internal_flags::InternalFlags,
|
|
808
|
+
replay::TestHistoryBuilder,
|
|
809
|
+
test_help::{build_fake_sdk, MockPollCfg, ResponseType},
|
|
809
810
|
};
|
|
810
|
-
use rstest::{fixture, rstest};
|
|
811
811
|
use std::{cell::RefCell, mem::discriminant, rc::Rc};
|
|
812
|
-
use temporal_sdk::{
|
|
813
|
-
ActivityOptions, CancellableFuture, WfContext, WorkflowFunction, WorkflowResult,
|
|
814
|
-
};
|
|
812
|
+
use temporal_sdk::{ActivityOptions, CancellableFuture, WfContext, WorkflowFunction};
|
|
815
813
|
use temporal_sdk_core_protos::{
|
|
816
814
|
coresdk::workflow_activation::{workflow_activation_job, WorkflowActivationJob},
|
|
817
|
-
|
|
815
|
+
DEFAULT_WORKFLOW_TYPE,
|
|
818
816
|
};
|
|
819
|
-
|
|
820
|
-
#[fixture]
|
|
821
|
-
fn activity_happy_hist() -> ManagedWFFunc {
|
|
822
|
-
let func = WorkflowFunction::new(activity_wf);
|
|
823
|
-
let t = canned_histories::single_activity("activity-id-1");
|
|
824
|
-
assert_eq!(2, t.get_full_history_info().unwrap().wf_task_count());
|
|
825
|
-
ManagedWFFunc::new(t, func, vec![])
|
|
826
|
-
}
|
|
827
|
-
|
|
828
|
-
#[fixture]
|
|
829
|
-
fn activity_failure_hist() -> ManagedWFFunc {
|
|
830
|
-
let func = WorkflowFunction::new(activity_wf);
|
|
831
|
-
let t = canned_histories::single_failed_activity("activity-id-1");
|
|
832
|
-
assert_eq!(2, t.get_full_history_info().unwrap().wf_task_count());
|
|
833
|
-
ManagedWFFunc::new(t, func, vec![])
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
async fn activity_wf(command_sink: WfContext) -> WorkflowResult<()> {
|
|
837
|
-
command_sink
|
|
838
|
-
.activity(ActivityOptions {
|
|
839
|
-
activity_id: Some("activity-id-1".to_string()),
|
|
840
|
-
activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
|
|
841
|
-
..Default::default()
|
|
842
|
-
})
|
|
843
|
-
.await;
|
|
844
|
-
Ok(().into())
|
|
845
|
-
}
|
|
846
|
-
|
|
847
|
-
#[rstest(
|
|
848
|
-
wfm,
|
|
849
|
-
case::success(activity_happy_hist()),
|
|
850
|
-
case::failure(activity_failure_hist())
|
|
851
|
-
)]
|
|
852
|
-
#[tokio::test]
|
|
853
|
-
async fn single_activity_inc(mut wfm: ManagedWFFunc) {
|
|
854
|
-
wfm.get_next_activation().await.unwrap();
|
|
855
|
-
let commands = wfm.get_server_commands().commands;
|
|
856
|
-
assert_eq!(commands.len(), 1);
|
|
857
|
-
assert_eq!(
|
|
858
|
-
commands[0].command_type,
|
|
859
|
-
CommandType::ScheduleActivityTask as i32
|
|
860
|
-
);
|
|
861
|
-
|
|
862
|
-
wfm.get_next_activation().await.unwrap();
|
|
863
|
-
let commands = wfm.get_server_commands().commands;
|
|
864
|
-
assert_eq!(commands.len(), 1);
|
|
865
|
-
assert_eq!(
|
|
866
|
-
commands[0].command_type,
|
|
867
|
-
CommandType::CompleteWorkflowExecution as i32
|
|
868
|
-
);
|
|
869
|
-
wfm.shutdown().await.unwrap();
|
|
870
|
-
}
|
|
871
|
-
|
|
872
|
-
#[rstest(
|
|
873
|
-
wfm,
|
|
874
|
-
case::success(activity_happy_hist()),
|
|
875
|
-
case::failure(activity_failure_hist())
|
|
876
|
-
)]
|
|
877
|
-
#[tokio::test]
|
|
878
|
-
async fn single_activity_full(mut wfm: ManagedWFFunc) {
|
|
879
|
-
wfm.process_all_activations().await.unwrap();
|
|
880
|
-
let commands = wfm.get_server_commands().commands;
|
|
881
|
-
assert_eq!(commands.len(), 1);
|
|
882
|
-
assert_eq!(
|
|
883
|
-
commands[0].command_type,
|
|
884
|
-
CommandType::CompleteWorkflowExecution as i32
|
|
885
|
-
);
|
|
886
|
-
wfm.shutdown().await.unwrap();
|
|
887
|
-
}
|
|
817
|
+
use temporal_sdk_core_test_utils::interceptors::ActivationAssertionsInterceptor;
|
|
888
818
|
|
|
889
819
|
#[tokio::test]
|
|
890
820
|
async fn immediate_activity_cancelation() {
|
|
@@ -900,24 +830,36 @@ mod test {
|
|
|
900
830
|
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
901
831
|
t.add_full_wf_task();
|
|
902
832
|
t.add_workflow_execution_completed();
|
|
903
|
-
let mut
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
)
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
833
|
+
let mut worker = build_fake_sdk(MockPollCfg::from_resps(t, [ResponseType::AllHistory]));
|
|
834
|
+
worker.register_wf(DEFAULT_WORKFLOW_TYPE, func);
|
|
835
|
+
|
|
836
|
+
let mut aai = ActivationAssertionsInterceptor::default();
|
|
837
|
+
aai.then(|a| {
|
|
838
|
+
assert_matches!(
|
|
839
|
+
a.jobs.as_slice(),
|
|
840
|
+
[WorkflowActivationJob {
|
|
841
|
+
variant: Some(workflow_activation_job::Variant::StartWorkflow(_)),
|
|
842
|
+
}]
|
|
843
|
+
)
|
|
844
|
+
});
|
|
845
|
+
aai.then(|a| {
|
|
846
|
+
assert_matches!(
|
|
847
|
+
a.jobs.as_slice(),
|
|
848
|
+
[WorkflowActivationJob {
|
|
849
|
+
variant: Some(workflow_activation_job::Variant::ResolveActivity(
|
|
850
|
+
ResolveActivity {
|
|
851
|
+
result: Some(ActivityResolution {
|
|
852
|
+
status: Some(activity_resolution::Status::Cancelled(_))
|
|
853
|
+
}),
|
|
854
|
+
..
|
|
855
|
+
}
|
|
856
|
+
)),
|
|
857
|
+
},]
|
|
858
|
+
)
|
|
859
|
+
});
|
|
860
|
+
|
|
861
|
+
worker.set_worker_interceptor(aai);
|
|
862
|
+
worker.run().await.unwrap();
|
|
921
863
|
}
|
|
922
864
|
|
|
923
865
|
#[test]
|