@temporalio/core-bridge 1.6.0 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/Cargo.lock +520 -456
  2. package/lib/index.d.ts +8 -6
  3. package/lib/index.js.map +1 -1
  4. package/package.json +8 -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 +2 -2
  11. package/sdk-core/.buildkite/docker/docker-compose.yaml +1 -1
  12. package/sdk-core/.buildkite/pipeline.yml +1 -1
  13. package/sdk-core/.github/workflows/heavy.yml +1 -0
  14. package/sdk-core/README.md +13 -7
  15. package/sdk-core/client/src/lib.rs +27 -9
  16. package/sdk-core/client/src/metrics.rs +17 -8
  17. package/sdk-core/client/src/raw.rs +3 -3
  18. package/sdk-core/core/Cargo.toml +3 -4
  19. package/sdk-core/core/src/abstractions/take_cell.rs +28 -0
  20. package/sdk-core/core/src/abstractions.rs +197 -18
  21. package/sdk-core/core/src/core_tests/activity_tasks.rs +137 -45
  22. package/sdk-core/core/src/core_tests/child_workflows.rs +6 -5
  23. package/sdk-core/core/src/core_tests/determinism.rs +212 -2
  24. package/sdk-core/core/src/core_tests/local_activities.rs +183 -36
  25. package/sdk-core/core/src/core_tests/queries.rs +32 -14
  26. package/sdk-core/core/src/core_tests/workers.rs +8 -5
  27. package/sdk-core/core/src/core_tests/workflow_tasks.rs +340 -51
  28. package/sdk-core/core/src/ephemeral_server/mod.rs +110 -8
  29. package/sdk-core/core/src/internal_flags.rs +141 -0
  30. package/sdk-core/core/src/lib.rs +14 -9
  31. package/sdk-core/core/src/replay/mod.rs +16 -27
  32. package/sdk-core/core/src/telemetry/metrics.rs +69 -35
  33. package/sdk-core/core/src/telemetry/mod.rs +38 -14
  34. package/sdk-core/core/src/telemetry/prometheus_server.rs +19 -13
  35. package/sdk-core/core/src/test_help/mod.rs +65 -13
  36. package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +119 -160
  37. package/sdk-core/core/src/worker/activities/activity_task_poller_stream.rs +89 -0
  38. package/sdk-core/core/src/worker/activities/local_activities.rs +122 -6
  39. package/sdk-core/core/src/worker/activities.rs +347 -173
  40. package/sdk-core/core/src/worker/client/mocks.rs +22 -2
  41. package/sdk-core/core/src/worker/client.rs +18 -2
  42. package/sdk-core/core/src/worker/mod.rs +137 -44
  43. package/sdk-core/core/src/worker/workflow/history_update.rs +132 -51
  44. package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +207 -166
  45. package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +6 -7
  46. package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +6 -7
  47. package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +157 -82
  48. package/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +12 -12
  49. package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +6 -7
  50. package/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +13 -15
  51. package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +170 -60
  52. package/sdk-core/core/src/worker/workflow/machines/mod.rs +24 -16
  53. package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +6 -8
  54. package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +320 -204
  55. package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +10 -13
  56. package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +15 -23
  57. package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +187 -46
  58. package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +237 -111
  59. package/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +13 -13
  60. package/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +10 -6
  61. package/sdk-core/core/src/worker/workflow/managed_run.rs +81 -62
  62. package/sdk-core/core/src/worker/workflow/mod.rs +341 -79
  63. package/sdk-core/core/src/worker/workflow/run_cache.rs +18 -11
  64. package/sdk-core/core/src/worker/workflow/wft_extraction.rs +15 -3
  65. package/sdk-core/core/src/worker/workflow/workflow_stream/saved_wf_inputs.rs +2 -0
  66. package/sdk-core/core/src/worker/workflow/workflow_stream.rs +75 -52
  67. package/sdk-core/core-api/Cargo.toml +0 -1
  68. package/sdk-core/core-api/src/lib.rs +13 -7
  69. package/sdk-core/core-api/src/telemetry.rs +4 -6
  70. package/sdk-core/core-api/src/worker.rs +5 -0
  71. package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +80 -55
  72. package/sdk-core/fsm/rustfsm_trait/src/lib.rs +22 -68
  73. package/sdk-core/histories/ends_empty_wft_complete.bin +0 -0
  74. package/sdk-core/histories/old_change_marker_format.bin +0 -0
  75. package/sdk-core/protos/api_upstream/.github/CODEOWNERS +2 -1
  76. package/sdk-core/protos/api_upstream/Makefile +1 -1
  77. package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +5 -17
  78. package/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +11 -0
  79. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +1 -6
  80. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +6 -6
  81. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +5 -0
  82. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +22 -6
  83. package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +48 -19
  84. package/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +2 -0
  85. package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +3 -0
  86. package/sdk-core/protos/api_upstream/temporal/api/{enums/v1/interaction_type.proto → protocol/v1/message.proto} +29 -11
  87. package/sdk-core/protos/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +63 -0
  88. package/sdk-core/protos/api_upstream/temporal/api/update/v1/message.proto +111 -0
  89. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +59 -28
  90. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +2 -2
  91. package/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +7 -8
  92. package/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +10 -7
  93. package/sdk-core/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +19 -30
  94. package/sdk-core/protos/local/temporal/sdk/core/common/common.proto +1 -0
  95. package/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +1 -0
  96. package/sdk-core/protos/local/temporal/sdk/core/external_data/external_data.proto +8 -0
  97. package/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +65 -60
  98. package/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +85 -84
  99. package/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +9 -3
  100. package/sdk-core/sdk/Cargo.toml +1 -1
  101. package/sdk-core/sdk/src/lib.rs +21 -5
  102. package/sdk-core/sdk/src/workflow_context/options.rs +7 -1
  103. package/sdk-core/sdk/src/workflow_context.rs +24 -17
  104. package/sdk-core/sdk/src/workflow_future.rs +9 -3
  105. package/sdk-core/sdk-core-protos/src/history_builder.rs +114 -89
  106. package/sdk-core/sdk-core-protos/src/history_info.rs +6 -1
  107. package/sdk-core/sdk-core-protos/src/lib.rs +205 -64
  108. package/sdk-core/test-utils/src/canned_histories.rs +106 -296
  109. package/sdk-core/test-utils/src/lib.rs +32 -5
  110. package/sdk-core/tests/heavy_tests.rs +10 -43
  111. package/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +25 -3
  112. package/sdk-core/tests/integ_tests/heartbeat_tests.rs +5 -3
  113. package/sdk-core/tests/integ_tests/metrics_tests.rs +218 -16
  114. package/sdk-core/tests/integ_tests/polling_tests.rs +3 -8
  115. package/sdk-core/tests/integ_tests/queries_tests.rs +4 -2
  116. package/sdk-core/tests/integ_tests/visibility_tests.rs +34 -23
  117. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +97 -81
  118. package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +1 -0
  119. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +1 -0
  120. package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +80 -3
  121. package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +5 -1
  122. package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +1 -0
  123. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +25 -3
  124. package/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +2 -4
  125. package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +30 -0
  126. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +64 -0
  127. package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +1 -0
  128. package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +4 -0
  129. package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +3 -1
  130. package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +7 -2
  131. package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +6 -7
  132. package/sdk-core/tests/integ_tests/workflow_tests.rs +8 -8
  133. package/sdk-core/tests/main.rs +16 -25
  134. package/sdk-core/tests/runner.rs +11 -9
  135. package/src/conversions.rs +14 -8
  136. package/src/runtime.rs +9 -8
  137. package/ts/index.ts +8 -6
  138. package/sdk-core/protos/api_upstream/temporal/api/interaction/v1/message.proto +0 -87
