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
|
@@ -190,9 +190,7 @@ async fn complete_with_task_not_found_during_shutdown() {
|
|
|
190
190
|
complete_order.borrow_mut().push(1);
|
|
191
191
|
};
|
|
192
192
|
tokio::join!(shutdown_fut, poll_fut, complete_fut);
|
|
193
|
-
|
|
194
|
-
// workflow task is marked complete as soon as we get not found back from the server.
|
|
195
|
-
assert_eq!(&complete_order.into_inner(), &[1, 3, 2])
|
|
193
|
+
assert_eq!(&complete_order.into_inner(), &[1, 2, 3])
|
|
196
194
|
}
|
|
197
195
|
|
|
198
196
|
#[tokio::test]
|
|
@@ -16,7 +16,7 @@ use rstest::{fixture, rstest};
|
|
|
16
16
|
use std::{
|
|
17
17
|
collections::{HashMap, VecDeque},
|
|
18
18
|
sync::{
|
|
19
|
-
atomic::{AtomicU64, Ordering},
|
|
19
|
+
atomic::{AtomicBool, AtomicU64, Ordering},
|
|
20
20
|
Arc,
|
|
21
21
|
},
|
|
22
22
|
time::Duration,
|
|
@@ -37,20 +37,25 @@ use temporal_sdk_core_protos::{
|
|
|
37
37
|
},
|
|
38
38
|
workflow_completion::WorkflowActivationCompletion,
|
|
39
39
|
},
|
|
40
|
-
default_wes_attribs,
|
|
40
|
+
default_act_sched, default_wes_attribs,
|
|
41
41
|
temporal::api::{
|
|
42
42
|
command::v1::command::Attributes,
|
|
43
43
|
common::v1::{Payload, RetryPolicy},
|
|
44
44
|
enums::v1::{EventType, WorkflowTaskFailedCause},
|
|
45
45
|
failure::v1::Failure,
|
|
46
|
-
history::v1::{
|
|
46
|
+
history::v1::{
|
|
47
|
+
history_event, TimerFiredEventAttributes,
|
|
48
|
+
WorkflowPropertiesModifiedExternallyEventAttributes,
|
|
49
|
+
},
|
|
47
50
|
workflowservice::v1::{
|
|
48
51
|
GetWorkflowExecutionHistoryResponse, RespondWorkflowTaskCompletedResponse,
|
|
49
52
|
},
|
|
50
53
|
},
|
|
51
|
-
DEFAULT_WORKFLOW_TYPE,
|
|
54
|
+
DEFAULT_ACTIVITY_TYPE, DEFAULT_WORKFLOW_TYPE,
|
|
55
|
+
};
|
|
56
|
+
use temporal_sdk_core_test_utils::{
|
|
57
|
+
fanout_tasks, schedule_activity_cmd, start_timer_cmd, WorkerTestHelpers,
|
|
52
58
|
};
|
|
53
|
-
use temporal_sdk_core_test_utils::{fanout_tasks, start_timer_cmd};
|
|
54
59
|
use tokio::{
|
|
55
60
|
join,
|
|
56
61
|
sync::{Barrier, Semaphore},
|
|
@@ -120,7 +125,7 @@ async fn single_activity_completion(worker: Worker) {
|
|
|
120
125
|
&job_assert!(workflow_activation_job::Variant::StartWorkflow(_)),
|
|
121
126
|
vec![ScheduleActivity {
|
|
122
127
|
activity_id: "fake_activity".to_string(),
|
|
123
|
-
..
|
|
128
|
+
..default_act_sched()
|
|
124
129
|
}
|
|
125
130
|
.into()],
|
|
126
131
|
),
|
|
@@ -245,7 +250,7 @@ async fn scheduled_activity_cancellation_try_cancel(hist_batches: &'static [usiz
|
|
|
245
250
|
seq: activity_seq,
|
|
246
251
|
activity_id: activity_id.to_string(),
|
|
247
252
|
cancellation_type: ActivityCancellationType::TryCancel as i32,
|
|
248
|
-
..
|
|
253
|
+
..default_act_sched()
|
|
249
254
|
}
|
|
250
255
|
.into()],
|
|
251
256
|
),
|
|
@@ -281,7 +286,7 @@ async fn scheduled_activity_timeout(hist_batches: &'static [usize]) {
|
|
|
281
286
|
vec![ScheduleActivity {
|
|
282
287
|
seq: activity_seq,
|
|
283
288
|
activity_id: activity_id.to_string(),
|
|
284
|
-
..
|
|
289
|
+
..default_act_sched()
|
|
285
290
|
}
|
|
286
291
|
.into()],
|
|
287
292
|
),
|
|
@@ -334,7 +339,7 @@ async fn started_activity_timeout(hist_batches: &'static [usize]) {
|
|
|
334
339
|
vec![ScheduleActivity {
|
|
335
340
|
seq: activity_seq,
|
|
336
341
|
activity_id: activity_seq.to_string(),
|
|
337
|
-
..
|
|
342
|
+
..default_act_sched()
|
|
338
343
|
}
|
|
339
344
|
.into()],
|
|
340
345
|
),
|
|
@@ -389,7 +394,7 @@ async fn cancelled_activity_timeout(hist_batches: &'static [usize]) {
|
|
|
389
394
|
vec![ScheduleActivity {
|
|
390
395
|
seq: activity_seq,
|
|
391
396
|
activity_id: activity_id.to_string(),
|
|
392
|
-
..
|
|
397
|
+
..default_act_sched()
|
|
393
398
|
}
|
|
394
399
|
.into()],
|
|
395
400
|
),
|
|
@@ -457,10 +462,10 @@ async fn abandoned_activities_ignore_start_and_complete(hist_batches: &'static [
|
|
|
457
462
|
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
458
463
|
t.add_full_wf_task();
|
|
459
464
|
let act_scheduled_event_id = t.add_activity_task_scheduled(activity_id);
|
|
460
|
-
let timer_started_event_id = t.
|
|
465
|
+
let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
|
|
461
466
|
t.add_timer_fired(timer_started_event_id, "1".to_string());
|
|
462
467
|
t.add_full_wf_task();
|
|
463
|
-
let timer_started_event_id = t.
|
|
468
|
+
let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
|
|
464
469
|
let act_started_event_id = t.add_activity_task_started(act_scheduled_event_id);
|
|
465
470
|
t.add_activity_task_completed(
|
|
466
471
|
act_scheduled_event_id,
|
|
@@ -476,7 +481,7 @@ async fn abandoned_activities_ignore_start_and_complete(hist_batches: &'static [
|
|
|
476
481
|
|
|
477
482
|
worker.register_wf(wf_type.to_owned(), |ctx: WfContext| async move {
|
|
478
483
|
let act_fut = ctx.activity(ActivityOptions {
|
|
479
|
-
activity_type:
|
|
484
|
+
activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
|
|
480
485
|
start_to_close_timeout: Some(Duration::from_secs(5)),
|
|
481
486
|
cancellation_type: ActivityCancellationType::Abandon,
|
|
482
487
|
..Default::default()
|
|
@@ -542,7 +547,7 @@ async fn verify_activity_cancellation(
|
|
|
542
547
|
seq: activity_seq,
|
|
543
548
|
activity_id: activity_seq.to_string(),
|
|
544
549
|
cancellation_type: cancel_type as i32,
|
|
545
|
-
..
|
|
550
|
+
..default_act_sched()
|
|
546
551
|
}
|
|
547
552
|
.into()],
|
|
548
553
|
),
|
|
@@ -610,7 +615,7 @@ async fn verify_activity_cancellation_wait_for_cancellation(activity_id: u32, wo
|
|
|
610
615
|
seq: activity_id,
|
|
611
616
|
activity_id: activity_id.to_string(),
|
|
612
617
|
cancellation_type: ActivityCancellationType::WaitCancellationCompleted as i32,
|
|
613
|
-
..
|
|
618
|
+
..default_act_sched()
|
|
614
619
|
}
|
|
615
620
|
.into()],
|
|
616
621
|
),
|
|
@@ -892,7 +897,7 @@ async fn max_wft_respected() {
|
|
|
892
897
|
let total_wfs = 100;
|
|
893
898
|
let wf_ids: Vec<_> = (0..total_wfs)
|
|
894
899
|
.into_iter()
|
|
895
|
-
.map(|i| format!("fake-wf-{}"
|
|
900
|
+
.map(|i| format!("fake-wf-{i}"))
|
|
896
901
|
.collect();
|
|
897
902
|
let hists = wf_ids.iter().map(|wf_id| {
|
|
898
903
|
let hist = canned_histories::single_timer("1");
|
|
@@ -947,7 +952,7 @@ async fn activity_not_canceled_on_replay_repro(hist_batches: &'static [usize]) {
|
|
|
947
952
|
seq: activity_id,
|
|
948
953
|
activity_id: activity_id.to_string(),
|
|
949
954
|
cancellation_type: ActivityCancellationType::TryCancel as i32,
|
|
950
|
-
..
|
|
955
|
+
..default_act_sched()
|
|
951
956
|
}
|
|
952
957
|
.into(),
|
|
953
958
|
start_timer_cmd(1, Duration::from_secs(1)),
|
|
@@ -989,9 +994,9 @@ async fn activity_not_canceled_when_also_completed_repro(hist_batches: &'static
|
|
|
989
994
|
&job_assert!(workflow_activation_job::Variant::StartWorkflow(_)),
|
|
990
995
|
vec![ScheduleActivity {
|
|
991
996
|
seq: activity_id,
|
|
992
|
-
activity_id:
|
|
997
|
+
activity_id: "act-1".to_string(),
|
|
993
998
|
cancellation_type: ActivityCancellationType::TryCancel as i32,
|
|
994
|
-
..
|
|
999
|
+
..default_act_sched()
|
|
995
1000
|
}
|
|
996
1001
|
.into()],
|
|
997
1002
|
),
|
|
@@ -1022,7 +1027,7 @@ async fn activity_not_canceled_when_also_completed_repro(hist_batches: &'static
|
|
|
1022
1027
|
async fn lots_of_workflows() {
|
|
1023
1028
|
let total_wfs = 500;
|
|
1024
1029
|
let hists = (0..total_wfs).into_iter().map(|i| {
|
|
1025
|
-
let wf_id = format!("fake-wf-{}"
|
|
1030
|
+
let wf_id = format!("fake-wf-{i}");
|
|
1026
1031
|
let hist = canned_histories::single_timer("1");
|
|
1027
1032
|
FakeWfResponses {
|
|
1028
1033
|
wf_id,
|
|
@@ -1092,7 +1097,7 @@ async fn wft_timeout_repro(hist_batches: &'static [usize]) {
|
|
|
1092
1097
|
seq: activity_id,
|
|
1093
1098
|
activity_id: activity_id.to_string(),
|
|
1094
1099
|
cancellation_type: ActivityCancellationType::TryCancel as i32,
|
|
1095
|
-
..
|
|
1100
|
+
..default_act_sched()
|
|
1096
1101
|
}
|
|
1097
1102
|
.into()],
|
|
1098
1103
|
),
|
|
@@ -1225,14 +1230,13 @@ async fn buffered_work_drained_on_shutdown() {
|
|
|
1225
1230
|
let resp_1 = hist_to_poll_resp(&t, wfid.to_owned(), 1.into()).resp;
|
|
1226
1231
|
t.add_workflow_task_timed_out();
|
|
1227
1232
|
t.add_full_wf_task();
|
|
1228
|
-
let timer_started_event_id = t.
|
|
1229
|
-
t.add(
|
|
1230
|
-
|
|
1231
|
-
history_event::Attributes::TimerFiredEventAttributes(TimerFiredEventAttributes {
|
|
1233
|
+
let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
|
|
1234
|
+
t.add(history_event::Attributes::TimerFiredEventAttributes(
|
|
1235
|
+
TimerFiredEventAttributes {
|
|
1232
1236
|
started_event_id: timer_started_event_id,
|
|
1233
1237
|
timer_id: "1".to_string(),
|
|
1234
|
-
}
|
|
1235
|
-
);
|
|
1238
|
+
},
|
|
1239
|
+
));
|
|
1236
1240
|
t.add_full_wf_task();
|
|
1237
1241
|
t.add_workflow_execution_completed();
|
|
1238
1242
|
|
|
@@ -1264,6 +1268,8 @@ async fn buffered_work_drained_on_shutdown() {
|
|
|
1264
1268
|
.unwrap();
|
|
1265
1269
|
};
|
|
1266
1270
|
let complete_first = async move {
|
|
1271
|
+
// If the first complete is sent too fast, we may not have had a chance to buffer work.
|
|
1272
|
+
tokio::time::sleep(Duration::from_millis(50)).await;
|
|
1267
1273
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
1268
1274
|
act1.run_id,
|
|
1269
1275
|
start_timer_cmd(1, Duration::from_secs(1)),
|
|
@@ -1272,8 +1278,6 @@ async fn buffered_work_drained_on_shutdown() {
|
|
|
1272
1278
|
.unwrap();
|
|
1273
1279
|
};
|
|
1274
1280
|
join!(poll_fut, complete_first, async {
|
|
1275
|
-
// If the shutdown is sent too too fast, we might not have got a chance to even buffer work
|
|
1276
|
-
tokio::time::sleep(Duration::from_millis(5)).await;
|
|
1277
1281
|
core.shutdown().await;
|
|
1278
1282
|
});
|
|
1279
1283
|
}
|
|
@@ -1303,7 +1307,7 @@ async fn fail_wft_then_recover() {
|
|
|
1303
1307
|
act.run_id.clone(),
|
|
1304
1308
|
vec![ScheduleActivity {
|
|
1305
1309
|
activity_id: "fake_activity".to_string(),
|
|
1306
|
-
..
|
|
1310
|
+
..default_act_sched()
|
|
1307
1311
|
}
|
|
1308
1312
|
.into()],
|
|
1309
1313
|
))
|
|
@@ -1355,12 +1359,17 @@ async fn poll_response_triggers_wf_error() {
|
|
|
1355
1359
|
t.add_full_wf_task();
|
|
1356
1360
|
t.add_workflow_execution_completed();
|
|
1357
1361
|
|
|
1358
|
-
let mh = MockPollCfg::from_resp_batches(
|
|
1362
|
+
let mut mh = MockPollCfg::from_resp_batches(
|
|
1359
1363
|
"fake_wf_id",
|
|
1360
1364
|
t,
|
|
1361
1365
|
[ResponseType::AllHistory],
|
|
1362
1366
|
mock_workflow_client(),
|
|
1363
1367
|
);
|
|
1368
|
+
// Fail wft will be called when auto-failing.
|
|
1369
|
+
mh.num_expected_fails = 1;
|
|
1370
|
+
mh.expect_fail_wft_matcher = Box::new(move |_, cause, _| {
|
|
1371
|
+
matches!(cause, WorkflowTaskFailedCause::NonDeterministicError)
|
|
1372
|
+
});
|
|
1364
1373
|
let mock = build_mock_pollers(mh);
|
|
1365
1374
|
let core = mock_worker(mock);
|
|
1366
1375
|
// Poll for first WFT, which is immediately an eviction
|
|
@@ -1453,7 +1462,7 @@ async fn tries_cancel_of_completed_activity() {
|
|
|
1453
1462
|
ScheduleActivity {
|
|
1454
1463
|
seq: 1,
|
|
1455
1464
|
activity_id: "1".to_string(),
|
|
1456
|
-
..
|
|
1465
|
+
..default_act_sched()
|
|
1457
1466
|
}
|
|
1458
1467
|
.into(),
|
|
1459
1468
|
))
|
|
@@ -1546,9 +1555,8 @@ async fn failing_wft_doesnt_eat_permit_forever() {
|
|
|
1546
1555
|
))
|
|
1547
1556
|
.await
|
|
1548
1557
|
.unwrap();
|
|
1549
|
-
assert_eq!(worker.available_wft_permits().await, 2);
|
|
1550
|
-
|
|
1551
1558
|
worker.shutdown().await;
|
|
1559
|
+
assert_eq!(worker.available_wft_permits().await, 2);
|
|
1552
1560
|
}
|
|
1553
1561
|
|
|
1554
1562
|
#[tokio::test]
|
|
@@ -1574,6 +1582,8 @@ async fn cache_miss_will_fetch_history() {
|
|
|
1574
1582
|
let mut mock = build_mock_pollers(mh);
|
|
1575
1583
|
mock.worker_cfg(|cfg| {
|
|
1576
1584
|
cfg.max_cached_workflows = 1;
|
|
1585
|
+
// Also verifies tying the WFT permit to the fetch request doesn't get us stuck
|
|
1586
|
+
cfg.max_outstanding_workflow_tasks = 1;
|
|
1577
1587
|
});
|
|
1578
1588
|
let worker = mock_worker(mock);
|
|
1579
1589
|
|
|
@@ -1687,12 +1697,63 @@ async fn tasks_from_completion_are_delivered() {
|
|
|
1687
1697
|
core.shutdown().await;
|
|
1688
1698
|
}
|
|
1689
1699
|
|
|
1700
|
+
#[tokio::test]
|
|
1701
|
+
async fn pagination_works_with_tasks_from_completion() {
|
|
1702
|
+
let wfid = "fake_wf_id";
|
|
1703
|
+
let mut t = TestHistoryBuilder::default();
|
|
1704
|
+
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
1705
|
+
t.add_full_wf_task();
|
|
1706
|
+
t.add_we_signaled("sig", vec![]);
|
|
1707
|
+
t.add_full_wf_task();
|
|
1708
|
+
t.add_workflow_execution_completed();
|
|
1709
|
+
let get_exec_resp: GetWorkflowExecutionHistoryResponse = t.get_history_info(2).unwrap().into();
|
|
1710
|
+
|
|
1711
|
+
let mut mock = mock_workflow_client();
|
|
1712
|
+
let mut needs_pag_resp = hist_to_poll_resp(&t, wfid.to_owned(), ResponseType::OneTask(2)).resp;
|
|
1713
|
+
needs_pag_resp.next_page_token = vec![1];
|
|
1714
|
+
let complete_resp = RespondWorkflowTaskCompletedResponse {
|
|
1715
|
+
workflow_task: Some(needs_pag_resp),
|
|
1716
|
+
..Default::default()
|
|
1717
|
+
};
|
|
1718
|
+
mock.expect_complete_workflow_task()
|
|
1719
|
+
.times(1)
|
|
1720
|
+
.returning(move |_| Ok(complete_resp.clone()));
|
|
1721
|
+
mock.expect_complete_workflow_task()
|
|
1722
|
+
.times(1)
|
|
1723
|
+
.returning(|_| Ok(Default::default()));
|
|
1724
|
+
mock.expect_get_workflow_execution_history()
|
|
1725
|
+
.returning(move |_, _, _| Ok(get_exec_resp.clone()))
|
|
1726
|
+
.times(1);
|
|
1727
|
+
let mut mock = single_hist_mock_sg(wfid, t, [1], mock, true);
|
|
1728
|
+
mock.worker_cfg(|wc| wc.max_cached_workflows = 2);
|
|
1729
|
+
let core = mock_worker(mock);
|
|
1730
|
+
|
|
1731
|
+
let wf_task = core.poll_workflow_activation().await.unwrap();
|
|
1732
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::empty(wf_task.run_id))
|
|
1733
|
+
.await
|
|
1734
|
+
.unwrap();
|
|
1735
|
+
let wf_task = core.poll_workflow_activation().await.unwrap();
|
|
1736
|
+
assert_matches!(
|
|
1737
|
+
wf_task.jobs.as_slice(),
|
|
1738
|
+
[WorkflowActivationJob {
|
|
1739
|
+
variant: Some(workflow_activation_job::Variant::SignalWorkflow(_)),
|
|
1740
|
+
},]
|
|
1741
|
+
);
|
|
1742
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
|
1743
|
+
wf_task.run_id,
|
|
1744
|
+
vec![CompleteWorkflowExecution { result: None }.into()],
|
|
1745
|
+
))
|
|
1746
|
+
.await
|
|
1747
|
+
.unwrap();
|
|
1748
|
+
core.shutdown().await;
|
|
1749
|
+
}
|
|
1750
|
+
|
|
1690
1751
|
#[tokio::test]
|
|
1691
1752
|
async fn poll_faster_than_complete_wont_overflow_cache() {
|
|
1692
1753
|
// Make workflow tasks for 5 different runs
|
|
1693
1754
|
let tasks: Vec<_> = (1..=5)
|
|
1694
1755
|
.map(|i| FakeWfResponses {
|
|
1695
|
-
wf_id: format!("wf-{}"
|
|
1756
|
+
wf_id: format!("wf-{i}"),
|
|
1696
1757
|
hist: canned_histories::single_timer("1"),
|
|
1697
1758
|
response_batches: vec![ResponseType::ToTaskNum(1)],
|
|
1698
1759
|
})
|
|
@@ -1901,7 +1962,7 @@ async fn autocompletes_wft_no_work() {
|
|
|
1901
1962
|
seq: 1,
|
|
1902
1963
|
activity_id: activity_id.to_string(),
|
|
1903
1964
|
cancellation_type: ActivityCancellationType::Abandon as i32,
|
|
1904
|
-
..
|
|
1965
|
+
..default_act_sched()
|
|
1905
1966
|
}
|
|
1906
1967
|
.into(),
|
|
1907
1968
|
))
|
|
@@ -2014,10 +2075,7 @@ async fn continue_as_new_preserves_some_values() {
|
|
|
2014
2075
|
let mut mock_client = mock_workflow_client();
|
|
2015
2076
|
let hist = {
|
|
2016
2077
|
let mut t = TestHistoryBuilder::default();
|
|
2017
|
-
t.add(
|
|
2018
|
-
EventType::WorkflowExecutionStarted,
|
|
2019
|
-
wes_attrs.clone().into(),
|
|
2020
|
-
);
|
|
2078
|
+
t.add(wes_attrs.clone());
|
|
2021
2079
|
t.add_full_wf_task();
|
|
2022
2080
|
t
|
|
2023
2081
|
};
|
|
@@ -2061,21 +2119,19 @@ async fn continue_as_new_preserves_some_values() {
|
|
|
2061
2119
|
async fn ignorable_events_are_ok(#[values(true, false)] attribs_unset: bool) {
|
|
2062
2120
|
let mut t = TestHistoryBuilder::default();
|
|
2063
2121
|
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
2064
|
-
let id = t.
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
t.modify_event(id, |e| e.worker_may_ignore = true);
|
|
2073
|
-
if attribs_unset {
|
|
2074
|
-
t.modify_event(id, |e| {
|
|
2075
|
-
e.event_type = EventType::WorkflowPropertiesModifiedExternally as i32;
|
|
2122
|
+
let id = t.add(WorkflowPropertiesModifiedExternallyEventAttributes::default());
|
|
2123
|
+
t.modify_event(id, |e| {
|
|
2124
|
+
e.worker_may_ignore = true;
|
|
2125
|
+
// Ignorable events are ignored if we can't interpret the proto of either the event attribs
|
|
2126
|
+
// or proto - otherwise (this is the _may_ part of may ignore), we'll still try to process
|
|
2127
|
+
// it. That processing may ultimately still choose to do nothing, if we want to _explicitly_
|
|
2128
|
+
// ignore it.
|
|
2129
|
+
if attribs_unset {
|
|
2076
2130
|
e.attributes = None;
|
|
2077
|
-
}
|
|
2078
|
-
|
|
2131
|
+
} else {
|
|
2132
|
+
e.event_type = EventType::Unspecified as i32;
|
|
2133
|
+
}
|
|
2134
|
+
});
|
|
2079
2135
|
t.add_workflow_task_scheduled_and_started();
|
|
2080
2136
|
|
|
2081
2137
|
let mock = mock_workflow_client();
|
|
@@ -2088,3 +2144,290 @@ async fn ignorable_events_are_ok(#[values(true, false)] attribs_unset: bool) {
|
|
|
2088
2144
|
Some(workflow_activation_job::Variant::StartWorkflow(_))
|
|
2089
2145
|
);
|
|
2090
2146
|
}
|
|
2147
|
+
|
|
2148
|
+
#[tokio::test]
|
|
2149
|
+
async fn fetching_to_continue_replay_works() {
|
|
2150
|
+
let mut mock_client = mock_workflow_client();
|
|
2151
|
+
let mut t = TestHistoryBuilder::default();
|
|
2152
|
+
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
2153
|
+
t.add_full_wf_task();
|
|
2154
|
+
t.add_full_wf_task(); // ends 7
|
|
2155
|
+
let mut need_fetch_resp =
|
|
2156
|
+
hist_to_poll_resp(&t, "wfid".to_owned(), ResponseType::AllHistory).resp;
|
|
2157
|
+
need_fetch_resp.next_page_token = vec![1];
|
|
2158
|
+
|
|
2159
|
+
t.add_full_wf_task();
|
|
2160
|
+
t.add_we_signaled("hi", vec![]); // Need to make there be two complete WFTs
|
|
2161
|
+
t.add_full_wf_task(); // end 14
|
|
2162
|
+
let mut fetch_resp: GetWorkflowExecutionHistoryResponse =
|
|
2163
|
+
t.get_full_history_info().unwrap().into();
|
|
2164
|
+
// Should only contain events after 7
|
|
2165
|
+
if let Some(ref mut h) = fetch_resp.history {
|
|
2166
|
+
h.events.retain(|e| e.event_id >= 8);
|
|
2167
|
+
}
|
|
2168
|
+
// And indicate that even *more* needs to be fetched after this, so we see a request for the
|
|
2169
|
+
// next page happen.
|
|
2170
|
+
fetch_resp.next_page_token = vec![2];
|
|
2171
|
+
|
|
2172
|
+
let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
|
|
2173
|
+
t.add_timer_fired(timer_started_event_id, "1".to_string());
|
|
2174
|
+
t.add_full_wf_task();
|
|
2175
|
+
let mut final_fetch_resp: GetWorkflowExecutionHistoryResponse =
|
|
2176
|
+
t.get_full_history_info().unwrap().into();
|
|
2177
|
+
// Should have only the final event
|
|
2178
|
+
if let Some(ref mut h) = final_fetch_resp.history {
|
|
2179
|
+
h.events.retain(|e| e.event_id >= 15);
|
|
2180
|
+
}
|
|
2181
|
+
|
|
2182
|
+
let tasks = vec![
|
|
2183
|
+
ResponseType::ToTaskNum(1),
|
|
2184
|
+
ResponseType::Raw(need_fetch_resp),
|
|
2185
|
+
];
|
|
2186
|
+
mock_client
|
|
2187
|
+
.expect_get_workflow_execution_history()
|
|
2188
|
+
.returning(move |_, _, _| Ok(fetch_resp.clone()))
|
|
2189
|
+
.times(1);
|
|
2190
|
+
mock_client
|
|
2191
|
+
.expect_get_workflow_execution_history()
|
|
2192
|
+
.returning(move |_, _, _| Ok(final_fetch_resp.clone()))
|
|
2193
|
+
.times(1);
|
|
2194
|
+
let mut mock = single_hist_mock_sg("wfid", t, tasks, mock_client, true);
|
|
2195
|
+
mock.worker_cfg(|wc| wc.max_cached_workflows = 10);
|
|
2196
|
+
let core = mock_worker(mock);
|
|
2197
|
+
let act = core.poll_workflow_activation().await.unwrap();
|
|
2198
|
+
assert_matches!(
|
|
2199
|
+
act.jobs[0].variant,
|
|
2200
|
+
Some(workflow_activation_job::Variant::StartWorkflow(_))
|
|
2201
|
+
);
|
|
2202
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::empty(act.run_id))
|
|
2203
|
+
.await
|
|
2204
|
+
.unwrap();
|
|
2205
|
+
let act = core.poll_workflow_activation().await.unwrap();
|
|
2206
|
+
assert_matches!(
|
|
2207
|
+
act.jobs.as_slice(),
|
|
2208
|
+
[WorkflowActivationJob {
|
|
2209
|
+
variant: Some(workflow_activation_job::Variant::SignalWorkflow(_)),
|
|
2210
|
+
}]
|
|
2211
|
+
);
|
|
2212
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
2213
|
+
act.run_id,
|
|
2214
|
+
start_timer_cmd(1, Duration::from_secs(1)),
|
|
2215
|
+
))
|
|
2216
|
+
.await
|
|
2217
|
+
.unwrap();
|
|
2218
|
+
let act = core.poll_workflow_activation().await.unwrap();
|
|
2219
|
+
assert_matches!(
|
|
2220
|
+
act.jobs.as_slice(),
|
|
2221
|
+
[WorkflowActivationJob {
|
|
2222
|
+
variant: Some(workflow_activation_job::Variant::FireTimer(_)),
|
|
2223
|
+
}]
|
|
2224
|
+
);
|
|
2225
|
+
}
|
|
2226
|
+
|
|
2227
|
+
#[tokio::test]
|
|
2228
|
+
async fn fetching_error_evicts_wf() {
|
|
2229
|
+
let mut mock_client = mock_workflow_client();
|
|
2230
|
+
let mut t = TestHistoryBuilder::default();
|
|
2231
|
+
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
2232
|
+
t.add_workflow_task_scheduled_and_started();
|
|
2233
|
+
t.add_workflow_task_completed();
|
|
2234
|
+
let mut need_fetch_resp =
|
|
2235
|
+
hist_to_poll_resp(&t, "wfid".to_owned(), ResponseType::AllHistory).resp;
|
|
2236
|
+
need_fetch_resp.next_page_token = vec![1];
|
|
2237
|
+
let tasks = vec![
|
|
2238
|
+
ResponseType::ToTaskNum(1),
|
|
2239
|
+
ResponseType::Raw(need_fetch_resp),
|
|
2240
|
+
];
|
|
2241
|
+
mock_client
|
|
2242
|
+
.expect_get_workflow_execution_history()
|
|
2243
|
+
.returning(move |_, _, _| Err(tonic::Status::not_found("Ahh broken")))
|
|
2244
|
+
.times(1);
|
|
2245
|
+
let mut mock = single_hist_mock_sg("wfid", t, tasks, mock_client, true);
|
|
2246
|
+
mock.worker_cfg(|wc| wc.max_cached_workflows = 10);
|
|
2247
|
+
let core = mock_worker(mock);
|
|
2248
|
+
let act = core.poll_workflow_activation().await.unwrap();
|
|
2249
|
+
assert_matches!(
|
|
2250
|
+
act.jobs[0].variant,
|
|
2251
|
+
Some(workflow_activation_job::Variant::StartWorkflow(_))
|
|
2252
|
+
);
|
|
2253
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::empty(act.run_id))
|
|
2254
|
+
.await
|
|
2255
|
+
.unwrap();
|
|
2256
|
+
let evict_act = core.poll_workflow_activation().await.unwrap();
|
|
2257
|
+
assert_matches!(
|
|
2258
|
+
evict_act.jobs.as_slice(),
|
|
2259
|
+
[WorkflowActivationJob {
|
|
2260
|
+
variant: Some(workflow_activation_job::Variant::RemoveFromCache(r)),
|
|
2261
|
+
}] => r.message.contains("Fetching history failed")
|
|
2262
|
+
);
|
|
2263
|
+
}
|
|
2264
|
+
|
|
2265
|
+
/// This test verifies that if we fail to fetch a page during a completion, that we don't get stuck
|
|
2266
|
+
/// in the complete waiting for the completion to finish.
|
|
2267
|
+
#[tokio::test]
|
|
2268
|
+
async fn ensure_fetching_fail_during_complete_sends_task_failure() {
|
|
2269
|
+
let wfid = "fake_wf_id";
|
|
2270
|
+
let mut t = TestHistoryBuilder::default();
|
|
2271
|
+
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
2272
|
+
t.add_full_wf_task(); // started 3
|
|
2273
|
+
t.add_we_signaled("sig1", vec![]);
|
|
2274
|
+
t.add_full_wf_task(); // started 7
|
|
2275
|
+
t.add_we_signaled("sig2", vec![]);
|
|
2276
|
+
t.add_full_wf_task(); // started 11
|
|
2277
|
+
t.add_workflow_execution_completed();
|
|
2278
|
+
|
|
2279
|
+
let mut first_poll = hist_to_poll_resp(&t, wfid, ResponseType::ToTaskNum(1)).resp;
|
|
2280
|
+
first_poll.next_page_token = vec![1];
|
|
2281
|
+
first_poll.previous_started_event_id = 3;
|
|
2282
|
+
|
|
2283
|
+
let mut next_page: GetWorkflowExecutionHistoryResponse = t.get_history_info(2).unwrap().into();
|
|
2284
|
+
next_page.next_page_token = vec![2];
|
|
2285
|
+
|
|
2286
|
+
let mut mock = mock_workflow_client();
|
|
2287
|
+
mock.expect_get_workflow_execution_history()
|
|
2288
|
+
.returning(move |_, _, _| {
|
|
2289
|
+
error!("Called fetch!");
|
|
2290
|
+
Ok(next_page.clone())
|
|
2291
|
+
})
|
|
2292
|
+
.times(1);
|
|
2293
|
+
let mut really_empty_fetch_resp: GetWorkflowExecutionHistoryResponse =
|
|
2294
|
+
t.get_history_info(1).unwrap().into();
|
|
2295
|
+
really_empty_fetch_resp.history = Some(Default::default());
|
|
2296
|
+
mock.expect_get_workflow_execution_history()
|
|
2297
|
+
.returning(move |_, _, _| {
|
|
2298
|
+
error!("Called fetch second time!");
|
|
2299
|
+
Ok(really_empty_fetch_resp.clone())
|
|
2300
|
+
})
|
|
2301
|
+
.times(1);
|
|
2302
|
+
mock.expect_fail_workflow_task()
|
|
2303
|
+
.returning(|_, _, _| Ok(Default::default()))
|
|
2304
|
+
.times(1);
|
|
2305
|
+
|
|
2306
|
+
let mut mock = single_hist_mock_sg(wfid, t, [ResponseType::Raw(first_poll)], mock, true);
|
|
2307
|
+
mock.make_wft_stream_interminable();
|
|
2308
|
+
mock.worker_cfg(|wc| wc.max_cached_workflows = 2);
|
|
2309
|
+
let core = mock_worker(mock);
|
|
2310
|
+
|
|
2311
|
+
let wf_task = core.poll_workflow_activation().await.unwrap();
|
|
2312
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::empty(wf_task.run_id))
|
|
2313
|
+
.await
|
|
2314
|
+
.unwrap();
|
|
2315
|
+
|
|
2316
|
+
let wf_task = core.poll_workflow_activation().await.unwrap();
|
|
2317
|
+
assert_matches!(
|
|
2318
|
+
wf_task.jobs.as_slice(),
|
|
2319
|
+
[WorkflowActivationJob {
|
|
2320
|
+
variant: Some(workflow_activation_job::Variant::SignalWorkflow(_)),
|
|
2321
|
+
},]
|
|
2322
|
+
);
|
|
2323
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::empty(wf_task.run_id))
|
|
2324
|
+
.await
|
|
2325
|
+
.unwrap();
|
|
2326
|
+
|
|
2327
|
+
// Expect to see eviction b/c of history fetching error here.
|
|
2328
|
+
let wf_task = core.poll_workflow_activation().await.unwrap();
|
|
2329
|
+
assert_matches!(
|
|
2330
|
+
wf_task.jobs.as_slice(),
|
|
2331
|
+
[WorkflowActivationJob {
|
|
2332
|
+
variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
|
|
2333
|
+
},]
|
|
2334
|
+
);
|
|
2335
|
+
|
|
2336
|
+
core.shutdown().await;
|
|
2337
|
+
}
|
|
2338
|
+
|
|
2339
|
+
#[tokio::test]
|
|
2340
|
+
async fn lang_internal_flags() {
|
|
2341
|
+
let mut t = TestHistoryBuilder::default();
|
|
2342
|
+
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
2343
|
+
t.add_full_wf_task();
|
|
2344
|
+
t.set_flags_first_wft(&[], &[1]);
|
|
2345
|
+
t.add_we_signaled("sig1", vec![]);
|
|
2346
|
+
t.add_full_wf_task();
|
|
2347
|
+
t.set_flags_last_wft(&[], &[2]);
|
|
2348
|
+
t.add_we_signaled("sig2", vec![]);
|
|
2349
|
+
t.add_full_wf_task();
|
|
2350
|
+
t.add_workflow_execution_completed();
|
|
2351
|
+
|
|
2352
|
+
let mut mh = MockPollCfg::from_resp_batches(
|
|
2353
|
+
"fake_wf_id",
|
|
2354
|
+
t,
|
|
2355
|
+
[ResponseType::ToTaskNum(2), ResponseType::AllHistory],
|
|
2356
|
+
mock_workflow_client(),
|
|
2357
|
+
);
|
|
2358
|
+
mh.completion_asserts = Some(Box::new(|c| {
|
|
2359
|
+
assert_matches!(c.sdk_metadata.lang_used_flags.as_slice(), &[2]);
|
|
2360
|
+
}));
|
|
2361
|
+
let mut mock = build_mock_pollers(mh);
|
|
2362
|
+
mock.worker_cfg(|wc| wc.max_cached_workflows = 1);
|
|
2363
|
+
let core = mock_worker(mock);
|
|
2364
|
+
|
|
2365
|
+
let act = core.poll_workflow_activation().await.unwrap();
|
|
2366
|
+
assert_matches!(act.available_internal_flags.as_slice(), [1]);
|
|
2367
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::empty(act.run_id))
|
|
2368
|
+
.await
|
|
2369
|
+
.unwrap();
|
|
2370
|
+
|
|
2371
|
+
let act = core.poll_workflow_activation().await.unwrap();
|
|
2372
|
+
let mut completion = WorkflowActivationCompletion::empty(act.run_id);
|
|
2373
|
+
completion.add_internal_flags(2);
|
|
2374
|
+
core.complete_workflow_activation(completion).await.unwrap();
|
|
2375
|
+
|
|
2376
|
+
let act = core.poll_workflow_activation().await.unwrap();
|
|
2377
|
+
assert_matches!(act.available_internal_flags.as_slice(), [1, 2]);
|
|
2378
|
+
core.complete_execution(&act.run_id).await;
|
|
2379
|
+
core.shutdown().await;
|
|
2380
|
+
}
|
|
2381
|
+
|
|
2382
|
+
// Verify we send flags to server when they're used
|
|
2383
|
+
#[tokio::test]
|
|
2384
|
+
async fn core_internal_flags() {
|
|
2385
|
+
let mut t = TestHistoryBuilder::default();
|
|
2386
|
+
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
2387
|
+
t.add_full_wf_task();
|
|
2388
|
+
let act_scheduled_event_id = t.add_activity_task_scheduled("act-id");
|
|
2389
|
+
let act_started_event_id = t.add_activity_task_started(act_scheduled_event_id);
|
|
2390
|
+
t.add_activity_task_completed(
|
|
2391
|
+
act_scheduled_event_id,
|
|
2392
|
+
act_started_event_id,
|
|
2393
|
+
Default::default(),
|
|
2394
|
+
);
|
|
2395
|
+
t.add_full_wf_task();
|
|
2396
|
+
t.add_workflow_execution_completed();
|
|
2397
|
+
|
|
2398
|
+
let mut mh = MockPollCfg::from_resp_batches(
|
|
2399
|
+
"fake_wf_id",
|
|
2400
|
+
t,
|
|
2401
|
+
[ResponseType::ToTaskNum(1), ResponseType::ToTaskNum(2)],
|
|
2402
|
+
mock_workflow_client(),
|
|
2403
|
+
);
|
|
2404
|
+
let first_poll = AtomicBool::new(true);
|
|
2405
|
+
mh.completion_asserts = Some(Box::new(move |c| {
|
|
2406
|
+
if !first_poll.load(Ordering::Acquire) {
|
|
2407
|
+
assert_matches!(c.sdk_metadata.core_used_flags.as_slice(), &[1]);
|
|
2408
|
+
}
|
|
2409
|
+
first_poll.store(false, Ordering::Release);
|
|
2410
|
+
}));
|
|
2411
|
+
let mut mock = build_mock_pollers(mh);
|
|
2412
|
+
mock.worker_cfg(|wc| wc.max_cached_workflows = 1);
|
|
2413
|
+
let core = mock_worker(mock);
|
|
2414
|
+
|
|
2415
|
+
let act = core.poll_workflow_activation().await.unwrap();
|
|
2416
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
2417
|
+
act.run_id,
|
|
2418
|
+
schedule_activity_cmd(
|
|
2419
|
+
1,
|
|
2420
|
+
"whatever",
|
|
2421
|
+
"act-id",
|
|
2422
|
+
ActivityCancellationType::TryCancel,
|
|
2423
|
+
Duration::from_secs(60),
|
|
2424
|
+
Duration::from_secs(60),
|
|
2425
|
+
),
|
|
2426
|
+
))
|
|
2427
|
+
.await
|
|
2428
|
+
.unwrap();
|
|
2429
|
+
|
|
2430
|
+
let act = core.poll_workflow_activation().await.unwrap();
|
|
2431
|
+
core.complete_execution(&act.run_id).await;
|
|
2432
|
+
core.shutdown().await;
|
|
2433
|
+
}
|