@temporalio/core-bridge 0.19.2 → 0.20.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/Cargo.lock +90 -157
  2. package/Cargo.toml +1 -0
  3. package/index.d.ts +11 -27
  4. package/package.json +3 -3
  5. package/releases/aarch64-apple-darwin/index.node +0 -0
  6. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  7. package/releases/x86_64-apple-darwin/index.node +0 -0
  8. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  9. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  10. package/sdk-core/.buildkite/docker/Dockerfile +1 -1
  11. package/sdk-core/.buildkite/docker/docker-compose.yaml +1 -1
  12. package/sdk-core/.cargo/config.toml +1 -0
  13. package/sdk-core/CODEOWNERS +1 -1
  14. package/sdk-core/bridge-ffi/include/sdk-core-bridge.h +119 -86
  15. package/sdk-core/bridge-ffi/src/lib.rs +311 -315
  16. package/sdk-core/bridge-ffi/src/wrappers.rs +108 -113
  17. package/sdk-core/client/Cargo.toml +13 -9
  18. package/sdk-core/client/LICENSE.txt +23 -0
  19. package/sdk-core/client/src/lib.rs +286 -174
  20. package/sdk-core/client/src/metrics.rs +86 -12
  21. package/sdk-core/client/src/raw.rs +566 -0
  22. package/sdk-core/client/src/retry.rs +137 -99
  23. package/sdk-core/core/Cargo.toml +15 -10
  24. package/sdk-core/core/LICENSE.txt +23 -0
  25. package/sdk-core/core/benches/workflow_replay.rs +79 -0
  26. package/sdk-core/core/src/abstractions.rs +38 -0
  27. package/sdk-core/core/src/core_tests/activity_tasks.rs +108 -182
  28. package/sdk-core/core/src/core_tests/child_workflows.rs +16 -11
  29. package/sdk-core/core/src/core_tests/determinism.rs +24 -12
  30. package/sdk-core/core/src/core_tests/local_activities.rs +53 -27
  31. package/sdk-core/core/src/core_tests/mod.rs +30 -43
  32. package/sdk-core/core/src/core_tests/queries.rs +82 -81
  33. package/sdk-core/core/src/core_tests/workers.rs +111 -296
  34. package/sdk-core/core/src/core_tests/workflow_cancels.rs +4 -4
  35. package/sdk-core/core/src/core_tests/workflow_tasks.rs +257 -242
  36. package/sdk-core/core/src/lib.rs +73 -318
  37. package/sdk-core/core/src/pollers/mod.rs +4 -6
  38. package/sdk-core/core/src/pollers/poll_buffer.rs +20 -14
  39. package/sdk-core/core/src/protosext/mod.rs +7 -10
  40. package/sdk-core/core/src/replay/mod.rs +11 -150
  41. package/sdk-core/core/src/telemetry/metrics.rs +35 -2
  42. package/sdk-core/core/src/telemetry/mod.rs +49 -16
  43. package/sdk-core/core/src/telemetry/prometheus_server.rs +14 -35
  44. package/sdk-core/core/src/test_help/mod.rs +104 -170
  45. package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +57 -34
  46. package/sdk-core/core/src/worker/activities/local_activities.rs +95 -23
  47. package/sdk-core/core/src/worker/activities.rs +23 -16
  48. package/sdk-core/core/src/worker/client/mocks.rs +86 -0
  49. package/sdk-core/core/src/worker/client.rs +209 -0
  50. package/sdk-core/core/src/worker/mod.rs +207 -108
  51. package/sdk-core/core/src/workflow/driven_workflow.rs +21 -6
  52. package/sdk-core/core/src/workflow/history_update.rs +107 -24
  53. package/sdk-core/core/src/workflow/machines/activity_state_machine.rs +2 -3
  54. package/sdk-core/core/src/workflow/machines/child_workflow_state_machine.rs +2 -3
  55. package/sdk-core/core/src/workflow/machines/mod.rs +20 -17
  56. package/sdk-core/core/src/workflow/machines/signal_external_state_machine.rs +56 -19
  57. package/sdk-core/core/src/workflow/machines/transition_coverage.rs +5 -0
  58. package/sdk-core/core/src/workflow/machines/upsert_search_attributes_state_machine.rs +230 -22
  59. package/sdk-core/core/src/workflow/machines/workflow_machines.rs +81 -115
  60. package/sdk-core/core/src/workflow/machines/workflow_task_state_machine.rs +4 -4
  61. package/sdk-core/core/src/workflow/mod.rs +13 -1
  62. package/sdk-core/core/src/workflow/workflow_tasks/concurrency_manager.rs +70 -11
  63. package/sdk-core/core/src/workflow/workflow_tasks/mod.rs +65 -41
  64. package/sdk-core/core-api/Cargo.toml +9 -1
  65. package/sdk-core/core-api/LICENSE.txt +23 -0
  66. package/sdk-core/core-api/src/errors.rs +7 -38
  67. package/sdk-core/core-api/src/lib.rs +44 -52
  68. package/sdk-core/core-api/src/worker.rs +10 -2
  69. package/sdk-core/etc/deps.svg +127 -96
  70. package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +11 -7
  71. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +10 -0
  72. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +6 -1
  73. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +6 -0
  74. package/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +6 -0
  75. package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +2 -1
  76. package/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +3 -0
  77. package/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +12 -0
  78. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +25 -0
  79. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +4 -0
  80. package/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +19 -35
  81. package/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +2 -6
  82. package/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +53 -11
  83. package/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +14 -7
  84. package/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +3 -5
  85. package/sdk-core/sdk/Cargo.toml +16 -2
  86. package/sdk-core/sdk/LICENSE.txt +23 -0
  87. package/sdk-core/sdk/src/interceptors.rs +11 -0
  88. package/sdk-core/sdk/src/lib.rs +139 -151
  89. package/sdk-core/sdk/src/workflow_context/options.rs +86 -1
  90. package/sdk-core/sdk/src/workflow_context.rs +36 -17
  91. package/sdk-core/sdk/src/workflow_future.rs +19 -25
  92. package/sdk-core/sdk-core-protos/Cargo.toml +1 -1
  93. package/sdk-core/sdk-core-protos/build.rs +1 -0
  94. package/sdk-core/sdk-core-protos/src/history_info.rs +17 -4
  95. package/sdk-core/sdk-core-protos/src/lib.rs +251 -47
  96. package/sdk-core/test-utils/Cargo.toml +3 -1
  97. package/sdk-core/test-utils/src/canned_histories.rs +27 -0
  98. package/sdk-core/test-utils/src/histfetch.rs +3 -3
  99. package/sdk-core/test-utils/src/lib.rs +223 -68
  100. package/sdk-core/tests/integ_tests/client_tests.rs +27 -4
  101. package/sdk-core/tests/integ_tests/heartbeat_tests.rs +93 -14
  102. package/sdk-core/tests/integ_tests/polling_tests.rs +18 -12
  103. package/sdk-core/tests/integ_tests/queries_tests.rs +50 -53
  104. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +117 -103
  105. package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +8 -1
  106. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +10 -5
  107. package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +7 -1
  108. package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +32 -9
  109. package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +7 -1
  110. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +76 -15
  111. package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +19 -3
  112. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +39 -42
  113. package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +84 -0
  114. package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +30 -8
  115. package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +21 -6
  116. package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +26 -16
  117. package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +66 -0
  118. package/sdk-core/tests/integ_tests/workflow_tests.rs +78 -74
  119. package/sdk-core/tests/load_tests.rs +9 -6
  120. package/sdk-core/tests/main.rs +43 -10
  121. package/src/conversions.rs +7 -12
  122. package/src/lib.rs +322 -357
  123. package/sdk-core/client/src/mocks.rs +0 -167
  124. package/sdk-core/core/src/worker/dispatcher.rs +0 -171
  125. package/sdk-core/protos/local/temporal/sdk/core/bridge/service.proto +0 -61