@@ -2,7 +2,7 @@ use crate::{
2
2
  prost_dur,
3
3
  test_help::{
4
4
  build_fake_worker, build_mock_pollers, canned_histories, mock_manual_poller, mock_worker,
5
- MockPollCfg, MockWorkerInputs, MocksHolder, ResponseType,
5
+ MockPollCfg, MockWorkerInputs, MocksHolder, ResponseType, WorkerExt,
6
6
  },
7
7
  worker::client::mocks::mock_workflow_client,
8
8
  PollActivityError, PollWfError,
@@ -144,13 +144,18 @@ async fn can_shutdown_local_act_only_worker_when_act_polling() {
144
144
  .await
145
145
  .unwrap();
146
146
  barrier.wait().await;
147
+ // We need to see workflow poll return shutdown before activity poll will
148
+ assert_matches!(
149
+ worker.poll_workflow_activation().await.unwrap_err(),
150
+ PollWfError::ShutDown
151
+ );
147
152
  assert_matches!(
148
153
  worker.poll_activity_task().await.unwrap_err(),
149
154
  PollActivityError::ShutDown
150
155
  );
151
156
  }
152
157
  );
153
- worker.finalize_shutdown().await;
158
+ worker.drain_pollers_and_shutdown().await;
154
159
  }
155
160
 
156
161
  #[tokio::test]
@@ -190,9 +195,7 @@ async fn complete_with_task_not_found_during_shutdown() {
190
195
  complete_order.borrow_mut().push(1);
191
196
  };
192
197
  tokio::join!(shutdown_fut, poll_fut, complete_fut);
