temporalio 0.0.2 → 0.1.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.
- checksums.yaml +4 -4
- data/README.md +25 -23
- data/bridge/Cargo.lock +168 -59
- data/bridge/Cargo.toml +4 -2
- data/bridge/sdk-core/README.md +19 -6
- data/bridge/sdk-core/client/src/lib.rs +215 -39
- data/bridge/sdk-core/client/src/metrics.rs +17 -8
- data/bridge/sdk-core/client/src/raw.rs +4 -4
- data/bridge/sdk-core/client/src/retry.rs +32 -20
- data/bridge/sdk-core/core/Cargo.toml +22 -9
- data/bridge/sdk-core/core/src/abstractions.rs +203 -14
- data/bridge/sdk-core/core/src/core_tests/activity_tasks.rs +76 -41
- data/bridge/sdk-core/core/src/core_tests/determinism.rs +165 -2
- data/bridge/sdk-core/core/src/core_tests/local_activities.rs +204 -83
- data/bridge/sdk-core/core/src/core_tests/queries.rs +3 -4
- data/bridge/sdk-core/core/src/core_tests/workers.rs +1 -3
- data/bridge/sdk-core/core/src/core_tests/workflow_tasks.rs +397 -54
- data/bridge/sdk-core/core/src/ephemeral_server/mod.rs +106 -12
- data/bridge/sdk-core/core/src/internal_flags.rs +136 -0
- data/bridge/sdk-core/core/src/lib.rs +16 -9
- data/bridge/sdk-core/core/src/telemetry/log_export.rs +1 -1
- data/bridge/sdk-core/core/src/telemetry/metrics.rs +69 -35
- data/bridge/sdk-core/core/src/telemetry/mod.rs +29 -13
- data/bridge/sdk-core/core/src/telemetry/prometheus_server.rs +17 -12
- data/bridge/sdk-core/core/src/test_help/mod.rs +62 -12
- data/bridge/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +112 -156
- data/bridge/sdk-core/core/src/worker/activities/activity_task_poller_stream.rs +89 -0
- data/bridge/sdk-core/core/src/worker/activities/local_activities.rs +352 -122
- data/bridge/sdk-core/core/src/worker/activities.rs +233 -157
- data/bridge/sdk-core/core/src/worker/client/mocks.rs +22 -2
- data/bridge/sdk-core/core/src/worker/client.rs +18 -2
- data/bridge/sdk-core/core/src/worker/mod.rs +165 -58
- data/bridge/sdk-core/core/src/worker/workflow/bridge.rs +1 -3
- data/bridge/sdk-core/core/src/worker/workflow/driven_workflow.rs +3 -5
- data/bridge/sdk-core/core/src/worker/workflow/history_update.rs +856 -277
- data/bridge/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +100 -43
- data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +7 -7
- data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +5 -4
- data/bridge/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +87 -27
- data/bridge/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +5 -4
- data/bridge/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +5 -4
- data/bridge/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +5 -4
- data/bridge/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +137 -62
- data/bridge/sdk-core/core/src/worker/workflow/machines/mod.rs +25 -17
- data/bridge/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +7 -6
- data/bridge/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +103 -152
- data/bridge/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +7 -7
- data/bridge/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +9 -9
- data/bridge/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +2 -2
- data/bridge/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +14 -7
- data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines/local_acts.rs +5 -16
- data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +201 -121
- data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +11 -14
- data/bridge/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +30 -15
- data/bridge/sdk-core/core/src/worker/workflow/managed_run.rs +1026 -376
- data/bridge/sdk-core/core/src/worker/workflow/mod.rs +460 -384
- data/bridge/sdk-core/core/src/worker/workflow/run_cache.rs +40 -57
- data/bridge/sdk-core/core/src/worker/workflow/wft_extraction.rs +125 -0
- data/bridge/sdk-core/core/src/worker/workflow/wft_poller.rs +1 -4
- data/bridge/sdk-core/core/src/worker/workflow/workflow_stream/saved_wf_inputs.rs +117 -0
- data/bridge/sdk-core/core/src/worker/workflow/workflow_stream/tonic_status_serde.rs +24 -0
- data/bridge/sdk-core/core/src/worker/workflow/workflow_stream.rs +448 -718
- data/bridge/sdk-core/core-api/Cargo.toml +2 -1
- data/bridge/sdk-core/core-api/src/errors.rs +1 -34
- data/bridge/sdk-core/core-api/src/lib.rs +6 -2
- data/bridge/sdk-core/core-api/src/telemetry.rs +0 -6
- data/bridge/sdk-core/core-api/src/worker.rs +14 -1
- data/bridge/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +18 -15
- data/bridge/sdk-core/fsm/rustfsm_trait/src/lib.rs +8 -3
- data/bridge/sdk-core/histories/evict_while_la_running_no_interference-16_history.bin +0 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +5 -17
- data/bridge/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +11 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +1 -6
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +6 -6
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +5 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +22 -6
- data/bridge/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +48 -19
- data/bridge/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +2 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +3 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/{enums/v1/interaction_type.proto → protocol/v1/message.proto} +29 -11
- data/bridge/sdk-core/protos/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +63 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/update/v1/message.proto +111 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +59 -28
- data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +2 -2
- data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/common/common.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/external_data/external_data.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +7 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +6 -0
- data/bridge/sdk-core/sdk/Cargo.toml +3 -2
- data/bridge/sdk-core/sdk/src/lib.rs +87 -20
- data/bridge/sdk-core/sdk/src/workflow_future.rs +9 -8
- data/bridge/sdk-core/sdk-core-protos/Cargo.toml +5 -2
- data/bridge/sdk-core/sdk-core-protos/build.rs +36 -1
- data/bridge/sdk-core/sdk-core-protos/src/history_builder.rs +100 -87
- data/bridge/sdk-core/sdk-core-protos/src/history_info.rs +5 -1
- data/bridge/sdk-core/sdk-core-protos/src/lib.rs +175 -57
- data/bridge/sdk-core/sdk-core-protos/src/task_token.rs +12 -2
- data/bridge/sdk-core/test-utils/Cargo.toml +3 -1
- data/bridge/sdk-core/test-utils/src/canned_histories.rs +106 -296
- data/bridge/sdk-core/test-utils/src/histfetch.rs +1 -1
- data/bridge/sdk-core/test-utils/src/lib.rs +82 -23
- data/bridge/sdk-core/test-utils/src/wf_input_saver.rs +50 -0
- data/bridge/sdk-core/test-utils/src/workflows.rs +29 -0
- data/bridge/sdk-core/tests/fuzzy_workflow.rs +130 -0
- data/bridge/sdk-core/tests/{load_tests.rs → heavy_tests.rs} +125 -51
- data/bridge/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +25 -3
- data/bridge/sdk-core/tests/integ_tests/heartbeat_tests.rs +5 -3
- data/bridge/sdk-core/tests/integ_tests/metrics_tests.rs +218 -16
- data/bridge/sdk-core/tests/integ_tests/polling_tests.rs +4 -47
- data/bridge/sdk-core/tests/integ_tests/queries_tests.rs +5 -128
- data/bridge/sdk-core/tests/integ_tests/visibility_tests.rs +83 -25
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/activities.rs +93 -69
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +1 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +6 -13
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +1 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +6 -2
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +3 -10
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +72 -191
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +1 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/patches.rs +7 -28
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/replay.rs +12 -7
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/resets.rs +1 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/signals.rs +18 -14
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +6 -20
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/timers.rs +10 -21
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +6 -4
- data/bridge/sdk-core/tests/integ_tests/workflow_tests.rs +10 -11
- data/bridge/sdk-core/tests/main.rs +3 -13
- data/bridge/sdk-core/tests/runner.rs +75 -36
- data/bridge/sdk-core/tests/wf_input_replay.rs +32 -0
- data/bridge/src/connection.rs +41 -25
- data/bridge/src/lib.rs +269 -14
- data/bridge/src/runtime.rs +1 -1
- data/bridge/src/test_server.rs +153 -0
- data/bridge/src/worker.rs +89 -16
- data/lib/gen/temporal/api/command/v1/message_pb.rb +4 -18
- data/lib/gen/temporal/api/common/v1/message_pb.rb +4 -0
- data/lib/gen/temporal/api/enums/v1/command_type_pb.rb +1 -3
- data/lib/gen/temporal/api/enums/v1/event_type_pb.rb +3 -3
- data/lib/gen/temporal/api/enums/v1/failed_cause_pb.rb +2 -0
- data/lib/gen/temporal/api/enums/v1/update_pb.rb +6 -4
- data/lib/gen/temporal/api/history/v1/message_pb.rb +27 -19
- data/lib/gen/temporal/api/namespace/v1/message_pb.rb +1 -0
- data/lib/gen/temporal/api/operatorservice/v1/request_response_pb.rb +3 -0
- data/lib/gen/temporal/api/protocol/v1/message_pb.rb +30 -0
- data/lib/gen/temporal/api/sdk/v1/task_complete_metadata_pb.rb +23 -0
- data/lib/gen/temporal/api/testservice/v1/request_response_pb.rb +49 -0
- data/lib/gen/temporal/api/testservice/v1/service_pb.rb +21 -0
- data/lib/gen/temporal/api/update/v1/message_pb.rb +72 -0
- data/lib/gen/temporal/api/workflowservice/v1/request_response_pb.rb +26 -16
- data/lib/gen/temporal/sdk/core/activity_result/activity_result_pb.rb +13 -9
- data/lib/gen/temporal/sdk/core/activity_task/activity_task_pb.rb +10 -6
- data/lib/gen/temporal/sdk/core/child_workflow/child_workflow_pb.rb +13 -9
- data/lib/gen/temporal/sdk/core/common/common_pb.rb +7 -3
- data/lib/gen/temporal/sdk/core/core_interface_pb.rb +9 -3
- data/lib/gen/temporal/sdk/core/external_data/external_data_pb.rb +7 -3
- data/lib/gen/temporal/sdk/core/workflow_activation/workflow_activation_pb.rb +27 -21
- data/lib/gen/temporal/sdk/core/workflow_commands/workflow_commands_pb.rb +28 -24
- data/lib/gen/temporal/sdk/core/workflow_completion/workflow_completion_pb.rb +12 -5
- data/lib/temporalio/activity/context.rb +13 -8
- data/lib/temporalio/activity/info.rb +1 -1
- data/lib/temporalio/bridge/connect_options.rb +15 -0
- data/lib/temporalio/bridge/retry_config.rb +24 -0
- data/lib/temporalio/bridge/tls_options.rb +19 -0
- data/lib/temporalio/client/implementation.rb +8 -8
- data/lib/temporalio/connection/retry_config.rb +44 -0
- data/lib/temporalio/connection/service.rb +20 -0
- data/lib/temporalio/connection/test_service.rb +92 -0
- data/lib/temporalio/connection/tls_options.rb +51 -0
- data/lib/temporalio/connection/workflow_service.rb +731 -0
- data/lib/temporalio/connection.rb +55 -720
- data/lib/temporalio/interceptor/activity_inbound.rb +22 -0
- data/lib/temporalio/interceptor/activity_outbound.rb +24 -0
- data/lib/temporalio/interceptor/chain.rb +5 -5
- data/lib/temporalio/interceptor/client.rb +8 -4
- data/lib/temporalio/interceptor.rb +22 -0
- data/lib/temporalio/retry_policy.rb +13 -3
- data/lib/temporalio/testing/time_skipping_handle.rb +32 -0
- data/lib/temporalio/testing/time_skipping_interceptor.rb +23 -0
- data/lib/temporalio/testing/workflow_environment.rb +112 -0
- data/lib/temporalio/testing.rb +175 -0
- data/lib/temporalio/version.rb +1 -1
- data/lib/temporalio/worker/activity_runner.rb +26 -4
- data/lib/temporalio/worker/activity_worker.rb +44 -18
- data/lib/temporalio/worker/sync_worker.rb +47 -11
- data/lib/temporalio/worker.rb +27 -21
- data/lib/temporalio/workflow/async.rb +46 -0
- data/lib/temporalio/workflow/future.rb +138 -0
- data/lib/temporalio/workflow/info.rb +76 -0
- data/temporalio.gemspec +4 -3
- metadata +67 -17
- data/bridge/sdk-core/Cargo.lock +0 -2606
- data/bridge/sdk-core/protos/api_upstream/temporal/api/interaction/v1/message.proto +0 -87
- data/lib/bridge.so +0 -0
- data/lib/gen/temporal/api/enums/v1/interaction_type_pb.rb +0 -25
- data/lib/gen/temporal/api/interaction/v1/message_pb.rb +0 -49
- data/lib/gen/temporal/sdk/core/bridge/bridge_pb.rb +0 -222
|
@@ -3,6 +3,8 @@ pub(crate) mod client;
|
|
|
3
3
|
mod workflow;
|
|
4
4
|
|
|
5
5
|
pub use temporal_sdk_core_api::worker::{WorkerConfig, WorkerConfigBuilder};
|
|
6
|
+
#[cfg(feature = "save_wf_inputs")]
|
|
7
|
+
pub use workflow::replay_wf_state_inputs;
|
|
6
8
|
|
|
7
9
|
pub(crate) use activities::{
|
|
8
10
|
ExecutingLAId, LocalActRequest, LocalActivityExecutionResult, LocalActivityResolution,
|
|
@@ -19,20 +21,30 @@ use crate::{
|
|
|
19
21
|
WorkflowTaskPoller,
|
|
20
22
|
},
|
|
21
23
|
protosext::{validate_activity_completion, ValidPollWFTQResponse},
|
|
22
|
-
telemetry::
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
telemetry::{
|
|
25
|
+
metrics::{
|
|
26
|
+
activity_poller, local_activity_worker_type, workflow_poller, workflow_sticky_poller,
|
|
27
|
+
MetricsContext,
|
|
28
|
+
},
|
|
29
|
+
TelemetryInstance,
|
|
25
30
|
},
|
|
26
31
|
worker::{
|
|
27
32
|
activities::{DispatchOrTimeoutLA, LACompleteAction, LocalActivityManager},
|
|
28
33
|
client::WorkerClient,
|
|
29
|
-
workflow::{LocalResolution, WorkflowBasics, Workflows},
|
|
34
|
+
workflow::{LAReqSink, LocalResolution, WorkflowBasics, Workflows},
|
|
30
35
|
},
|
|
31
36
|
ActivityHeartbeat, CompleteActivityError, PollActivityError, PollWfError, WorkerTrait,
|
|
32
37
|
};
|
|
33
38
|
use activities::{LocalInFlightActInfo, WorkerActivityTasks};
|
|
34
39
|
use futures::Stream;
|
|
35
|
-
use std::{
|
|
40
|
+
use std::{
|
|
41
|
+
convert::TryInto,
|
|
42
|
+
future,
|
|
43
|
+
sync::{
|
|
44
|
+
atomic::{AtomicBool, Ordering},
|
|
45
|
+
Arc,
|
|
46
|
+
},
|
|
47
|
+
};
|
|
36
48
|
use temporal_sdk_core_protos::{
|
|
37
49
|
coresdk::{
|
|
38
50
|
activity_result::activity_execution_result,
|
|
@@ -44,10 +56,11 @@ use temporal_sdk_core_protos::{
|
|
|
44
56
|
temporal::api::{
|
|
45
57
|
enums::v1::TaskQueueKind,
|
|
46
58
|
taskqueue::v1::{StickyExecutionAttributes, TaskQueue},
|
|
47
|
-
workflowservice::v1::PollActivityTaskQueueResponse,
|
|
59
|
+
workflowservice::v1::{get_system_info_response, PollActivityTaskQueueResponse},
|
|
48
60
|
},
|
|
49
61
|
TaskToken,
|
|
50
62
|
};
|
|
63
|
+
use tokio::sync::mpsc::unbounded_channel;
|
|
51
64
|
use tokio_util::sync::CancellationToken;
|
|
52
65
|
|
|
53
66
|
/// A worker polls on a certain task queue
|
|
@@ -66,6 +79,10 @@ pub struct Worker {
|
|
|
66
79
|
/// Will be called at the end of each activation completion
|
|
67
80
|
#[allow(clippy::type_complexity)] // Sorry clippy, there's no simple way to re-use here.
|
|
68
81
|
post_activate_hook: Option<Box<dyn Fn(&Self, &str, usize) + Send + Sync>>,
|
|
82
|
+
/// Set when non-local activities are complete and should stop being polled
|
|
83
|
+
non_local_activities_complete: Arc<AtomicBool>,
|
|
84
|
+
/// Set when local activities are complete and should stop being polled
|
|
85
|
+
local_activities_complete: Arc<AtomicBool>,
|
|
69
86
|
}
|
|
70
87
|
|
|
71
88
|
#[async_trait::async_trait]
|
|
@@ -134,6 +151,9 @@ impl WorkerTrait for Worker {
|
|
|
134
151
|
if let Some(atm) = self.at_task_mgr.as_ref() {
|
|
135
152
|
atm.notify_shutdown();
|
|
136
153
|
}
|
|
154
|
+
// Let the manager know that shutdown has been initiated to try to unblock the local activity poll in case this
|
|
155
|
+
// worker is an activity-only worker.
|
|
156
|
+
self.local_act_mgr.shutdown_initiated();
|
|
137
157
|
info!(
|
|
138
158
|
task_queue=%self.config.task_queue,
|
|
139
159
|
namespace=%self.config.namespace,
|
|
@@ -156,11 +176,17 @@ impl Worker {
|
|
|
156
176
|
config: WorkerConfig,
|
|
157
177
|
sticky_queue_name: Option<String>,
|
|
158
178
|
client: Arc<dyn WorkerClient>,
|
|
159
|
-
|
|
179
|
+
telem_instance: Option<&TelemetryInstance>,
|
|
160
180
|
) -> Self {
|
|
161
181
|
info!(task_queue=%config.task_queue,
|
|
162
182
|
namespace=%config.namespace,
|
|
163
183
|
"Initializing worker");
|
|
184
|
+
let metrics = if let Some(ti) = telem_instance {
|
|
185
|
+
MetricsContext::top_level(config.namespace.clone(), ti)
|
|
186
|
+
.with_task_q(config.task_queue.clone())
|
|
187
|
+
} else {
|
|
188
|
+
MetricsContext::no_op()
|
|
189
|
+
};
|
|
164
190
|
metrics.worker_registered();
|
|
165
191
|
|
|
166
192
|
let shutdown_token = CancellationToken::new();
|
|
@@ -223,31 +249,34 @@ impl Worker {
|
|
|
223
249
|
wft_stream,
|
|
224
250
|
act_poll_buffer,
|
|
225
251
|
metrics,
|
|
252
|
+
telem_instance,
|
|
226
253
|
shutdown_token,
|
|
227
254
|
)
|
|
228
255
|
}
|
|
229
256
|
|
|
230
257
|
#[cfg(test)]
|
|
231
258
|
pub(crate) fn new_test(config: WorkerConfig, client: impl WorkerClient + 'static) -> Self {
|
|
232
|
-
Self::new(config, None, Arc::new(client),
|
|
259
|
+
Self::new(config, None, Arc::new(client), None)
|
|
233
260
|
}
|
|
234
261
|
|
|
262
|
+
#[allow(clippy::too_many_arguments)] // Not much worth combining here
|
|
235
263
|
pub(crate) fn new_with_pollers(
|
|
236
|
-
config: WorkerConfig,
|
|
264
|
+
mut config: WorkerConfig,
|
|
237
265
|
sticky_queue_name: Option<String>,
|
|
238
266
|
client: Arc<dyn WorkerClient>,
|
|
239
267
|
wft_stream: impl Stream<Item = Result<ValidPollWFTQResponse, tonic::Status>> + Send + 'static,
|
|
240
268
|
act_poller: Option<BoxedActPoller>,
|
|
241
269
|
metrics: MetricsContext,
|
|
270
|
+
telem_instance: Option<&TelemetryInstance>,
|
|
242
271
|
shutdown_token: CancellationToken,
|
|
243
272
|
) -> Self {
|
|
273
|
+
let (hb_tx, hb_rx) = unbounded_channel();
|
|
244
274
|
let local_act_mgr = Arc::new(LocalActivityManager::new(
|
|
245
275
|
config.max_outstanding_local_activities,
|
|
246
276
|
config.namespace.clone(),
|
|
277
|
+
hb_tx,
|
|
247
278
|
metrics.with_new_attrs([local_activity_worker_type()]),
|
|
248
279
|
));
|
|
249
|
-
let lam_clone = local_act_mgr.clone();
|
|
250
|
-
let local_act_req_sink = move |requests| lam_clone.enqueue(requests);
|
|
251
280
|
let at_task_mgr = act_poller.map(|ap| {
|
|
252
281
|
WorkerActivityTasks::new(
|
|
253
282
|
config.max_outstanding_activities,
|
|
@@ -259,18 +288,20 @@ impl Worker {
|
|
|
259
288
|
config.default_heartbeat_throttle_interval,
|
|
260
289
|
)
|
|
261
290
|
});
|
|
291
|
+
let poll_on_non_local_activities = at_task_mgr.is_some();
|
|
292
|
+
if !poll_on_non_local_activities {
|
|
293
|
+
info!("Activity polling is disabled for this worker");
|
|
294
|
+
};
|
|
295
|
+
let la_sink = LAReqSink::new(local_act_mgr.clone(), config.wf_state_inputs.clone());
|
|
262
296
|
Self {
|
|
263
297
|
wf_client: client.clone(),
|
|
264
298
|
workflows: Workflows::new(
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
max_outstanding_wfts: config.max_outstanding_workflow_tasks,
|
|
268
|
-
shutdown_token: shutdown_token.child_token(),
|
|
299
|
+
build_wf_basics(
|
|
300
|
+
&mut config,
|
|
269
301
|
metrics,
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
},
|
|
302
|
+
shutdown_token.child_token(),
|
|
303
|
+
client.capabilities().cloned().unwrap_or_default(),
|
|
304
|
+
),
|
|
274
305
|
sticky_queue_name.map(|sq| StickyExecutionAttributes {
|
|
275
306
|
worker_task_queue: Some(TaskQueue {
|
|
276
307
|
name: sq,
|
|
@@ -285,16 +316,22 @@ impl Worker {
|
|
|
285
316
|
}),
|
|
286
317
|
client,
|
|
287
318
|
wft_stream,
|
|
288
|
-
|
|
319
|
+
la_sink,
|
|
320
|
+
local_act_mgr.clone(),
|
|
321
|
+
hb_rx,
|
|
289
322
|
at_task_mgr
|
|
290
323
|
.as_ref()
|
|
291
324
|
.map(|mgr| mgr.get_handle_for_workflows()),
|
|
325
|
+
telem_instance,
|
|
292
326
|
),
|
|
293
327
|
at_task_mgr,
|
|
294
328
|
local_act_mgr,
|
|
295
329
|
config,
|
|
296
330
|
shutdown_token,
|
|
297
331
|
post_activate_hook: None,
|
|
332
|
+
// Complete if there configured not to poll on non-local activities.
|
|
333
|
+
non_local_activities_complete: Arc::new(AtomicBool::new(!poll_on_non_local_activities)),
|
|
334
|
+
local_activities_complete: Default::default(),
|
|
298
335
|
}
|
|
299
336
|
}
|
|
300
337
|
|
|
@@ -304,15 +341,16 @@ impl Worker {
|
|
|
304
341
|
self.initiate_shutdown();
|
|
305
342
|
// Next we need to wait for all local activities to finish so no more workflow task
|
|
306
343
|
// heartbeats will be generated
|
|
307
|
-
self.local_act_mgr.shutdown_and_wait_all_finished().await;
|
|
308
344
|
// Wait for workflows to finish
|
|
309
345
|
self.workflows
|
|
310
346
|
.shutdown()
|
|
311
347
|
.await
|
|
312
348
|
.expect("Workflow processing terminates cleanly");
|
|
349
|
+
let lam = self.local_act_mgr.clone();
|
|
350
|
+
lam.wait_all_outstanding_tasks_finished().await;
|
|
313
351
|
// Wait for activities to finish
|
|
314
352
|
if let Some(acts) = self.at_task_mgr.as_ref() {
|
|
315
|
-
acts.
|
|
353
|
+
acts.shutdown().await;
|
|
316
354
|
}
|
|
317
355
|
}
|
|
318
356
|
|
|
@@ -346,13 +384,9 @@ impl Worker {
|
|
|
346
384
|
.unwrap_or_default()
|
|
347
385
|
}
|
|
348
386
|
|
|
349
|
-
#[
|
|
387
|
+
#[allow(unused)]
|
|
350
388
|
pub(crate) async fn available_wft_permits(&self) -> usize {
|
|
351
|
-
self.workflows
|
|
352
|
-
.get_state_info()
|
|
353
|
-
.await
|
|
354
|
-
.expect("You can only check for available permits before shutdown")
|
|
355
|
-
.available_wft_permits
|
|
389
|
+
self.workflows.available_wft_permits()
|
|
356
390
|
}
|
|
357
391
|
|
|
358
392
|
/// Get new activity tasks (may be local or nonlocal). Local activities are returned first
|
|
@@ -361,35 +395,63 @@ impl Worker {
|
|
|
361
395
|
/// Returns `Ok(None)` in the event of a poll timeout or if the polling loop should otherwise
|
|
362
396
|
/// be restarted
|
|
363
397
|
async fn activity_poll(&self) -> Result<Option<ActivityTask>, PollActivityError> {
|
|
398
|
+
let local_activities_complete = self.local_activities_complete.load(Ordering::Relaxed);
|
|
399
|
+
let non_local_activities_complete =
|
|
400
|
+
self.non_local_activities_complete.load(Ordering::Relaxed);
|
|
401
|
+
if local_activities_complete && non_local_activities_complete {
|
|
402
|
+
return Err(PollActivityError::ShutDown);
|
|
403
|
+
}
|
|
364
404
|
let act_mgr_poll = async {
|
|
405
|
+
if non_local_activities_complete {
|
|
406
|
+
future::pending::<()>().await;
|
|
407
|
+
unreachable!()
|
|
408
|
+
}
|
|
365
409
|
if let Some(ref act_mgr) = self.at_task_mgr {
|
|
366
|
-
act_mgr.poll().await
|
|
410
|
+
let res = act_mgr.poll().await;
|
|
411
|
+
if let Err(err) = res.as_ref() {
|
|
412
|
+
if matches!(err, PollActivityError::ShutDown) {
|
|
413
|
+
self.non_local_activities_complete
|
|
414
|
+
.store(true, Ordering::Relaxed);
|
|
415
|
+
return Ok(None);
|
|
416
|
+
}
|
|
417
|
+
};
|
|
418
|
+
res.map(Some)
|
|
367
419
|
} else {
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
420
|
+
// We expect the local activity branch below to produce shutdown when appropriate if
|
|
421
|
+
// there are no activity pollers.
|
|
422
|
+
future::pending::<()>().await;
|
|
423
|
+
unreachable!()
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
let local_activities_poll = async {
|
|
427
|
+
if local_activities_complete {
|
|
428
|
+
future::pending::<()>().await;
|
|
429
|
+
unreachable!()
|
|
430
|
+
}
|
|
431
|
+
match self.local_act_mgr.next_pending().await {
|
|
432
|
+
Some(DispatchOrTimeoutLA::Dispatch(r)) => Ok(Some(r)),
|
|
433
|
+
Some(DispatchOrTimeoutLA::Timeout {
|
|
434
|
+
run_id,
|
|
435
|
+
resolution,
|
|
436
|
+
task,
|
|
437
|
+
}) => {
|
|
438
|
+
self.notify_local_result(&run_id, LocalResolution::LocalActivity(resolution));
|
|
439
|
+
Ok(task)
|
|
440
|
+
}
|
|
441
|
+
None => {
|
|
442
|
+
if self.shutdown_token.is_cancelled() {
|
|
443
|
+
self.local_activities_complete
|
|
444
|
+
.store(true, Ordering::Relaxed);
|
|
445
|
+
}
|
|
446
|
+
Ok(None)
|
|
447
|
+
}
|
|
371
448
|
}
|
|
372
449
|
};
|
|
373
450
|
|
|
374
451
|
tokio::select! {
|
|
375
452
|
biased;
|
|
376
453
|
|
|
377
|
-
r =
|
|
378
|
-
match r {
|
|
379
|
-
Some(DispatchOrTimeoutLA::Dispatch(r)) => Ok(Some(r)),
|
|
380
|
-
Some(DispatchOrTimeoutLA::Timeout { run_id, resolution, task }) => {
|
|
381
|
-
self.notify_local_result(
|
|
382
|
-
&run_id, LocalResolution::LocalActivity(resolution));
|
|
383
|
-
Ok(task)
|
|
384
|
-
},
|
|
385
|
-
None => {
|
|
386
|
-
if self.shutdown_token.is_cancelled() {
|
|
387
|
-
return Err(PollActivityError::ShutDown);
|
|
388
|
-
}
|
|
389
|
-
Ok(None)
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
},
|
|
454
|
+
r = local_activities_poll => r,
|
|
393
455
|
r = act_mgr_poll => r,
|
|
394
456
|
}
|
|
395
457
|
}
|
|
@@ -448,7 +510,16 @@ impl Worker {
|
|
|
448
510
|
|
|
449
511
|
#[instrument(skip(self), fields(run_id, workflow_id, task_queue=%self.config.task_queue))]
|
|
450
512
|
pub(crate) async fn next_workflow_activation(&self) -> Result<WorkflowActivation, PollWfError> {
|
|
451
|
-
self.workflows.next_workflow_activation().await
|
|
513
|
+
let r = self.workflows.next_workflow_activation().await;
|
|
514
|
+
// In the event workflows are shutdown, begin shutdown of everything else, since that's
|
|
515
|
+
// about to happen anyway. Tell the local activity manager that, so that it can know to
|
|
516
|
+
// cancel any remaining outstanding LAs and shutdown.
|
|
517
|
+
if matches!(r, Err(PollWfError::ShutDown)) {
|
|
518
|
+
// This is covering the situation where WFT pollers dying is the reason for shutdown
|
|
519
|
+
self.initiate_shutdown();
|
|
520
|
+
self.local_act_mgr.workflows_have_shutdown();
|
|
521
|
+
}
|
|
522
|
+
r
|
|
452
523
|
}
|
|
453
524
|
|
|
454
525
|
#[instrument(skip(self, completion),
|
|
@@ -458,11 +529,14 @@ impl Worker {
|
|
|
458
529
|
&self,
|
|
459
530
|
completion: WorkflowActivationCompletion,
|
|
460
531
|
) -> Result<(), CompleteWfError> {
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
532
|
+
self.workflows
|
|
533
|
+
.activation_completed(
|
|
534
|
+
completion,
|
|
535
|
+
self.post_activate_hook.as_ref().map(|h| {
|
|
536
|
+
|run_id: &str, most_recent_event: usize| h(self, run_id, most_recent_event)
|
|
537
|
+
}),
|
|
538
|
+
)
|
|
539
|
+
.await?;
|
|
466
540
|
Ok(())
|
|
467
541
|
}
|
|
468
542
|
|
|
@@ -508,14 +582,39 @@ impl Worker {
|
|
|
508
582
|
}
|
|
509
583
|
}
|
|
510
584
|
|
|
585
|
+
fn build_wf_basics(
|
|
586
|
+
config: &mut WorkerConfig,
|
|
587
|
+
metrics: MetricsContext,
|
|
588
|
+
shutdown_token: CancellationToken,
|
|
589
|
+
server_capabilities: get_system_info_response::Capabilities,
|
|
590
|
+
) -> WorkflowBasics {
|
|
591
|
+
WorkflowBasics {
|
|
592
|
+
max_cached_workflows: config.max_cached_workflows,
|
|
593
|
+
max_outstanding_wfts: config.max_outstanding_workflow_tasks,
|
|
594
|
+
shutdown_token,
|
|
595
|
+
metrics,
|
|
596
|
+
namespace: config.namespace.clone(),
|
|
597
|
+
task_queue: config.task_queue.clone(),
|
|
598
|
+
ignore_evicts_on_shutdown: config.ignore_evicts_on_shutdown,
|
|
599
|
+
fetching_concurrency: config.fetching_concurrency,
|
|
600
|
+
server_capabilities,
|
|
601
|
+
#[cfg(feature = "save_wf_inputs")]
|
|
602
|
+
wf_state_inputs: config.wf_state_inputs.take(),
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
|
|
511
606
|
#[cfg(test)]
|
|
512
607
|
mod tests {
|
|
513
608
|
use super::*;
|
|
514
|
-
use crate::{
|
|
609
|
+
use crate::{
|
|
610
|
+
advance_fut, test_help::test_worker_cfg, worker::client::mocks::mock_workflow_client,
|
|
611
|
+
};
|
|
612
|
+
use futures::FutureExt;
|
|
613
|
+
|
|
515
614
|
use temporal_sdk_core_protos::temporal::api::workflowservice::v1::PollActivityTaskQueueResponse;
|
|
516
615
|
|
|
517
616
|
#[tokio::test]
|
|
518
|
-
async fn
|
|
617
|
+
async fn activity_timeouts_maintain_permit() {
|
|
519
618
|
let mut mock_client = mock_workflow_client();
|
|
520
619
|
mock_client
|
|
521
620
|
.expect_poll_activity_task()
|
|
@@ -526,8 +625,16 @@ mod tests {
|
|
|
526
625
|
.build()
|
|
527
626
|
.unwrap();
|
|
528
627
|
let worker = Worker::new_test(cfg, mock_client);
|
|
529
|
-
|
|
530
|
-
|
|
628
|
+
let fut = worker.poll_activity_task();
|
|
629
|
+
advance_fut!(fut);
|
|
630
|
+
assert_eq!(
|
|
631
|
+
worker
|
|
632
|
+
.at_task_mgr
|
|
633
|
+
.as_ref()
|
|
634
|
+
.unwrap()
|
|
635
|
+
.remaining_activity_capacity(),
|
|
636
|
+
4
|
|
637
|
+
);
|
|
531
638
|
}
|
|
532
639
|
|
|
533
640
|
#[tokio::test]
|
|
@@ -25,11 +25,9 @@ impl WorkflowBridge {
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
#[async_trait::async_trait]
|
|
29
28
|
impl WorkflowFetcher for WorkflowBridge {
|
|
30
|
-
|
|
29
|
+
fn fetch_workflow_iteration_output(&mut self) -> Vec<WFCommand> {
|
|
31
30
|
let in_cmds = self.incoming_commands.try_recv();
|
|
32
|
-
|
|
33
31
|
let in_cmds = in_cmds.unwrap_or_else(|_| vec![WFCommand::NoCommandsFromLang]);
|
|
34
32
|
debug!(in_cmds = %in_cmds.display(), "wf bridge iteration fetch");
|
|
35
33
|
in_cmds
|
|
@@ -78,16 +78,14 @@ impl DrivenWorkflow {
|
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
#[async_trait::async_trait]
|
|
82
81
|
impl WorkflowFetcher for DrivenWorkflow {
|
|
83
|
-
|
|
84
|
-
self.fetcher.fetch_workflow_iteration_output()
|
|
82
|
+
fn fetch_workflow_iteration_output(&mut self) -> Vec<WFCommand> {
|
|
83
|
+
self.fetcher.fetch_workflow_iteration_output()
|
|
85
84
|
}
|
|
86
85
|
}
|
|
87
86
|
|
|
88
87
|
/// Implementors of this trait represent a way to fetch output from executing/iterating some
|
|
89
88
|
/// workflow code (or a mocked workflow).
|
|
90
|
-
#[async_trait::async_trait]
|
|
91
89
|
pub trait WorkflowFetcher: Send {
|
|
92
90
|
/// Obtain any output from the workflow's recent execution(s). Because the lang sdk is
|
|
93
91
|
/// responsible for calling workflow code as a result of receiving tasks from
|
|
@@ -97,5 +95,5 @@ pub trait WorkflowFetcher: Send {
|
|
|
97
95
|
///
|
|
98
96
|
/// In the case of the real [WorkflowBridge] implementation, commands are simply pulled from
|
|
99
97
|
/// a buffer that the language side sinks into when it calls [crate::Core::complete_task]
|
|
100
|
-
|
|
98
|
+
fn fetch_workflow_iteration_output(&mut self) -> Vec<WFCommand>;
|
|
101
99
|
}
|