@@ -3,13 +3,14 @@ use crate::{
3
3
  job_assert,
4
4
  replay::TestHistoryBuilder,
5
5
  test_help::{
6
- build_fake_core, build_mock_pollers, build_multihist_mock_sg, canned_histories,
7
- gen_assert_and_fail, gen_assert_and_reply, hist_to_poll_resp, mock_core, poll_and_reply,
6
+ build_fake_worker, build_mock_pollers, build_multihist_mock_sg, canned_histories,
7
+ gen_assert_and_fail, gen_assert_and_reply, hist_to_poll_resp, mock_worker, poll_and_reply,
8
8
  poll_and_reply_clears_outstanding_evicts, single_hist_mock_sg, FakeWfResponses,
9
9
  MockPollCfg, MocksHolder, ResponseType, NO_MORE_WORK_ERROR_MSG, TEST_Q,
10
10
  },
11
+ worker::client::mocks::mock_workflow_client,
11
12
  workflow::WorkflowCachingPolicy::{self, AfterEveryReply, NonSticky},
12
- Core, CoreSDK, WorkflowActivationCompletion,
13
+ Worker,
13
14
  };
14
15
  use rstest::{fixture, rstest};
15
16
  use std::{
@@ -17,50 +18,53 @@ use std::{
17
18
  sync::atomic::{AtomicU64, AtomicUsize, Ordering},
18
19
  time::Duration,
19
20
  };
20
- use temporal_client::mocks::mock_gateway;
21
+ use temporal_sdk_core_api::Worker as WorkerTrait;
21
22
  use temporal_sdk_core_protos::{
22
23
  coresdk::{
23
24
  activity_result::{self as ar, activity_resolution, ActivityResolution},
24
25
  workflow_activation::{
25
- workflow_activation_job, FireTimer, ResolveActivity, StartWorkflow, UpdateRandomSeed,
26
- WorkflowActivationJob,
26
+ remove_from_cache::EvictionReason, workflow_activation_job, FireTimer, ResolveActivity,
27
+ StartWorkflow, UpdateRandomSeed, WorkflowActivationJob,
27
28
  },
28
29
  workflow_commands::{
29
30
  ActivityCancellationType, CancelTimer, CompleteWorkflowExecution,
30
31
  FailWorkflowExecution, RequestCancelActivity, ScheduleActivity,
31
32
  },
33
+ workflow_completion::WorkflowActivationCompletion,
32
34
  },
33
35
  temporal::api::{
34
36
  enums::v1::{EventType, WorkflowTaskFailedCause},
35
37
  failure::v1::Failure,
36
- history::v1::{history_event, TimerFiredEventAttributes},
37
- workflowservice::v1::RespondWorkflowTaskCompletedResponse,
38
+ history::v1::{history_event, History, TimerFiredEventAttributes},
39
+ workflowservice::v1::{
40
+ GetWorkflowExecutionHistoryResponse, RespondWorkflowTaskCompletedResponse,
41
+ },
38
42
  },
39
43
  };
40
44
  use temporal_sdk_core_test_utils::{fanout_tasks, start_timer_cmd};
41
45
 
42
46
  #[fixture(hist_batches = &[])]
43
- fn single_timer_setup(hist_batches: &'static [usize]) -> CoreSDK {
47
+ fn single_timer_setup(hist_batches: &'static [usize]) -> Worker {
44
48
  let wfid = "fake_wf_id";
45
49
 
46
50
  let t = canned_histories::single_timer("1");
47
- build_fake_core(wfid, t, hist_batches)
51
+ build_fake_worker(wfid, t, hist_batches)
48
52
  }
49
53
 
50
54
  #[fixture(hist_batches = &[])]
51
- fn single_activity_setup(hist_batches: &'static [usize]) -> CoreSDK {
55
+ fn single_activity_setup(hist_batches: &'static [usize]) -> Worker {
52
56
  let wfid = "fake_wf_id";
53
57
 
54
58
  let t = canned_histories::single_activity("fake_activity");
55
- build_fake_core(wfid, t, hist_batches)
59
+ build_fake_worker(wfid, t, hist_batches)
56
60
  }
57
61
 
58
62
  #[fixture(hist_batches = &[])]
59
- fn single_activity_failure_setup(hist_batches: &'static [usize]) -> CoreSDK {
63
+ fn single_activity_failure_setup(hist_batches: &'static [usize]) -> Worker {
60
64
  let wfid = "fake_wf_id";
61
65
 
62
66
  let t = canned_histories::single_failed_activity("fake_activity");
63
- build_fake_core(wfid, t, hist_batches)
67
+ build_fake_worker(wfid, t, hist_batches)
64
68
  }
65
69
 
66
70
  #[rstest]
@@ -69,9 +73,9 @@ fn single_activity_failure_setup(hist_batches: &'static [usize]) -> CoreSDK {
69
73
  #[case::incremental_evict(single_timer_setup(&[1, 2]), AfterEveryReply)]
70
74
  #[case::replay_evict(single_timer_setup(&[2, 2]), AfterEveryReply)]
71
75
  #[tokio::test]
72
- async fn single_timer(#[case] core: CoreSDK, #[case] evict: WorkflowCachingPolicy) {
76
+ async fn single_timer(#[case] worker: Worker, #[case] evict: WorkflowCachingPolicy) {
73
77
  poll_and_reply(
74
- &core,
78
+ &worker,
75
79
  evict,
76
80
  &[
77
81
  gen_assert_and_reply(
@@ -87,16 +91,16 @@ async fn single_timer(#[case] core: CoreSDK, #[case] evict: WorkflowCachingPolic
87
91
  .await;
88
92
  }
89
93
 
90
- #[rstest(core,
94
+ #[rstest(worker,
91
95
  case::incremental(single_activity_setup(&[1, 2])),
92
96
  case::incremental_activity_failure(single_activity_failure_setup(&[1, 2])),
93
97
  case::replay(single_activity_setup(&[2])),
94
98
  case::replay_activity_failure(single_activity_failure_setup(&[2]))
95
99
  )]
96
100
  #[tokio::test]
97
- async fn single_activity_completion(core: CoreSDK) {
101
+ async fn single_activity_completion(worker: Worker) {
98
102
  poll_and_reply(
99
- &core,
103
+ &worker,
100
104
  NonSticky,
101
105
  &[
102
106
  gen_assert_and_reply(
@@ -127,7 +131,7 @@ async fn parallel_timer_test_across_wf_bridge(hist_batches: &'static [usize]) {
127
131
  timer_1_id.to_string().as_str(),
128
132
  timer_2_id.to_string().as_str(),
129
133
  );
130
- let core = build_fake_core(wfid, t, hist_batches);
134
+ let core = build_fake_worker(wfid, t, hist_batches);
131
135
 
132
136
  poll_and_reply(
133
137
  &core,
@@ -179,7 +183,7 @@ async fn timer_cancel(hist_batches: &'static [usize]) {
179
183
  timer_id.to_string().as_str(),
180
184
  cancel_timer_id.to_string().as_str(),
181
185
  );
182
- let core = build_fake_core(wfid, t, hist_batches);
186
+ let core = build_fake_worker(wfid, t, hist_batches);
183
187
 
184
188
  poll_and_reply(
185
189
  &core,
@@ -216,7 +220,7 @@ async fn scheduled_activity_cancellation_try_cancel(hist_batches: &'static [usiz
216
220
  let signal_id = "signal";
217
221
 
218
222
  let t = canned_histories::cancel_scheduled_activity(activity_id, signal_id);
219
- let core = build_fake_core(wfid, t, hist_batches);
223
+ let core = build_fake_worker(wfid, t, hist_batches);
220
224
 
221
225
  poll_and_reply(
222
226
  &core,
@@ -254,7 +258,7 @@ async fn scheduled_activity_timeout(hist_batches: &'static [usize]) {
254
258
  let activity_id = "fake_activity";
255
259
 
256
260
  let t = canned_histories::scheduled_activity_timeout(activity_id);
257
- let core = build_fake_core(wfid, t, hist_batches);
261
+ let core = build_fake_worker(wfid, t, hist_batches);
258
262
  poll_and_reply(
259
263
  &core,
260
264
  NonSticky,
@@ -306,7 +310,7 @@ async fn started_activity_timeout(hist_batches: &'static [usize]) {
306
310
  let activity_seq = 1;
307
311
 
308
312
  let t = canned_histories::started_activity_timeout(activity_seq.to_string().as_str());
309
- let core = build_fake_core(wfid, t, hist_batches);
313
+ let core = build_fake_worker(wfid, t, hist_batches);
310
314
 
311
315
  poll_and_reply(
312
316
  &core,
@@ -361,7 +365,7 @@ async fn cancelled_activity_timeout(hist_batches: &'static [usize]) {
361
365
  let signal_id = "signal";
362
366
 
363
367
  let t = canned_histories::scheduled_cancelled_activity_timeout(activity_id, signal_id);
364
- let core = build_fake_core(wfid, t, hist_batches);
368
+ let core = build_fake_worker(wfid, t, hist_batches);
365
369
 
366
370
  poll_and_reply(
367
371
  &core,
@@ -408,7 +412,7 @@ async fn scheduled_activity_cancellation_abandon(hist_batches: &'static [usize])
408
412
  activity_id.to_string().as_str(),
409
413
  signal_id,
410
414
  );
411
- let core = build_fake_core(wfid, t, hist_batches);
415
+ let core = build_fake_worker(wfid, t, hist_batches);
412
416
 
413
417
  verify_activity_cancellation(&core, activity_id, ActivityCancellationType::Abandon).await;
414
418
  }
@@ -424,7 +428,7 @@ async fn started_activity_cancellation_abandon(hist_batches: &'static [usize]) {
424
428
  activity_id.to_string().as_str(),
425
429
  signal_id,
426
430
  );
427
- let core = build_fake_core(wfid, t, hist_batches);
431
+ let core = build_fake_worker(wfid, t, hist_batches);
428
432
 
429
433
  verify_activity_cancellation(&core, activity_id, ActivityCancellationType::Abandon).await;
430
434
  }
@@ -440,7 +444,7 @@ async fn scheduled_activity_cancellation_try_cancel_task_canceled(hist_batches:
440
444
  activity_id.to_string().as_str(),
441
445
  signal_id,
442
446
  );
443
- let core = build_fake_core(wfid, t, hist_batches);
447
+ let core = build_fake_worker(wfid, t, hist_batches);
444
448
 
445
449
  verify_activity_cancellation(&core, activity_id, ActivityCancellationType::TryCancel).await;
446
450
  }
@@ -456,19 +460,19 @@ async fn started_activity_cancellation_try_cancel_task_canceled(hist_batches: &'
456
460
  activity_id.to_string().as_str(),
457
461
  signal_id,
458
462
  );
459
- let core = build_fake_core(wfid, t, hist_batches);
463
+ let core = build_fake_worker(wfid, t, hist_batches);
460
464
 
461
465
  verify_activity_cancellation(&core, activity_id, ActivityCancellationType::TryCancel).await;
462
466
  }
463
467
 
464
468
  /// Verification for try cancel & abandon histories
465
469
  async fn verify_activity_cancellation(
466
- core: &CoreSDK,
470
+ worker: &Worker,
467
471
  activity_seq: u32,
468
472
  cancel_type: ActivityCancellationType,
469
473
  ) {
470
474
  poll_and_reply(
471
- core,
475
+ worker,
472
476
  NonSticky,
473
477
  &[
474
478
  gen_assert_and_reply(
@@ -513,7 +517,7 @@ async fn scheduled_activity_cancellation_wait_for_cancellation(hist_batches: &'s
513
517
  activity_id.to_string().as_str(),
514
518
  signal_id,
515
519
  );
516
- let core = build_fake_core(wfid, t, hist_batches);
520
+ let core = build_fake_worker(wfid, t, hist_batches);
517
521
 
518
522
  verify_activity_cancellation_wait_for_cancellation(activity_id, &core).await;
519
523
  }
@@ -529,14 +533,14 @@ async fn started_activity_cancellation_wait_for_cancellation(hist_batches: &'sta
529
533
  activity_id.to_string().as_str(),
530
534
  signal_id,
531
535
  );
532
- let core = build_fake_core(wfid, t, hist_batches);
536
+ let core = build_fake_worker(wfid, t, hist_batches);
533
537
 
534
538
  verify_activity_cancellation_wait_for_cancellation(activity_id, &core).await;
535
539
  }
536
540
 
537
- async fn verify_activity_cancellation_wait_for_cancellation(activity_id: u32, core: &CoreSDK) {
541
+ async fn verify_activity_cancellation_wait_for_cancellation(activity_id: u32, worker: &Worker) {
538
542
  poll_and_reply(
539
- core,
543
+ worker,
540
544
  NonSticky,
541
545
  &[
542
546
  gen_assert_and_reply(
@@ -586,7 +590,7 @@ async fn workflow_update_random_seed_on_workflow_reset() {
586
590
  timer_1_id.to_string().as_str(),
587
591
  new_run_id,
588
592
  );
589
- let core = build_fake_core(wfid, t, &[2]);
593
+ let core = build_fake_worker(wfid, t, &[2]);
590
594
 
591
595
  poll_and_reply(
592
596
  &core,
@@ -640,7 +644,7 @@ async fn cancel_timer_before_sent_wf_bridge() {
640
644
  t.add_full_wf_task();
641
645
  t.add_workflow_execution_completed();
642
646
 
643
- let core = build_fake_core(wfid, t, &[1]);
647
+ let core = build_fake_worker(wfid, t, &[1]);
644
648
 
645
649
  poll_and_reply(
646
650
  &core,
@@ -678,12 +682,11 @@ async fn complete_activation_with_failure(
678
682
  wf_id: wfid.to_string(),
679
683
  hist,
680
684
  response_batches: batches.iter().map(Into::into).collect(),
681
- task_q: TEST_Q.to_owned(),
682
685
  }],
683
686
  true,
684
687
  Some(1),
685
688
  );
686
- let core = mock_core(mock_sg);
689
+ let core = mock_worker(mock_sg);
687
690
 
688
691
  poll_and_reply(
689
692
  &core,
@@ -711,7 +714,7 @@ async fn simple_timer_fail_wf_execution(hist_batches: &'static [usize]) {
711
714
  let timer_id = 1;
712
715
 
713
716
  let t = canned_histories::single_timer(timer_id.to_string().as_str());
714
- let core = build_fake_core(wfid, t, hist_batches);
717
+ let core = build_fake_worker(wfid, t, hist_batches);
715
718
 
716
719
  poll_and_reply(
717
720
  &core,
@@ -742,7 +745,7 @@ async fn two_signals(hist_batches: &'static [usize]) {
742
745
  let wfid = "fake_wf_id";
743
746
 
744
747
  let t = canned_histories::two_signals("sig1", "sig2");
745
- let core = build_fake_core(wfid, t, hist_batches);
748
+ let core = build_fake_worker(wfid, t, hist_batches);
746
749
 
747
750
  poll_and_reply(
748
751
  &core,
@@ -786,14 +789,13 @@ async fn workflow_failures_only_reported_once() {
786
789
  wf_id: wfid.to_string(),
787
790
  hist,
788
791
  response_batches: response_batches.into_iter().map(Into::into).collect(),
789
- task_q: TEST_Q.to_owned(),
790
792
  }],
791
793
  true,
792
794
  // We should only call the server to say we failed twice (once after each success)
793
795
  Some(2),
794
796
  );
795
797
  let omap = mocks.outstanding_task_map.clone();
796
- let core = mock_core(mocks);
798
+ let core = mock_worker(mocks);
797
799
 
798
800
  poll_and_reply_clears_outstanding_evicts(
799
801
  &core,
@@ -835,13 +837,11 @@ async fn max_concurrent_wft_respected() {
835
837
  wf_id: "wf1".to_string(),
836
838
  hist: t1,
837
839
  response_batches: vec![ResponseType::AllHistory],
838
- task_q: TEST_Q.to_string(),
839
840
  },
840
841
  FakeWfResponses {
841
842
  wf_id: "wf2".to_string(),
842
843
  hist: t2,
843
844
  response_batches: vec![ResponseType::AllHistory],
844
- task_q: TEST_Q.to_string(),
845
845
  },
846
846
  ],
847
847
  true,
@@ -850,30 +850,29 @@ async fn max_concurrent_wft_respected() {
850
850
  let mut mock = build_mock_pollers(mh);
851
851
  // Limit the core to two outstanding workflow tasks, hence we should only see polling
852
852
  // happen twice, since we will not actually finish the two workflows
853
- mock.worker_cfg(TEST_Q, |cfg| {
853
+ mock.worker_cfg(|cfg| {
854
854
  cfg.max_cached_workflows = 2;
855
855
  cfg.max_outstanding_workflow_tasks = 2;
856
856
  });
857
- let core = mock_core(mock);
857
+ let core = mock_worker(mock);
858
858
 
859
859
  // Poll twice in a row before completing -- we should be at limit
860
- let r1 = core.poll_workflow_activation(TEST_Q).await.unwrap();
860
+ let r1 = core.poll_workflow_activation().await.unwrap();
861
861
  let r1_run_id = r1.run_id.clone();
862
- let r2 = core.poll_workflow_activation(TEST_Q).await.unwrap();
862
+ let r2 = core.poll_workflow_activation().await.unwrap();
863
863
  // Now we immediately poll for new work, and complete the r1 activation. The poll must not
864
864
  // unblock until the completion goes through.
865
865
  let last_finisher = AtomicUsize::new(0);
866
866
  let (_, mut r1) = tokio::join! {
867
867
  async {
868
868
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
869
- TEST_Q,
870
869
  r1.run_id,
871
870
  start_timer_cmd(1, Duration::from_secs(1)))
872
871
  ).await.unwrap();
873
872
  last_finisher.store(1, Ordering::SeqCst);
874
873
  },
875
874
  async {
876
- let r = core.poll_workflow_activation(TEST_Q).await.unwrap();
875
+ let r = core.poll_workflow_activation().await.unwrap();
877
876
  last_finisher.store(2, Ordering::SeqCst);
878
877
  r
879
878
  }
@@ -884,38 +883,35 @@ async fn max_concurrent_wft_respected() {
884
883
  // Since we never did anything with r2, all subsequent activations should be for wf1
885
884
  for i in 2..=20 {
886
885
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
887
- TEST_Q,
888
886
  r1.run_id,
889
887
  start_timer_cmd(i, Duration::from_secs(1)),
890
888
  ))
891
889
  .await
892
890
  .unwrap();
893
- r1 = core.poll_workflow_activation(TEST_Q).await.unwrap();
891
+ r1 = core.poll_workflow_activation().await.unwrap();
894
892
  assert_eq!(r1.run_id, r1_run_id);
895
893
  }
896
894
  // Finish the tasks so we can shut down
897
895
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
898
- TEST_Q,
899
896
  r1.run_id,
900
897
  CompleteWorkflowExecution { result: None }.into(),
901
898
  ))
902
899
  .await
903
900
  .unwrap();
904
901
  // Evict r2
905
- core.request_workflow_eviction(TEST_Q, &r2.run_id);
902
+ core.request_workflow_eviction(&r2.run_id);
906
903
  // We have to properly complete the outstanding task (or the mock will be confused why a task
907
904
  // failure was reported)
908
905
  let _ = core
909
906
  .complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
910
- TEST_Q,
911
907
  r2.run_id,
912
908
  start_timer_cmd(1, Duration::from_secs(1)),
913
909
  ))
914
910
  .await;
915
911
  // Get and complete eviction
916
- let r2 = core.poll_workflow_activation(TEST_Q).await.unwrap();
912
+ let r2 = core.poll_workflow_activation().await.unwrap();
917
913
  let _ = core
918
- .complete_workflow_activation(WorkflowActivationCompletion::empty(TEST_Q, r2.run_id))
914
+ .complete_workflow_activation(WorkflowActivationCompletion::empty(r2.run_id))
919
915
  .await;
920
916
  core.shutdown().await;
921
917
  }
@@ -925,7 +921,7 @@ async fn max_concurrent_wft_respected() {
925
921
  async fn activity_not_canceled_on_replay_repro(hist_batches: &'static [usize]) {
926
922
  let wfid = "fake_wf_id";
927
923
  let t = canned_histories::unsent_at_cancel_repro();
928
- let core = build_fake_core(wfid, t, hist_batches);
924
+ let core = build_fake_worker(wfid, t, hist_batches);
929
925
  let activity_id = 1;
930
926
 
931
927
  poll_and_reply(
@@ -971,7 +967,7 @@ async fn activity_not_canceled_on_replay_repro(hist_batches: &'static [usize]) {
971
967
  async fn activity_not_canceled_when_also_completed_repro(hist_batches: &'static [usize]) {
972
968
  let wfid = "fake_wf_id";
973
969
  let t = canned_histories::cancel_not_sent_when_also_complete_repro();
974
- let core = build_fake_core(wfid, t, hist_batches);
970
+ let core = build_fake_worker(wfid, t, hist_batches);
975
971
  let activity_id = 1;
976
972
 
977
973
  poll_and_reply(
@@ -1020,45 +1016,40 @@ async fn lots_of_workflows() {
1020
1016
  wf_id,
1021
1017
  hist,
1022
1018
  response_batches: vec![1.into(), 2.into()],
1023
- task_q: TEST_Q.to_owned(),
1024
1019
  }
1025
1020
  });
1026
1021
  let mock = build_multihist_mock_sg(hists, false, None);
1027
- let core = &mock_core(mock);
1022
+ let worker = &mock_worker(mock);
1028
1023
 
1029
1024
  fanout_tasks(5, |_| async move {
1030
- while let Ok(wft) = core.poll_workflow_activation(TEST_Q).await {
1025
+ while let Ok(wft) = worker.poll_workflow_activation().await {
1031
1026
  let job = &wft.jobs[0];
1032
1027
  let reply = match job.variant {
1033
1028
  Some(workflow_activation_job::Variant::StartWorkflow(_)) => {
1034
1029
  start_timer_cmd(1, Duration::from_secs(1))
1035
1030
  }
1036
1031
  Some(workflow_activation_job::Variant::RemoveFromCache(_)) => {
1037
- core.complete_workflow_activation(WorkflowActivationCompletion::empty(
1038
- TEST_Q, wft.run_id,
1039
- ))
1040
- .await
1041
- .unwrap();
1032
+ worker
1033
+ .complete_workflow_activation(WorkflowActivationCompletion::empty(
1034
+ wft.run_id,
1035
+ ))
1036
+ .await
1037
+ .unwrap();
1042
1038
  continue;
1043
1039
  }
1044
1040
  _ => CompleteWorkflowExecution { result: None }.into(),
1045
1041
  };
1046
- core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
1047
- TEST_Q, wft.run_id, reply,
1048
- ))
1049
- .await
1050
- .unwrap();
1042
+ worker
1043
+ .complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
1044
+ wft.run_id, reply,
1045
+ ))
1046
+ .await
1047
+ .unwrap();
1051
1048
  }
1052
1049
  })
1053
1050
  .await;
1054
- assert_eq!(
1055
- core.workers
1056
- .get(TEST_Q)
1057
- .unwrap()
1058
- .outstanding_workflow_tasks(),
1059
- 0
1060
- );
1061
- core.shutdown().await;
1051
+ assert_eq!(worker.outstanding_workflow_tasks(), 0);
1052
+ worker.shutdown().await;
1062
1053
  }
1063
1054
 
1064
1055
  #[rstest(hist_batches, case::incremental(&[1, 2]), case::replay(&[2]))]
@@ -1066,7 +1057,7 @@ async fn lots_of_workflows() {
1066
1057
  async fn wft_timeout_repro(hist_batches: &'static [usize]) {
1067
1058
  let wfid = "fake_wf_id";
1068
1059
  let t = canned_histories::wft_timeout_repro();
1069
- let core = build_fake_core(wfid, t, hist_batches);
1060
+ let core = build_fake_worker(wfid, t, hist_batches);
1070
1061
  let activity_id = 1;
1071
1062
 
1072
1063
  poll_and_reply(
@@ -1105,23 +1096,22 @@ async fn wft_timeout_repro(hist_batches: &'static [usize]) {
1105
1096
  async fn complete_after_eviction() {
1106
1097
  let wfid = "fake_wf_id";
1107
1098
  let t = canned_histories::single_timer("1");
1108
- let mut mock = mock_gateway();
1099
+ let mut mock = mock_workflow_client();
1109
1100
  mock.expect_complete_workflow_task().times(0);
1110
1101
  let mock = single_hist_mock_sg(wfid, t, &[2], mock, true);
1111
- let core = mock_core(mock);
1102
+ let core = mock_worker(mock);
1112
1103
 
1113
- let activation = core.poll_workflow_activation(TEST_Q).await.unwrap();
1104
+ let activation = core.poll_workflow_activation().await.unwrap();
1114
1105
  // We just got start workflow, immediately evict
1115
- core.request_workflow_eviction(TEST_Q, &activation.run_id);
1106
+ core.request_workflow_eviction(&activation.run_id);
1116
1107
  // Original task must be completed before we get the eviction
1117
1108
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
1118
- TEST_Q,
1119
1109
  activation.run_id,
1120
1110
  start_timer_cmd(1, Duration::from_secs(1)),
1121
1111
  ))
1122
1112
  .await
1123
1113
  .unwrap();
1124
- let eviction_activation = core.poll_workflow_activation(TEST_Q).await.unwrap();
1114
+ let eviction_activation = core.poll_workflow_activation().await.unwrap();
1125
1115
  assert_matches!(
1126
1116
  eviction_activation.jobs.as_slice(),
1127
1117
  [
@@ -1135,7 +1125,6 @@ async fn complete_after_eviction() {
1135
1125
  );
1136
1126
  // Complete the activation containing the eviction, the way we normally would have
1137
1127
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
1138
- TEST_Q,
1139
1128
  eviction_activation.run_id,
1140
1129
  vec![CompleteWorkflowExecution { result: None }.into()],
1141
1130
  ))
@@ -1150,19 +1139,18 @@ async fn sends_appropriate_sticky_task_queue_responses() {
1150
1139
  // include the information that tells the server to enqueue the next task on a sticky queue.
1151
1140
  let wfid = "fake_wf_id";
1152
1141
  let t = canned_histories::single_timer("1");
1153
- let mut mock = mock_gateway();
1142
+ let mut mock = mock_workflow_client();
1154
1143
  mock.expect_complete_workflow_task()
1155
1144
  .withf(|comp| comp.sticky_attributes.is_some())
1156
1145
  .times(1)
1157
1146
  .returning(|_| Ok(Default::default()));
1158
1147
  mock.expect_complete_workflow_task().times(0);
1159
1148
  let mut mock = single_hist_mock_sg(wfid, t, &[1], mock, false);
1160
- mock.worker_cfg(TEST_Q, |wc| wc.max_cached_workflows = 10);
1161
- let core = mock_core(mock);
1149
+ mock.worker_cfg(|wc| wc.max_cached_workflows = 10);
1150
+ let core = mock_worker(mock);
1162
1151
 
1163
- let activation = core.poll_workflow_activation(TEST_Q).await.unwrap();
1152
+ let activation = core.poll_workflow_activation().await.unwrap();
1164
1153
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
1165
- TEST_Q,
1166
1154
  activation.run_id,
1167
1155
  start_timer_cmd(1, Duration::from_secs(1)),
1168
1156
  ))
@@ -1175,19 +1163,18 @@ async fn sends_appropriate_sticky_task_queue_responses() {
1175
1163
  async fn new_server_work_while_eviction_outstanding_doesnt_overwrite_activation() {
1176
1164
  let wfid = "fake_wf_id";
1177
1165
  let t = canned_histories::single_timer("1");
1178
- let mock = single_hist_mock_sg(wfid, t, &[1, 2], mock_gateway(), false);
1179
- let core = mock_core(mock);
1166
+ let mock = single_hist_mock_sg(wfid, t, &[1, 2], mock_workflow_client(), false);
1167
+ let core = mock_worker(mock);
1180
1168
 
1181
1169
  // Poll for and complete first workflow task
1182
- let activation = core.poll_workflow_activation(TEST_Q).await.unwrap();
1170
+ let activation = core.poll_workflow_activation().await.unwrap();
1183
1171
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
1184
- TEST_Q,
1185
1172
  activation.run_id,
1186
1173
  start_timer_cmd(1, Duration::from_secs(1)),
1187
1174
  ))
1188
1175
  .await
1189
1176
  .unwrap();
1190
- let eviction_activation = core.poll_workflow_activation(TEST_Q).await.unwrap();
1177
+ let eviction_activation = core.poll_workflow_activation().await.unwrap();
1191
1178
  assert_matches!(
1192
1179
  eviction_activation.jobs.as_slice(),
1193
1180
  [WorkflowActivationJob {
@@ -1196,7 +1183,7 @@ async fn new_server_work_while_eviction_outstanding_doesnt_overwrite_activation(
1196
1183
  );
1197
1184
  // Poll again. We should not overwrite the eviction with the new work from the server to fire
1198
1185
  // the timer, so polling will try again, and run into the mock being out of responses.
1199
- let act = core.poll_workflow_activation(TEST_Q).await;
1186
+ let act = core.poll_workflow_activation().await;
1200
1187
  assert_matches!(act, Err(PollWfError::TonicError(err))
1201
1188
  if err.message() == NO_MORE_WORK_ERROR_MSG);
1202
1189
  core.shutdown().await;
@@ -1237,22 +1224,21 @@ async fn buffered_work_drained_on_shutdown() {
1237
1224
  ))
1238
1225
  .take(50),
1239
1226
  );
1240
- let mut mock = mock_gateway();
1227
+ let mut mock = mock_workflow_client();
1241
1228
  mock.expect_complete_workflow_task()
1242
1229
  .returning(|_| Ok(RespondWorkflowTaskCompletedResponse::default()));
1243
- let mut mock = MocksHolder::from_gateway_with_responses(mock, tasks, []);
1230
+ let mut mock = MocksHolder::from_client_with_responses(mock, tasks, []);
1244
1231
  // Cache on to avoid being super repetitive
1245
- mock.worker_cfg(TEST_Q, |wc| wc.max_cached_workflows = 10);
1246
- let core = &mock_core(mock);
1232
+ mock.worker_cfg(|wc| wc.max_cached_workflows = 10);
1233
+ let core = &mock_worker(mock);
1247
1234
 
1248
1235
  // Poll for first WFT
1249
- let act1 = core.poll_workflow_activation(TEST_Q).await.unwrap();
1236
+ let act1 = core.poll_workflow_activation().await.unwrap();
1250
1237
  let poll_fut = async move {
1251
1238
  // Now poll again, which will start spinning, and buffer the next WFT with timer fired in it
1252
1239
  // - it won't stop spinning until the first task is complete
1253
- let t = core.poll_workflow_activation(TEST_Q).await.unwrap();
1240
+ let t = core.poll_workflow_activation().await.unwrap();
1254
1241
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
1255
- TEST_Q,
1256
1242
  t.run_id,
1257
1243
  vec![CompleteWorkflowExecution { result: None }.into()],
1258
1244
  ))
@@ -1261,7 +1247,6 @@ async fn buffered_work_drained_on_shutdown() {
1261
1247
  };
1262
1248
  let complete_first = async move {
1263
1249
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
1264
- TEST_Q,
1265
1250
  act1.run_id,
1266
1251
  start_timer_cmd(1, Duration::from_secs(1)),
1267
1252
  ))
@@ -1279,7 +1264,7 @@ async fn buffered_work_drained_on_shutdown() {
1279
1264
  async fn buffering_tasks_doesnt_count_toward_outstanding_max() {
1280
1265
  let wfid = "fake_wf_id";
1281
1266
  let t = canned_histories::single_timer("1");
1282
- let mock = mock_gateway();
1267
+ let mock = mock_workflow_client();
1283
1268
  let mut tasks = VecDeque::new();
1284
1269
  // A way bigger task list than allowed outstanding tasks
1285
1270
  tasks.extend(
@@ -1291,18 +1276,18 @@ async fn buffering_tasks_doesnt_count_toward_outstanding_max() {
1291
1276
  ))
1292
1277
  .take(20),
1293
1278
  );
1294
- let mut mock = MocksHolder::from_gateway_with_responses(mock, tasks, []);
1295
- mock.worker_cfg(TEST_Q, |wc| {
1279
+ let mut mock = MocksHolder::from_client_with_responses(mock, tasks, []);
1280
+ mock.worker_cfg(|wc| {
1296
1281
  wc.max_cached_workflows = 10;
1297
1282
  wc.max_outstanding_workflow_tasks = 5;
1298
1283
  });
1299
- let core = mock_core(mock);
1284
+ let core = mock_worker(mock);
1300
1285
  // Poll for first WFT
1301
- core.poll_workflow_activation(TEST_Q).await.unwrap();
1286
+ core.poll_workflow_activation().await.unwrap();
1302
1287
  // This will error out when the mock runs out of responses. Otherwise it would hang when we
1303
1288
  // hit the max
1304
1289
  assert_matches!(
1305
- core.poll_workflow_activation(TEST_Q).await.unwrap_err(),
1290
+ core.poll_workflow_activation().await.unwrap_err(),
1306
1291
  PollWfError::TonicError(_)
1307
1292
  );
1308
1293
  }
@@ -1315,21 +1300,20 @@ async fn fail_wft_then_recover() {
1315
1300
  t,
1316
1301
  // We need to deliver all of history twice because of eviction
1317
1302
  [ResponseType::AllHistory, ResponseType::AllHistory],
1318
- mock_gateway(),
1303
+ mock_workflow_client(),
1319
1304
  );
1320
1305
  mh.num_expected_fails = Some(1);
1321
1306
  mh.expect_fail_wft_matcher =
1322
1307
  Box::new(|_, cause, _| matches!(cause, WorkflowTaskFailedCause::NonDeterministicError));
1323
1308
  let mut mock = build_mock_pollers(mh);
1324
- mock.worker_cfg(TEST_Q, |wc| {
1309
+ mock.worker_cfg(|wc| {
1325
1310
  wc.max_cached_workflows = 2;
1326
1311
  });
1327
- let core = mock_core(mock);
1312
+ let core = mock_worker(mock);
1328
1313
 
1329
- let act = core.poll_workflow_activation(TEST_Q).await.unwrap();
1314
+ let act = core.poll_workflow_activation().await.unwrap();
1330
1315
  // Start an activity instead of a timer, triggering nondeterminism error
1331
1316
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
1332
- TEST_Q,
1333
1317
  act.run_id.clone(),
1334
1318
  vec![ScheduleActivity {
1335
1319
  activity_id: "fake_activity".to_string(),
@@ -1340,7 +1324,7 @@ async fn fail_wft_then_recover() {
1340
1324
  .await
1341
1325
  .unwrap();
1342
1326
  // We must handle an eviction now
1343
- let evict_act = core.poll_workflow_activation(TEST_Q).await.unwrap();
1327
+ let evict_act = core.poll_workflow_activation().await.unwrap();
1344
1328
  assert_eq!(evict_act.run_id, act.run_id);
1345
1329
  assert_matches!(
1346
1330
  evict_act.jobs.as_slice(),
@@ -1348,23 +1332,19 @@ async fn fail_wft_then_recover() {
1348
1332
  variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
1349
1333
  }]
1350
1334
  );
1351
- core.complete_workflow_activation(WorkflowActivationCompletion::empty(
1352
- TEST_Q,
1353
- evict_act.run_id,
1354
- ))
1355
- .await
1356
- .unwrap();
1335
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(evict_act.run_id))
1336
+ .await
1337
+ .unwrap();
1357
1338
 
1358
1339
  // Workflow starting over, this time issue the right command
1359
- let act = core.poll_workflow_activation(TEST_Q).await.unwrap();
1340
+ let act = core.poll_workflow_activation().await.unwrap();
1360
1341
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
1361
- TEST_Q,
1362
1342
  act.run_id,
1363
1343
  vec![start_timer_cmd(1, Duration::from_secs(1))],
1364
1344
  ))
1365
1345
  .await
1366
1346
  .unwrap();
1367
- let act = core.poll_workflow_activation(TEST_Q).await.unwrap();
1347
+ let act = core.poll_workflow_activation().await.unwrap();
1368
1348
  assert_matches!(
1369
1349
  act.jobs.as_slice(),
1370
1350
  [WorkflowActivationJob {
@@ -1372,7 +1352,6 @@ async fn fail_wft_then_recover() {
1372
1352
  },]
1373
1353
  );
1374
1354
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
1375
- TEST_Q,
1376
1355
  act.run_id,
1377
1356
  vec![CompleteWorkflowExecution { result: None }.into()],
1378
1357
  ))
@@ -1390,15 +1369,19 @@ async fn poll_response_triggers_wf_error() {
1390
1369
  t.add_full_wf_task();
1391
1370
  t.add_workflow_execution_completed();
1392
1371
 
1393
- let mut mh =
1394
- MockPollCfg::from_resp_batches("fake_wf_id", t, [ResponseType::AllHistory], mock_gateway());
1372
+ let mut mh = MockPollCfg::from_resp_batches(
1373
+ "fake_wf_id",
1374
+ t,
1375
+ [ResponseType::AllHistory],
1376
+ mock_workflow_client(),
1377
+ );
1395
1378
  // Since applying the poll response immediately generates an error core will start polling again
1396
1379
  // Rather than panic on bad expectation we want to return the magic "no more work" error
1397
1380
  mh.enforce_correct_number_of_polls = false;
1398
1381
  let mock = build_mock_pollers(mh);
1399
- let core = mock_core(mock);
1382
+ let core = mock_worker(mock);
1400
1383
  // Poll for first WFT, which is immediately an eviction
1401
- let act = core.poll_workflow_activation(TEST_Q).await;
1384
+ let act = core.poll_workflow_activation().await;
1402
1385
  assert_matches!(act, Err(PollWfError::TonicError(err))
1403
1386
  if err.message() == NO_MORE_WORK_ERROR_MSG);
1404
1387
  }
@@ -1419,47 +1402,46 @@ async fn lang_slower_than_wft_timeouts() {
1419
1402
  hist_to_poll_resp(&t, wfid.to_owned(), 1.into(), TEST_Q.to_string()),
1420
1403
  hist_to_poll_resp(&t, wfid.to_owned(), 1.into(), TEST_Q.to_string()),
1421
1404
  ];
1422
- let mut mock = mock_gateway();
1405
+ let mut mock = mock_workflow_client();
1423
1406
  mock.expect_complete_workflow_task()
1424
1407
  .times(1)
1425
1408
  .returning(|_| Err(tonic::Status::not_found("Workflow task not found.")));
1426
1409
  mock.expect_complete_workflow_task()
1427
1410
  .times(1)
1428
1411
  .returning(|_| Ok(Default::default()));
1429
- let mut mock = MocksHolder::from_gateway_with_responses(mock, tasks, []);
1430
- mock.worker_cfg(TEST_Q, |wc| {
1412
+ let mut mock = MocksHolder::from_client_with_responses(mock, tasks, []);
1413
+ mock.worker_cfg(|wc| {
1431
1414
  wc.max_cached_workflows = 2;
1432
1415
  });
1433
- let core = mock_core(mock);
1416
+ let core = mock_worker(mock);
1434
1417
 
1435
- let wf_task = core.poll_workflow_activation(TEST_Q).await.unwrap();
1436
- let poll_until_no_work = core.poll_workflow_activation(TEST_Q).await;
1418
+ let wf_task = core.poll_workflow_activation().await.unwrap();
1419
+ let poll_until_no_work = core.poll_workflow_activation().await;
1437
1420
  assert_matches!(poll_until_no_work, Err(PollWfError::TonicError(err))
1438
1421
  if err.message() == NO_MORE_WORK_ERROR_MSG);
1439
1422
  // This completion runs into a workflow task not found error, since it's completing a stale
1440
1423
  // task.
1441
- core.complete_workflow_activation(WorkflowActivationCompletion::empty(TEST_Q, wf_task.run_id))
1424
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(wf_task.run_id))
1442
1425
  .await
1443
1426
  .unwrap();
1444
1427
  // Now we should get an eviction
1445
- let wf_task = core.poll_workflow_activation(TEST_Q).await.unwrap();
1428
+ let wf_task = core.poll_workflow_activation().await.unwrap();
1446
1429
  assert_matches!(
1447
1430
  wf_task.jobs.as_slice(),
1448
1431
  [WorkflowActivationJob {
1449
1432
  variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
1450
1433
  }]
1451
1434
  );
1452
- core.complete_workflow_activation(WorkflowActivationCompletion::empty(TEST_Q, wf_task.run_id))
1435
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(wf_task.run_id))
1453
1436
  .await
1454
1437
  .unwrap();
1455
1438
  // The last WFT buffered should be applied now
1456
- let start_again = core.poll_workflow_activation(TEST_Q).await.unwrap();
1439
+ let start_again = core.poll_workflow_activation().await.unwrap();
1457
1440
  assert_matches!(
1458
1441
  start_again.jobs[0].variant,
1459
1442
  Some(workflow_activation_job::Variant::StartWorkflow(_))
1460
1443
  );
1461
1444
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
1462
- TEST_Q,
1463
1445
  start_again.run_id,
1464
1446
  vec![CompleteWorkflowExecution { result: None }.into()],
1465
1447
  ))
@@ -1479,14 +1461,13 @@ async fn tries_cancel_of_completed_activity() {
1479
1461
  t.add_activity_task_completed(scheduled_event_id, started_event_id, Default::default());
1480
1462
  t.add_workflow_task_scheduled_and_started();
1481
1463
 
1482
- let mock = mock_gateway();
1464
+ let mock = mock_workflow_client();
1483
1465
  let mut mock = single_hist_mock_sg("fake_wf_id", t, &[1, 2], mock, true);
1484
- mock.worker_cfg(TEST_Q, |cfg| cfg.max_cached_workflows = 1);
1485
- let core = mock_core(mock);
1466
+ mock.worker_cfg(|cfg| cfg.max_cached_workflows = 1);
1467
+ let core = mock_worker(mock);
1486
1468
 
1487
- let activation = core.poll_workflow_activation(TEST_Q).await.unwrap();
1469
+ let activation = core.poll_workflow_activation().await.unwrap();
1488
1470
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
1489
- TEST_Q,
1490
1471
  activation.run_id,
1491
1472
  ScheduleActivity {
1492
1473
  seq: 1,
@@ -1497,7 +1478,7 @@ async fn tries_cancel_of_completed_activity() {
1497
1478
  ))
1498
1479
  .await
1499
1480
  .unwrap();
1500
- let activation = core.poll_workflow_activation(TEST_Q).await.unwrap();
1481
+ let activation = core.poll_workflow_activation().await.unwrap();
1501
1482
  assert_matches!(
1502
1483
  activation.jobs.as_slice(),
1503
1484
  [
@@ -1510,7 +1491,6 @@ async fn tries_cancel_of_completed_activity() {
1510
1491
  ]
1511
1492
  );
1512
1493
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
1513
- TEST_Q,
1514
1494
  activation.run_id,
1515
1495
  vec![
1516
1496
  RequestCancelActivity { seq: 1 }.into(),
@@ -1529,29 +1509,29 @@ async fn failing_wft_doesnt_eat_permit_forever() {
1529
1509
  t.add_by_type(EventType::WorkflowExecutionStarted);
1530
1510
  t.add_workflow_task_scheduled_and_started();
1531
1511
 
1532
- let mock = mock_gateway();
1512
+ let mock = mock_workflow_client();
1533
1513
  let mut mock = single_hist_mock_sg("fake_wf_id", t, [1, 1, 1], mock, true);
1534
- mock.worker_cfg(TEST_Q, |cfg| {
1514
+ mock.worker_cfg(|cfg| {
1535
1515
  cfg.max_cached_workflows = 2;
1536
1516
  cfg.max_outstanding_workflow_tasks = 2;
1537
1517
  });
1538
1518
  let outstanding_mock_tasks = mock.outstanding_task_map.clone();
1539
- let core = mock_core(mock);
1519
+ let worker = mock_worker(mock);
1540
1520
 
1541
1521
  let mut run_id = "".to_string();
1542
1522
  // Fail twice, verifying a permit is eaten. We cannot fail the same run more than twice in a row
1543
1523
  // because we purposefully time out rather than spamming.
1544
1524
  for _ in 1..=2 {
1545
- let activation = core.poll_workflow_activation(TEST_Q).await.unwrap();
1525
+ let activation = worker.poll_workflow_activation().await.unwrap();
1546
1526
  // Issue a nonsense completion that will trigger a WFT failure
1547
- core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
1548
- TEST_Q,
1549
- activation.run_id,
1550
- RequestCancelActivity { seq: 1 }.into(),
1551
- ))
1552
- .await
1553
- .unwrap();
1554
- let activation = core.poll_workflow_activation(TEST_Q).await.unwrap();
1527
+ worker
1528
+ .complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
1529
+ activation.run_id,
1530
+ RequestCancelActivity { seq: 1 }.into(),
1531
+ ))
1532
+ .await
1533
+ .unwrap();
1534
+ let activation = worker.poll_workflow_activation().await.unwrap();
1555
1535
  assert_matches!(
1556
1536
  activation.jobs.as_slice(),
1557
1537
  [WorkflowActivationJob {
@@ -1559,14 +1539,12 @@ async fn failing_wft_doesnt_eat_permit_forever() {
1559
1539
  },]
1560
1540
  );
1561
1541
  run_id = activation.run_id.clone();
1562
- core.complete_workflow_activation(WorkflowActivationCompletion::empty(
1563
- TEST_Q,
1564
- activation.run_id,
1565
- ))
1566
- .await
1567
- .unwrap();
1568
- assert_eq!(core.outstanding_wfts(TEST_Q), 0);
1569
- assert_eq!(core.available_wft_permits(TEST_Q), 2);
1542
+ worker
1543
+ .complete_workflow_activation(WorkflowActivationCompletion::empty(activation.run_id))
1544
+ .await
1545
+ .unwrap();
1546
+ assert_eq!(worker.outstanding_workflow_tasks(), 0);
1547
+ assert_eq!(worker.available_wft_permits(), 2);
1570
1548
  }
1571
1549
  // We should be "out of work" because the mock service thinks we didn't complete the last task,
1572
1550
  // which we didn't, because we don't spam failures. The real server would eventually time out
@@ -1577,91 +1555,86 @@ async fn failing_wft_doesnt_eat_permit_forever() {
1577
1555
  .unwrap()
1578
1556
  .write()
1579
1557
  .remove_by_left(&run_id);
1580
- let activation = core.poll_workflow_activation(TEST_Q).await.unwrap();
1581
- core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
1582
- TEST_Q,
1583
- activation.run_id,
1584
- CompleteWorkflowExecution { result: None }.into(),
1585
- ))
1586
- .await
1587
- .unwrap();
1558
+ let activation = worker.poll_workflow_activation().await.unwrap();
1559
+ worker
1560
+ .complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
1561
+ activation.run_id,
1562
+ CompleteWorkflowExecution { result: None }.into(),
1563
+ ))
1564
+ .await
1565
+ .unwrap();
1588
1566
 
1589
- core.shutdown().await;
1567
+ worker.shutdown().await;
1590
1568
  }
1591
1569
 
1592
1570
  #[tokio::test]
1593
- async fn cache_miss_doesnt_eat_permit_forever() {
1571
+ async fn cache_miss_will_fetch_history() {
1594
1572
  let mut t = TestHistoryBuilder::default();
1595
1573
  t.add_by_type(EventType::WorkflowExecutionStarted);
1596
1574
  t.add_full_wf_task();
1597
1575
  t.add_we_signaled("sig", vec![]);
1598
1576
  t.add_full_wf_task();
1599
1577
  t.add_workflow_execution_completed();
1578
+ let get_exec_resp: GetWorkflowExecutionHistoryResponse = t.get_history_info(2).unwrap().into();
1600
1579
 
1601
1580
  let mut mh = MockPollCfg::from_resp_batches(
1602
1581
  "fake_wf_id",
1603
1582
  t,
1604
- [
1605
- ResponseType::ToTaskNum(1),
1606
- ResponseType::OneTask(2),
1607
- ResponseType::ToTaskNum(1),
1608
- ResponseType::OneTask(2),
1609
- ResponseType::ToTaskNum(1),
1610
- ResponseType::OneTask(2),
1611
- // Last one to complete successfully
1612
- ResponseType::ToTaskNum(1),
1613
- ],
1614
- mock_gateway(),
1583
+ [ResponseType::ToTaskNum(1), ResponseType::OneTask(2)],
1584
+ mock_workflow_client(),
1615
1585
  );
1616
- mh.num_expected_fails = Some(3);
1617
- mh.expect_fail_wft_matcher =
1618
- Box::new(|_, cause, _| matches!(cause, WorkflowTaskFailedCause::ResetStickyTaskQueue));
1586
+ mh.num_expected_fails = Some(0);
1587
+ mh.mock_client
1588
+ .expect_get_workflow_execution_history()
1589
+ .times(1)
1590
+ .returning(move |_, _, _| Ok(get_exec_resp.clone()));
1619
1591
  let mut mock = build_mock_pollers(mh);
1620
- mock.worker_cfg(TEST_Q, |cfg| {
1621
- cfg.max_outstanding_workflow_tasks = 2;
1592
+ mock.worker_cfg(|cfg| {
1593
+ cfg.max_cached_workflows = 1;
1622
1594
  });
1623
- let core = mock_core(mock);
1624
-
1625
- // Spin missing the cache to verify that we don't get stuck
1626
- for _ in 1..=3 {
1627
- // Start
1628
- let activation = core.poll_workflow_activation(TEST_Q).await.unwrap();
1629
- core.complete_workflow_activation(WorkflowActivationCompletion::empty(
1630
- TEST_Q,
1631
- activation.run_id,
1632
- ))
1595
+ let worker = mock_worker(mock);
1596
+
1597
+ let activation = worker.poll_workflow_activation().await.unwrap();
1598
+ assert_matches!(
1599
+ activation.jobs.as_slice(),
1600
+ [WorkflowActivationJob {
1601
+ variant: Some(workflow_activation_job::Variant::StartWorkflow(_)),
1602
+ }]
1603
+ );
1604
+ worker
1605
+ .complete_workflow_activation(WorkflowActivationCompletion::empty(&activation.run_id))
1633
1606
  .await
1634
1607
  .unwrap();
1635
- // Evict
1636
- let activation = core.poll_workflow_activation(TEST_Q).await.unwrap();
1637
- assert_matches!(
1638
- activation.jobs.as_slice(),
1639
- [WorkflowActivationJob {
1640
- variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
1641
- },]
1642
- );
1643
- core.complete_workflow_activation(WorkflowActivationCompletion::empty(
1644
- TEST_Q,
1608
+ // Force an eviction
1609
+ worker.request_wf_eviction(
1610
+ &activation.run_id,
1611
+ "whatever",
1612
+ EvictionReason::LangRequested,
1613
+ );
1614
+ // Handle the eviction, and the restart
1615
+ for _ in 1..=2 {
1616
+ let activation = worker.poll_workflow_activation().await.unwrap();
1617
+ worker
1618
+ .complete_workflow_activation(WorkflowActivationCompletion::empty(activation.run_id))
1619
+ .await
1620
+ .unwrap();
1621
+ }
1622
+ let activation = worker.poll_workflow_activation().await.unwrap();
1623
+ assert_matches!(
1624
+ activation.jobs.as_slice(),
1625
+ [WorkflowActivationJob {
1626
+ variant: Some(workflow_activation_job::Variant::SignalWorkflow(_)),
1627
+ }]
1628
+ );
1629
+ worker
1630
+ .complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
1645
1631
  activation.run_id,
1632
+ CompleteWorkflowExecution { result: None }.into(),
1646
1633
  ))
1647
1634
  .await
1648
1635
  .unwrap();
1649
- assert_eq!(core.outstanding_wfts(TEST_Q), 0);
1650
- assert_eq!(core.available_wft_permits(TEST_Q), 2);
1651
- // When we loop back up, the poll will trigger a cache miss, which we should immediately
1652
- // reply to WFT with failure, and then poll again, which will deliver the from-the-start
1653
- // history
1654
- }
1655
- let activation = core.poll_workflow_activation(TEST_Q).await.unwrap();
1656
- core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
1657
- TEST_Q,
1658
- activation.run_id,
1659
- CompleteWorkflowExecution { result: None }.into(),
1660
- ))
1661
- .await
1662
- .unwrap();
1663
-
1664
- core.shutdown().await;
1636
+ assert_eq!(worker.outstanding_workflow_tasks(), 0);
1637
+ worker.shutdown().await;
1665
1638
  }
1666
1639
 
1667
1640
  /// This test verifies that WFTs which come as replies to completing a WFT are properly delivered
@@ -1682,7 +1655,7 @@ async fn tasks_from_completion_are_delivered() {
1682
1655
  1.into(),
1683
1656
  TEST_Q.to_string(),
1684
1657
  )];
1685
- let mut mock = mock_gateway();
1658
+ let mut mock = mock_workflow_client();
1686
1659
  mock.expect_complete_workflow_task()
1687
1660
  .times(1)
1688
1661
  .returning(move |_| {
@@ -1698,15 +1671,15 @@ async fn tasks_from_completion_are_delivered() {
1698
1671
  mock.expect_complete_workflow_task()
1699
1672
  .times(1)
1700
1673
  .returning(|_| Ok(Default::default()));
1701
- let mut mock = MocksHolder::from_gateway_with_responses(mock, tasks, []);
1702
- mock.worker_cfg(TEST_Q, |wc| wc.max_cached_workflows = 2);
1703
- let core = mock_core(mock);
1674
+ let mut mock = MocksHolder::from_client_with_responses(mock, tasks, []);
1675
+ mock.worker_cfg(|wc| wc.max_cached_workflows = 2);
1676
+ let core = mock_worker(mock);
1704
1677
 
1705
- let wf_task = core.poll_workflow_activation(TEST_Q).await.unwrap();
1706
- core.complete_workflow_activation(WorkflowActivationCompletion::empty(TEST_Q, wf_task.run_id))
1678
+ let wf_task = core.poll_workflow_activation().await.unwrap();
1679
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(wf_task.run_id))
1707
1680
  .await
1708
1681
  .unwrap();
1709
- let wf_task = core.poll_workflow_activation(TEST_Q).await.unwrap();
1682
+ let wf_task = core.poll_workflow_activation().await.unwrap();
1710
1683
  assert_matches!(
1711
1684
  wf_task.jobs.as_slice(),
1712
1685
  [WorkflowActivationJob {
@@ -1714,7 +1687,6 @@ async fn tasks_from_completion_are_delivered() {
1714
1687
  },]
1715
1688
  );
1716
1689
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
1717
- TEST_Q,
1718
1690
  wf_task.run_id,
1719
1691
  vec![CompleteWorkflowExecution { result: None }.into()],
1720
1692
  ))
@@ -1722,3 +1694,46 @@ async fn tasks_from_completion_are_delivered() {
1722
1694
  .unwrap();
1723
1695
  core.shutdown().await;
1724
1696
  }
1697
+
1698
+ #[tokio::test]
1699
+ async fn evict_missing_wf_during_poll_doesnt_eat_permit() {
1700
+ let wfid = "fake_wf_id";
1701
+ let mut t = TestHistoryBuilder::default();
1702
+ t.add_by_type(EventType::WorkflowExecutionStarted);
1703
+ t.add_full_wf_task();
1704
+ t.add_we_signaled("sig", vec![]);
1705
+ t.add_full_wf_task();
1706
+ t.add_workflow_execution_completed();
1707
+
1708
+ let tasks = [hist_to_poll_resp(
1709
+ &t,
1710
+ wfid.to_owned(),
1711
+ // Use a partial task so that we'll fetch history
1712
+ ResponseType::OneTask(2),
1713
+ TEST_Q.to_string(),
1714
+ )];
1715
+ let mut mock = mock_workflow_client();
1716
+ mock.expect_get_workflow_execution_history()
1717
+ .times(1)
1718
+ .returning(move |_, _, _| {
1719
+ Ok(GetWorkflowExecutionHistoryResponse {
1720
+ // Empty history so we error applying it (no jobs)
1721
+ history: Some(History { events: vec![] }),
1722
+ raw_history: vec![],
1723
+ next_page_token: vec![],
1724
+ archived: false,
1725
+ })
1726
+ });
1727
+ let mut mock = MocksHolder::from_client_with_responses(mock, tasks, []);
1728
+ mock.worker_cfg(|wc| {
1729
+ wc.max_cached_workflows = 1;
1730
+ wc.max_outstanding_workflow_tasks = 1;
1731
+ });
1732
+ let core = mock_worker(mock);
1733
+
1734
+ // Should error because mock is out of work
1735
+ assert_matches!(core.poll_workflow_activation().await, Err(_));
1736
+ assert_eq!(core.available_wft_permits(), 1);
1737
+
1738
+ core.shutdown().await;
1739
+ }