193
- // Shutdown will currently complete first before the actual eviction reply since the
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])
198
+ assert_eq!(&complete_order.into_inner(), &[1, 2, 3])
196
199
  }
197
200
 
198
201
  #[tokio::test]
@@ -16,11 +16,12 @@ 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,
23
23
  };
24
+ use temporal_client::WorkflowOptions;
24
25
  use temporal_sdk::{ActivityOptions, CancellableFuture, WfContext};
25
26
  use temporal_sdk_core_api::{errors::PollWfError, Worker as WorkerTrait};
26
27
  use temporal_sdk_core_protos::{
@@ -33,24 +34,29 @@ use temporal_sdk_core_protos::{
33
34
  workflow_commands::{
34
35
  ActivityCancellationType, CancelTimer, CompleteWorkflowExecution,
35
36
  ContinueAsNewWorkflowExecution, FailWorkflowExecution, RequestCancelActivity,
36
- ScheduleActivity,
37
+ ScheduleActivity, SetPatchMarker,
37
38
  },
38
39
  workflow_completion::WorkflowActivationCompletion,
39
40
  },
40
- default_wes_attribs,
41
+ default_act_sched, default_wes_attribs,
41
42
  temporal::api::{
42
43
  command::v1::command::Attributes,
43
44
  common::v1::{Payload, RetryPolicy},
44
45
  enums::v1::{EventType, WorkflowTaskFailedCause},
45
46
  failure::v1::Failure,
46
- history::v1::{history_event, TimerFiredEventAttributes},
47
+ history::v1::{
48
+ history_event, TimerFiredEventAttributes,
49
+ WorkflowPropertiesModifiedExternallyEventAttributes,
50
+ },
47
51
  workflowservice::v1::{
48
52
  GetWorkflowExecutionHistoryResponse, RespondWorkflowTaskCompletedResponse,
49
53
  },
50
54
  },
51
- DEFAULT_WORKFLOW_TYPE,
55
+ DEFAULT_ACTIVITY_TYPE, DEFAULT_WORKFLOW_TYPE,
56
+ };
57
+ use temporal_sdk_core_test_utils::{
58
+ fanout_tasks, schedule_activity_cmd, start_timer_cmd, WorkerTestHelpers,
52
59
  };
53
- use temporal_sdk_core_test_utils::{fanout_tasks, start_timer_cmd};
54
60
  use tokio::{
55
61
  join,
56
62
  sync::{Barrier, Semaphore},
@@ -120,7 +126,7 @@ async fn single_activity_completion(worker: Worker) {
120
126
  &job_assert!(workflow_activation_job::Variant::StartWorkflow(_)),
121
127
  vec![ScheduleActivity {
122
128
  activity_id: "fake_activity".to_string(),
123
- ..Default::default()
129
+ ..default_act_sched()
124
130
  }
125
131
  .into()],
126
132
  ),
@@ -245,7 +251,7 @@ async fn scheduled_activity_cancellation_try_cancel(hist_batches: &'static [usiz
245
251
  seq: activity_seq,
246
252
  activity_id: activity_id.to_string(),
247
253
  cancellation_type: ActivityCancellationType::TryCancel as i32,
248
- ..Default::default()
254
+ ..default_act_sched()
249
255
  }
250
256
  .into()],
251
257
  ),
@@ -281,7 +287,7 @@ async fn scheduled_activity_timeout(hist_batches: &'static [usize]) {
281
287
  vec![ScheduleActivity {
282
288
  seq: activity_seq,
283
289
  activity_id: activity_id.to_string(),
284
- ..Default::default()
290
+ ..default_act_sched()
285
291
  }
286
292
  .into()],
287
293
  ),
@@ -334,7 +340,7 @@ async fn started_activity_timeout(hist_batches: &'static [usize]) {
334
340
  vec![ScheduleActivity {
335
341
  seq: activity_seq,
336
342
  activity_id: activity_seq.to_string(),
337
- ..Default::default()
343
+ ..default_act_sched()
338
344
  }
339
345
  .into()],
340
346
  ),
@@ -389,7 +395,7 @@ async fn cancelled_activity_timeout(hist_batches: &'static [usize]) {
389
395
  vec![ScheduleActivity {
390
396
  seq: activity_seq,
391
397
  activity_id: activity_id.to_string(),
392
- ..Default::default()
398
+ ..default_act_sched()
393
399
  }
394
400
  .into()],
395
401
  ),
@@ -457,10 +463,10 @@ async fn abandoned_activities_ignore_start_and_complete(hist_batches: &'static [
457
463
  t.add_by_type(EventType::WorkflowExecutionStarted);
458
464
  t.add_full_wf_task();
459
465
  let act_scheduled_event_id = t.add_activity_task_scheduled(activity_id);
460
- let timer_started_event_id = t.add_get_event_id(EventType::TimerStarted, None);
466
+ let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
461
467
  t.add_timer_fired(timer_started_event_id, "1".to_string());
462
468
  t.add_full_wf_task();
463
- let timer_started_event_id = t.add_get_event_id(EventType::TimerStarted, None);
469
+ let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
464
470
  let act_started_event_id = t.add_activity_task_started(act_scheduled_event_id);
465
471
  t.add_activity_task_completed(
466
472
  act_scheduled_event_id,
@@ -476,7 +482,7 @@ async fn abandoned_activities_ignore_start_and_complete(hist_batches: &'static [
476
482
 
477
483
  worker.register_wf(wf_type.to_owned(), |ctx: WfContext| async move {
478
484
  let act_fut = ctx.activity(ActivityOptions {
479
- activity_type: "echo_activity".to_string(),
485
+ activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
480
486
  start_to_close_timeout: Some(Duration::from_secs(5)),
481
487
  cancellation_type: ActivityCancellationType::Abandon,
482
488
  ..Default::default()
@@ -542,7 +548,7 @@ async fn verify_activity_cancellation(
542
548
  seq: activity_seq,
543
549
  activity_id: activity_seq.to_string(),
544
550
  cancellation_type: cancel_type as i32,
545
- ..Default::default()
551
+ ..default_act_sched()
546
552
  }
547
553
  .into()],
548
554
  ),
@@ -610,7 +616,7 @@ async fn verify_activity_cancellation_wait_for_cancellation(activity_id: u32, wo
610
616
  seq: activity_id,
611
617
  activity_id: activity_id.to_string(),
612
618
  cancellation_type: ActivityCancellationType::WaitCancellationCompleted as i32,
613
- ..Default::default()
619
+ ..default_act_sched()
614
620
  }
615
621
  .into()],
616
622
  ),
@@ -947,7 +953,7 @@ async fn activity_not_canceled_on_replay_repro(hist_batches: &'static [usize]) {
947
953
  seq: activity_id,
948
954
  activity_id: activity_id.to_string(),
949
955
  cancellation_type: ActivityCancellationType::TryCancel as i32,
950
- ..Default::default()
956
+ ..default_act_sched()
951
957
  }
952
958
  .into(),
953
959
  start_timer_cmd(1, Duration::from_secs(1)),
@@ -989,9 +995,9 @@ async fn activity_not_canceled_when_also_completed_repro(hist_batches: &'static
989
995
  &job_assert!(workflow_activation_job::Variant::StartWorkflow(_)),
990
996
  vec![ScheduleActivity {
991
997
  seq: activity_id,
992
- activity_id: activity_id.to_string(),
998
+ activity_id: "act-1".to_string(),
993
999
  cancellation_type: ActivityCancellationType::TryCancel as i32,
994
- ..Default::default()
1000
+ ..default_act_sched()
995
1001
  }
996
1002
  .into()],
997
1003
  ),
@@ -1092,7 +1098,7 @@ async fn wft_timeout_repro(hist_batches: &'static [usize]) {
1092
1098
  seq: activity_id,
1093
1099
  activity_id: activity_id.to_string(),
1094
1100
  cancellation_type: ActivityCancellationType::TryCancel as i32,
1095
- ..Default::default()
1101
+ ..default_act_sched()
1096
1102
  }
1097
1103
  .into()],
1098
1104
  ),
@@ -1225,14 +1231,13 @@ async fn buffered_work_drained_on_shutdown() {
1225
1231
  let resp_1 = hist_to_poll_resp(&t, wfid.to_owned(), 1.into()).resp;
1226
1232
  t.add_workflow_task_timed_out();
1227
1233
  t.add_full_wf_task();
1228
- let timer_started_event_id = t.add_get_event_id(EventType::TimerStarted, None);
1229
- t.add(
1230
- EventType::TimerFired,
1231
- history_event::Attributes::TimerFiredEventAttributes(TimerFiredEventAttributes {
1234
+ let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
1235
+ t.add(history_event::Attributes::TimerFiredEventAttributes(
1236
+ TimerFiredEventAttributes {
1232
1237
  started_event_id: timer_started_event_id,
1233
1238
  timer_id: "1".to_string(),
1234
- }),
1235
- );
1239
+ },
1240
+ ));
1236
1241
  t.add_full_wf_task();
1237
1242
  t.add_workflow_execution_completed();
1238
1243
 
@@ -1264,6 +1269,8 @@ async fn buffered_work_drained_on_shutdown() {
1264
1269
  .unwrap();
1265
1270
  };
1266
1271
  let complete_first = async move {
1272
+ // If the first complete is sent too fast, we may not have had a chance to buffer work.
1273
+ tokio::time::sleep(Duration::from_millis(50)).await;
1267
1274
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
1268
1275
  act1.run_id,
1269
1276
  start_timer_cmd(1, Duration::from_secs(1)),
@@ -1272,8 +1279,6 @@ async fn buffered_work_drained_on_shutdown() {
1272
1279
  .unwrap();
1273
1280
  };
1274
1281
  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
1282
  core.shutdown().await;
1278
1283
  });
1279
1284
  }
@@ -1303,7 +1308,7 @@ async fn fail_wft_then_recover() {
1303
1308
  act.run_id.clone(),
1304
1309
  vec![ScheduleActivity {
1305
1310
  activity_id: "fake_activity".to_string(),
1306
- ..Default::default()
1311
+ ..default_act_sched()
1307
1312
  }
1308
1313
  .into()],
1309
1314
  ))
@@ -1355,12 +1360,17 @@ async fn poll_response_triggers_wf_error() {
1355
1360
  t.add_full_wf_task();
1356
1361
  t.add_workflow_execution_completed();
1357
1362
 
1358
- let mh = MockPollCfg::from_resp_batches(
1363
+ let mut mh = MockPollCfg::from_resp_batches(
1359
1364
  "fake_wf_id",
1360
1365
  t,
1361
1366
  [ResponseType::AllHistory],
1362
1367
  mock_workflow_client(),
1363
1368
  );
1369
+ // Fail wft will be called when auto-failing.
1370
+ mh.num_expected_fails = 1;
1371
+ mh.expect_fail_wft_matcher = Box::new(move |_, cause, _| {
1372
+ matches!(cause, WorkflowTaskFailedCause::NonDeterministicError)
1373
+ });
1364
1374
  let mock = build_mock_pollers(mh);
1365
1375
  let core = mock_worker(mock);
1366
1376
  // Poll for first WFT, which is immediately an eviction
@@ -1453,7 +1463,7 @@ async fn tries_cancel_of_completed_activity() {
1453
1463
  ScheduleActivity {
1454
1464
  seq: 1,
1455
1465
  activity_id: "1".to_string(),
1456
- ..Default::default()
1466
+ ..default_act_sched()
1457
1467
  }
1458
1468
  .into(),
1459
1469
  ))
@@ -1953,7 +1963,7 @@ async fn autocompletes_wft_no_work() {
1953
1963
  seq: 1,
1954
1964
  activity_id: activity_id.to_string(),
1955
1965
  cancellation_type: ActivityCancellationType::Abandon as i32,
1956
- ..Default::default()
1966
+ ..default_act_sched()
1957
1967
  }
1958
1968
  .into(),
1959
1969
  ))
@@ -2066,10 +2076,7 @@ async fn continue_as_new_preserves_some_values() {
2066
2076
  let mut mock_client = mock_workflow_client();
2067
2077
  let hist = {
2068
2078
  let mut t = TestHistoryBuilder::default();
2069
- t.add(
2070
- EventType::WorkflowExecutionStarted,
2071
- wes_attrs.clone().into(),
2072
- );
2079
+ t.add(wes_attrs.clone());
2073
2080
  t.add_full_wf_task();
2074
2081
  t
2075
2082
  };
@@ -2113,21 +2120,19 @@ async fn continue_as_new_preserves_some_values() {
2113
2120
  async fn ignorable_events_are_ok(#[values(true, false)] attribs_unset: bool) {
2114
2121
  let mut t = TestHistoryBuilder::default();
2115
2122
  t.add_by_type(EventType::WorkflowExecutionStarted);
2116
- let id = t.add_get_event_id(
2117
- EventType::Unspecified,
2118
- Some(
2119
- history_event::Attributes::WorkflowPropertiesModifiedExternallyEventAttributes(
2120
- Default::default(),
2121
- ),
2122
- ),
2123
- );
2124
- t.modify_event(id, |e| e.worker_may_ignore = true);
2125
- if attribs_unset {
2126
- t.modify_event(id, |e| {
2127
- e.event_type = EventType::WorkflowPropertiesModifiedExternally as i32;
2123
+ let id = t.add(WorkflowPropertiesModifiedExternallyEventAttributes::default());
2124
+ t.modify_event(id, |e| {
2125
+ e.worker_may_ignore = true;
2126
+ // Ignorable events are ignored if we can't interpret the proto of either the event attribs
2127
+ // or proto - otherwise (this is the _may_ part of may ignore), we'll still try to process
2128
+ // it. That processing may ultimately still choose to do nothing, if we want to _explicitly_
2129
+ // ignore it.
2130
+ if attribs_unset {
2128
2131
  e.attributes = None;
2129
- });
2130
- }
2132
+ } else {
2133
+ e.event_type = EventType::Unspecified as i32;
2134
+ }
2135
+ });
2131
2136
  t.add_workflow_task_scheduled_and_started();
2132
2137
 
2133
2138
  let mock = mock_workflow_client();
@@ -2165,7 +2170,7 @@ async fn fetching_to_continue_replay_works() {
2165
2170
  // next page happen.
2166
2171
  fetch_resp.next_page_token = vec![2];
2167
2172
 
2168
- let timer_started_event_id = t.add_get_event_id(EventType::TimerStarted, None);
2173
+ let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
2169
2174
  t.add_timer_fired(timer_started_event_id, "1".to_string());
2170
2175
  t.add_full_wf_task();
2171
2176
  let mut final_fetch_resp: GetWorkflowExecutionHistoryResponse =
@@ -2331,3 +2336,287 @@ async fn ensure_fetching_fail_during_complete_sends_task_failure() {
2331
2336
 
2332
2337
  core.shutdown().await;
2333
2338
  }
2339
+
2340
+ #[tokio::test]
2341
+ async fn lang_internal_flags() {
2342
+ let mut t = TestHistoryBuilder::default();
2343
+ t.add_by_type(EventType::WorkflowExecutionStarted);
2344
+ t.add_full_wf_task();
2345
+ t.set_flags_first_wft(&[], &[1]);
2346
+ t.add_we_signaled("sig1", vec![]);
2347
+ t.add_full_wf_task();
2348
+ t.set_flags_last_wft(&[], &[2]);
2349
+ t.add_we_signaled("sig2", vec![]);
2350
+ t.add_full_wf_task();
2351
+ t.add_workflow_execution_completed();
2352
+
2353
+ let mut mh = MockPollCfg::from_resp_batches(
2354
+ "fake_wf_id",
2355
+ t,
2356
+ [ResponseType::ToTaskNum(2), ResponseType::AllHistory],
2357
+ mock_workflow_client(),
2358
+ );
2359
+ mh.completion_asserts = Some(Box::new(|c| {
2360
+ assert_matches!(c.sdk_metadata.lang_used_flags.as_slice(), &[2]);
2361
+ }));
2362
+ let mut mock = build_mock_pollers(mh);
2363
+ mock.worker_cfg(|wc| wc.max_cached_workflows = 1);
2364
+ let core = mock_worker(mock);
2365
+
2366
+ let act = core.poll_workflow_activation().await.unwrap();
2367
+ assert_matches!(act.available_internal_flags.as_slice(), [1]);
2368
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(act.run_id))
2369
+ .await
2370
+ .unwrap();
2371
+
2372
+ let act = core.poll_workflow_activation().await.unwrap();
2373
+ let mut completion = WorkflowActivationCompletion::empty(act.run_id);
2374
+ completion.add_internal_flags(2);
2375
+ core.complete_workflow_activation(completion).await.unwrap();
2376
+
2377
+ let act = core.poll_workflow_activation().await.unwrap();
2378
+ assert_matches!(act.available_internal_flags.as_slice(), [1, 2]);
2379
+ core.complete_execution(&act.run_id).await;
2380
+ core.shutdown().await;
2381
+ }
2382
+
2383
+ // Verify we send flags to server when they're used
2384
+ #[tokio::test]
2385
+ async fn core_internal_flags() {
2386
+ let mut t = TestHistoryBuilder::default();
2387
+ t.add_by_type(EventType::WorkflowExecutionStarted);
2388
+ t.add_full_wf_task();
2389
+ let act_scheduled_event_id = t.add_activity_task_scheduled("act-id");
2390
+ let act_started_event_id = t.add_activity_task_started(act_scheduled_event_id);
2391
+ t.add_activity_task_completed(
2392
+ act_scheduled_event_id,
2393
+ act_started_event_id,
2394
+ Default::default(),
2395
+ );
2396
+ t.add_full_wf_task();
2397
+ t.add_workflow_execution_completed();
2398
+
2399
+ let mut mh = MockPollCfg::from_resp_batches(
2400
+ "fake_wf_id",
2401
+ t,
2402
+ [ResponseType::ToTaskNum(1), ResponseType::ToTaskNum(2)],
2403
+ mock_workflow_client(),
2404
+ );
2405
+ let first_poll = AtomicBool::new(true);
2406
+ mh.completion_asserts = Some(Box::new(move |c| {
2407
+ if !first_poll.load(Ordering::Acquire) {
2408
+ assert_matches!(c.sdk_metadata.core_used_flags.as_slice(), &[1]);
2409
+ }
2410
+ first_poll.store(false, Ordering::Release);
2411
+ }));
2412
+ let mut mock = build_mock_pollers(mh);
2413
+ mock.worker_cfg(|wc| wc.max_cached_workflows = 1);
2414
+ let core = mock_worker(mock);
2415
+
2416
+ let act = core.poll_workflow_activation().await.unwrap();
2417
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
2418
+ act.run_id,
2419
+ schedule_activity_cmd(
2420
+ 1,
2421
+ "whatever",
2422
+ "act-id",
2423
+ ActivityCancellationType::TryCancel,
2424
+ Duration::from_secs(60),
2425
+ Duration::from_secs(60),
2426
+ ),
2427
+ ))
2428
+ .await
2429
+ .unwrap();
2430
+
2431
+ let act = core.poll_workflow_activation().await.unwrap();
2432
+ core.complete_execution(&act.run_id).await;
2433
+ core.shutdown().await;
2434
+ }
2435
+
2436
+ #[tokio::test]
2437
+ async fn post_terminal_commands_are_discarded() {
2438
+ let mut t = TestHistoryBuilder::default();
2439
+ t.add_by_type(EventType::WorkflowExecutionStarted);
2440
+ t.add_full_wf_task();
2441
+ t.add_workflow_execution_completed();
2442
+
2443
+ let mut mh = MockPollCfg::from_resp_batches(
2444
+ "fake_wf_id",
2445
+ t,
2446
+ [ResponseType::ToTaskNum(1), ResponseType::AllHistory],
2447
+ mock_workflow_client(),
2448
+ );
2449
+ mh.completion_asserts = Some(Box::new(|c| {
2450
+ // Only the complete execution command should actually be sent
2451
+ assert_eq!(c.commands.len(), 1);
2452
+ }));
2453
+ let mut mock = build_mock_pollers(mh);
2454
+ mock.worker_cfg(|wc| wc.max_cached_workflows = 1);
2455
+ let core = mock_worker(mock);
2456
+
2457
+ let act = core.poll_workflow_activation().await.unwrap();
2458
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
2459
+ act.run_id,
2460
+ vec![
2461
+ CompleteWorkflowExecution { result: None }.into(),
2462
+ start_timer_cmd(1, Duration::from_secs(1)),
2463
+ ],
2464
+ ))
2465
+ .await
2466
+ .unwrap();
2467
+
2468
+ // This just ensures applying the complete history w/ the completion command works, though
2469
+ // there's no activation.
2470
+ let act = core.poll_workflow_activation().await;
2471
+ assert_matches!(act.unwrap_err(), PollWfError::ShutDown);
2472
+
2473
+ core.shutdown().await;
2474
+ }
2475
+
2476
+ // Lang expects to always see jobs in this order:
2477
+ // patches, signals, everything else, queries
2478
+ #[tokio::test]
2479
+ async fn jobs_are_in_appropriate_order() {
2480
+ let p1 = "patchy-mc-patchface";
2481
+ let p2 = "enchi-the-kitty";
2482
+ let mut t = TestHistoryBuilder::default();
2483
+ t.add_by_type(EventType::WorkflowExecutionStarted);
2484
+ t.add_full_wf_task();
2485
+ t.add_has_change_marker(p1, false);
2486
+ let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
2487
+ t.add_timer_fired(timer_started_event_id, "1".to_string());
2488
+ t.add_we_signaled("yummy-salmon", vec![]);
2489
+ t.add_full_wf_task();
2490
+ t.add_has_change_marker(p2, false);
2491
+ t.add_workflow_execution_completed();
2492
+
2493
+ let mh = MockPollCfg::from_resp_batches(
2494
+ "fake_wf_id",
2495
+ t,
2496
+ [ResponseType::AllHistory],
2497
+ mock_workflow_client(),
2498
+ );
2499
+ let mut mock = build_mock_pollers(mh);
2500
+ mock.worker_cfg(|wc| wc.max_cached_workflows = 1);
2501
+ let core = mock_worker(mock);
2502
+
2503
+ let act = core.poll_workflow_activation().await.unwrap();
2504
+ // Patch notifications always come first
2505
+ assert_matches!(
2506
+ act.jobs[0].variant.as_ref().unwrap(),
2507
+ workflow_activation_job::Variant::NotifyHasPatch(_)
2508
+ );
2509
+ assert_matches!(
2510
+ act.jobs[1].variant.as_ref().unwrap(),
2511
+ workflow_activation_job::Variant::StartWorkflow(_)
2512
+ );
2513
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
2514
+ act.run_id,
2515
+ vec![
2516
+ SetPatchMarker {
2517
+ patch_id: p1.to_string(),
2518
+ deprecated: false,
2519
+ }
2520
+ .into(),
2521
+ start_timer_cmd(1, Duration::from_secs(1)),
2522
+ ],
2523
+ ))
2524
+ .await
2525
+ .unwrap();
2526
+ let act = core.poll_workflow_activation().await.unwrap();
2527
+ assert_matches!(
2528
+ act.jobs[0].variant.as_ref().unwrap(),
2529
+ workflow_activation_job::Variant::NotifyHasPatch(_)
2530
+ );
2531
+ assert_matches!(
2532
+ act.jobs[1].variant.as_ref().unwrap(),
2533
+ workflow_activation_job::Variant::SignalWorkflow(_)
2534
+ );
2535
+ assert_matches!(
2536
+ act.jobs[2].variant.as_ref().unwrap(),
2537
+ workflow_activation_job::Variant::FireTimer(_)
2538
+ );
2539
+ }
2540
+
2541
+ #[rstest]
2542
+ #[tokio::test]
2543
+ async fn history_length_with_fail_and_timeout(
2544
+ #[values(true, false)] use_cache: bool,
2545
+ #[values(1, 2, 3)] history_responses_case: u8,
2546
+ ) {
2547
+ let wfid = "fake_wf_id";
2548
+ let mut t = TestHistoryBuilder::default();
2549
+ t.add_by_type(EventType::WorkflowExecutionStarted);
2550
+ t.add_full_wf_task();
2551
+ let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
2552
+ t.add_timer_fired(timer_started_event_id, "1".to_string());
2553
+ t.add_workflow_task_scheduled_and_started();
2554
+ t.add_workflow_task_failed_with_failure(WorkflowTaskFailedCause::Unspecified, "ahh".into());
2555
+ t.add_workflow_task_scheduled_and_started();
2556
+ t.add_workflow_task_timed_out();
2557
+ t.add_full_wf_task();
2558
+ let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
2559
+ t.add_timer_fired(timer_started_event_id, "2".to_string());
2560
+ t.add_full_wf_task();
2561
+ t.add_workflow_execution_completed();
2562
+
2563
+ let mut mock_client = mock_workflow_client();
2564
+ let history_responses = match history_responses_case {
2565
+ 1 => vec![ResponseType::AllHistory],
2566
+ 2 => vec![
2567
+ ResponseType::ToTaskNum(1),
2568
+ ResponseType::ToTaskNum(2),
2569
+ ResponseType::AllHistory,
2570
+ ],
2571
+ 3 => {
2572
+ let mut needs_fetch = hist_to_poll_resp(&t, wfid, ResponseType::ToTaskNum(2)).resp;
2573
+ needs_fetch.next_page_token = vec![1];
2574
+ // Truncate the history a bit in order to force incomplete WFT
2575
+ needs_fetch.history.as_mut().unwrap().events.truncate(6);
2576
+ let needs_fetch_resp = ResponseType::Raw(needs_fetch);
2577
+ let mut empty_fetch_resp: GetWorkflowExecutionHistoryResponse =
2578
+ t.get_history_info(1).unwrap().into();
2579
+ empty_fetch_resp.history.as_mut().unwrap().events = vec![];
2580
+ mock_client
2581
+ .expect_get_workflow_execution_history()
2582
+ .returning(move |_, _, _| Ok(empty_fetch_resp.clone()))
2583
+ .times(1);
2584
+ vec![
2585
+ ResponseType::ToTaskNum(1),
2586
+ needs_fetch_resp,
2587
+ ResponseType::ToTaskNum(2),
2588
+ ResponseType::AllHistory,
2589
+ ]
2590
+ }
2591
+ _ => unreachable!(),
2592
+ };
2593
+
2594
+ let mut mh = MockPollCfg::from_resp_batches(wfid, t, history_responses, mock_client);
2595
+ if history_responses_case == 3 {
2596
+ // Expect the failed pagination fetch
2597
+ mh.num_expected_fails = 1;
2598
+ }
2599
+ let mut worker = mock_sdk_cfg(mh, |wc| {
2600
+ if use_cache {
2601
+ wc.max_cached_workflows = 1;
2602
+ }
2603
+ });
2604
+ worker.register_wf(DEFAULT_WORKFLOW_TYPE, |ctx: WfContext| async move {
2605
+ assert_eq!(ctx.history_length(), 3);
2606
+ ctx.timer(Duration::from_secs(1)).await;
2607
+ assert_eq!(ctx.history_length(), 14);
2608
+ ctx.timer(Duration::from_secs(1)).await;
2609
+ assert_eq!(ctx.history_length(), 19);
2610
+ Ok(().into())
2611
+ });
2612
+ worker
2613
+ .submit_wf(
2614
+ wfid.to_owned(),
2615
+ DEFAULT_WORKFLOW_TYPE.to_owned(),
2616
+ vec![],
2617
+ WorkflowOptions::default(),
2618
+ )
2619
+ .await
2620
+ .unwrap();
2621
+ worker.run_until_done().await.unwrap();
2622
+ }