@temporalio/core-bridge 1.11.6 → 1.11.8

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 (191) hide show
  1. package/Cargo.lock +902 -468
  2. package/package.json +3 -3
  3. package/releases/aarch64-apple-darwin/index.node +0 -0
  4. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  5. package/releases/x86_64-apple-darwin/index.node +0 -0
  6. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  7. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  8. package/sdk-core/.cargo/config.toml +5 -0
  9. package/sdk-core/.github/workflows/per-pr.yml +59 -5
  10. package/sdk-core/Cargo.toml +3 -2
  11. package/sdk-core/client/Cargo.toml +3 -3
  12. package/sdk-core/client/src/lib.rs +154 -161
  13. package/sdk-core/client/src/metrics.rs +15 -8
  14. package/sdk-core/client/src/proxy.rs +1 -1
  15. package/sdk-core/client/src/raw.rs +176 -33
  16. package/sdk-core/client/src/retry.rs +102 -465
  17. package/sdk-core/client/src/worker_registry/mod.rs +2 -2
  18. package/sdk-core/client/src/workflow_handle/mod.rs +19 -1
  19. package/sdk-core/core/Cargo.toml +12 -14
  20. package/sdk-core/core/benches/workflow_replay.rs +1 -1
  21. package/sdk-core/core/src/abstractions.rs +2 -2
  22. package/sdk-core/core/src/core_tests/activity_tasks.rs +99 -46
  23. package/sdk-core/core/src/core_tests/child_workflows.rs +68 -9
  24. package/sdk-core/core/src/core_tests/determinism.rs +2 -2
  25. package/sdk-core/core/src/core_tests/local_activities.rs +20 -33
  26. package/sdk-core/core/src/core_tests/mod.rs +7 -8
  27. package/sdk-core/core/src/core_tests/queries.rs +79 -79
  28. package/sdk-core/core/src/core_tests/replay_flag.rs +5 -5
  29. package/sdk-core/core/src/core_tests/updates.rs +6 -6
  30. package/sdk-core/core/src/core_tests/workers.rs +19 -22
  31. package/sdk-core/core/src/core_tests/workflow_cancels.rs +3 -3
  32. package/sdk-core/core/src/core_tests/workflow_tasks.rs +154 -106
  33. package/sdk-core/core/src/ephemeral_server/mod.rs +66 -10
  34. package/sdk-core/core/src/internal_flags.rs +103 -12
  35. package/sdk-core/core/src/lib.rs +21 -13
  36. package/sdk-core/core/src/pollers/mod.rs +200 -6
  37. package/sdk-core/core/src/pollers/poll_buffer.rs +32 -8
  38. package/sdk-core/core/src/protosext/mod.rs +7 -7
  39. package/sdk-core/core/src/protosext/protocol_messages.rs +2 -2
  40. package/sdk-core/core/src/replay/mod.rs +8 -9
  41. package/sdk-core/core/src/retry_logic.rs +8 -6
  42. package/sdk-core/core/src/telemetry/log_export.rs +4 -4
  43. package/sdk-core/core/src/telemetry/metrics.rs +111 -25
  44. package/sdk-core/core/src/telemetry/mod.rs +11 -4
  45. package/sdk-core/core/src/telemetry/otel.rs +108 -144
  46. package/sdk-core/core/src/telemetry/prometheus_server.rs +1 -4
  47. package/sdk-core/core/src/test_help/mod.rs +27 -21
  48. package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +7 -5
  49. package/sdk-core/core/src/worker/activities/local_activities.rs +9 -9
  50. package/sdk-core/core/src/worker/activities.rs +34 -46
  51. package/sdk-core/core/src/worker/client/mocks.rs +24 -2
  52. package/sdk-core/core/src/worker/client.rs +169 -33
  53. package/sdk-core/core/src/worker/mod.rs +132 -56
  54. package/sdk-core/core/src/worker/nexus.rs +410 -0
  55. package/sdk-core/core/src/worker/tuner/resource_based.rs +27 -5
  56. package/sdk-core/core/src/worker/tuner.rs +29 -2
  57. package/sdk-core/core/src/worker/workflow/driven_workflow.rs +8 -3
  58. package/sdk-core/core/src/worker/workflow/history_update.rs +5 -8
  59. package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +83 -87
  60. package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +38 -38
  61. package/sdk-core/core/src/worker/workflow/machines/cancel_nexus_op_state_machine.rs +117 -0
  62. package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +8 -18
  63. package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +114 -108
  64. package/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +16 -31
  65. package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +7 -14
  66. package/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +8 -15
  67. package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +34 -75
  68. package/sdk-core/core/src/worker/workflow/machines/mod.rs +26 -48
  69. package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +10 -17
  70. package/sdk-core/core/src/worker/workflow/machines/nexus_operation_state_machine.rs +543 -0
  71. package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +22 -31
  72. package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +53 -51
  73. package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +40 -45
  74. package/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +2 -2
  75. package/sdk-core/core/src/worker/workflow/machines/update_state_machine.rs +8 -10
  76. package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +24 -30
  77. package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +182 -116
  78. package/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +4 -8
  79. package/sdk-core/core/src/worker/workflow/managed_run.rs +75 -45
  80. package/sdk-core/core/src/worker/workflow/mod.rs +104 -55
  81. package/sdk-core/core/src/worker/workflow/run_cache.rs +23 -4
  82. package/sdk-core/core/src/worker/workflow/wft_extraction.rs +4 -4
  83. package/sdk-core/core/src/worker/workflow/wft_poller.rs +3 -3
  84. package/sdk-core/core/src/worker/workflow/workflow_stream.rs +32 -13
  85. package/sdk-core/core-api/Cargo.toml +2 -3
  86. package/sdk-core/core-api/src/errors.rs +22 -20
  87. package/sdk-core/core-api/src/lib.rs +24 -5
  88. package/sdk-core/core-api/src/telemetry/metrics.rs +27 -1
  89. package/sdk-core/core-api/src/telemetry.rs +37 -3
  90. package/sdk-core/core-api/src/worker.rs +36 -3
  91. package/sdk-core/docker/docker-compose-ci.yaml +25 -0
  92. package/sdk-core/etc/otel-collector-ci.yaml +36 -0
  93. package/sdk-core/etc/otel-collector-config.yaml +3 -3
  94. package/sdk-core/etc/prometheus.yaml +1 -1
  95. package/sdk-core/fsm/Cargo.toml +1 -1
  96. package/sdk-core/fsm/rustfsm_procmacro/Cargo.toml +1 -1
  97. package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +3 -4
  98. package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +1 -1
  99. package/sdk-core/fsm/rustfsm_trait/Cargo.toml +1 -1
  100. package/sdk-core/sdk/Cargo.toml +1 -2
  101. package/sdk-core/sdk/src/activity_context.rs +1 -1
  102. package/sdk-core/sdk/src/interceptors.rs +1 -1
  103. package/sdk-core/sdk/src/lib.rs +126 -54
  104. package/sdk-core/sdk/src/workflow_context/options.rs +184 -74
  105. package/sdk-core/sdk/src/workflow_context.rs +193 -79
  106. package/sdk-core/sdk/src/workflow_future.rs +151 -131
  107. package/sdk-core/sdk-core-protos/Cargo.toml +3 -4
  108. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/VERSION +1 -1
  109. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/account/v1/message.proto +46 -0
  110. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/request_response.proto +254 -5
  111. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/service.proto +108 -2
  112. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/identity/v1/message.proto +94 -15
  113. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/namespace/v1/message.proto +102 -4
  114. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/nexus/v1/message.proto +84 -0
  115. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/operation/v1/message.proto +25 -10
  116. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/region/v1/message.proto +14 -1
  117. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/resource/v1/message.proto +25 -0
  118. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/sink/v1/message.proto +41 -0
  119. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/usage/v1/message.proto +59 -0
  120. package/sdk-core/sdk-core-protos/protos/api_upstream/.github/PULL_REQUEST_TEMPLATE.md +2 -0
  121. package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/create-release.yml +135 -0
  122. package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/push-to-buf.yml +20 -0
  123. package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/trigger-api-go-delete-release.yml +13 -0
  124. package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/trigger-api-go-publish-release.yml +13 -0
  125. package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/trigger-api-go-update.yml +13 -21
  126. package/sdk-core/sdk-core-protos/protos/api_upstream/Makefile +2 -2
  127. package/sdk-core/sdk-core-protos/protos/api_upstream/buf.yaml +1 -0
  128. package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv2.json +3386 -1047
  129. package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv3.yaml +3529 -1144
  130. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/batch/v1/message.proto +39 -1
  131. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/command/v1/message.proto +6 -0
  132. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/common/v1/message.proto +39 -1
  133. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/deployment/v1/message.proto +252 -0
  134. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +1 -0
  135. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/common.proto +6 -0
  136. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/deployment.proto +96 -0
  137. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/event_type.proto +2 -0
  138. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +2 -0
  139. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/nexus.proto +42 -0
  140. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/reset.proto +2 -0
  141. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/workflow.proto +43 -2
  142. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/errordetails/v1/message.proto +13 -1
  143. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/failure/v1/message.proto +14 -0
  144. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/history/v1/message.proto +70 -12
  145. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/nexus/v1/message.proto +12 -0
  146. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/query/v1/message.proto +9 -2
  147. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +46 -2
  148. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflow/v1/message.proto +206 -0
  149. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +482 -97
  150. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +230 -43
  151. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/core_interface.proto +6 -0
  152. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/nexus/nexus.proto +71 -0
  153. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +46 -2
  154. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +55 -9
  155. package/sdk-core/sdk-core-protos/src/history_builder.rs +5 -5
  156. package/sdk-core/sdk-core-protos/src/history_info.rs +5 -6
  157. package/sdk-core/sdk-core-protos/src/lib.rs +414 -34
  158. package/sdk-core/sdk-core-protos/src/task_token.rs +1 -1
  159. package/sdk-core/test-utils/Cargo.toml +3 -11
  160. package/sdk-core/test-utils/src/canned_histories.rs +1 -1
  161. package/sdk-core/test-utils/src/lib.rs +159 -85
  162. package/sdk-core/tests/fuzzy_workflow.rs +3 -3
  163. package/sdk-core/tests/heavy_tests.rs +3 -3
  164. package/sdk-core/tests/integ_tests/client_tests.rs +171 -20
  165. package/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +45 -39
  166. package/sdk-core/tests/integ_tests/heartbeat_tests.rs +7 -6
  167. package/sdk-core/tests/integ_tests/metrics_tests.rs +492 -35
  168. package/sdk-core/tests/integ_tests/polling_tests.rs +7 -5
  169. package/sdk-core/tests/integ_tests/queries_tests.rs +14 -17
  170. package/sdk-core/tests/integ_tests/update_tests.rs +47 -44
  171. package/sdk-core/tests/integ_tests/visibility_tests.rs +4 -3
  172. package/sdk-core/tests/integ_tests/worker_tests.rs +5 -5
  173. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +15 -13
  174. package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +28 -14
  175. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +7 -1
  176. package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +57 -4
  177. package/sdk-core/tests/integ_tests/workflow_tests/eager.rs +1 -1
  178. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +24 -18
  179. package/sdk-core/tests/integ_tests/workflow_tests/nexus.rs +506 -0
  180. package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +1 -1
  181. package/sdk-core/tests/integ_tests/workflow_tests/priority.rs +104 -0
  182. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +34 -31
  183. package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +1 -1
  184. package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +10 -7
  185. package/sdk-core/tests/integ_tests/workflow_tests.rs +152 -116
  186. package/sdk-core/tests/main.rs +36 -6
  187. package/sdk-core/tests/runner.rs +30 -9
  188. package/src/conversions/slot_supplier_bridge.rs +4 -0
  189. package/src/conversions.rs +1 -0
  190. package/src/worker.rs +5 -7
  191. package/sdk-core/core/src/worker/activities/activity_task_poller_stream.rs +0 -78
@@ -1,56 +1,57 @@
1
1
  use crate::{
2
- advance_fut,
2
+ Worker, advance_fut,
3
3
  internal_flags::CoreInternalFlags,
4
4
  job_assert,
5
5
  replay::TestHistoryBuilder,
6
6
  test_help::{
7
+ FakeWfResponses, MockPollCfg, MocksHolder, ResponseType, WorkerExt,
8
+ WorkflowCachingPolicy::{self, AfterEveryReply, NonSticky},
7
9
  build_fake_worker, build_mock_pollers, build_multihist_mock_sg, canned_histories,
8
10
  gen_assert_and_fail, gen_assert_and_reply, hist_to_poll_resp, mock_sdk, mock_sdk_cfg,
9
11
  mock_worker, poll_and_reply, poll_and_reply_clears_outstanding_evicts, single_hist_mock_sg,
10
- test_worker_cfg, FakeWfResponses, MockPollCfg, MocksHolder, ResponseType, WorkerExt,
11
- WorkflowCachingPolicy::{self, AfterEveryReply, NonSticky},
12
+ test_worker_cfg,
12
13
  },
13
14
  worker::{
14
- client::mocks::{mock_manual_workflow_client, mock_workflow_client},
15
15
  TunerBuilder,
16
+ client::mocks::{mock_manual_workflow_client, mock_workflow_client},
16
17
  },
17
- Worker,
18
18
  };
19
- use futures_util::{stream, FutureExt};
19
+ use futures_util::{FutureExt, stream};
20
20
  use mockall::TimesRange;
21
21
  use rstest::{fixture, rstest};
22
22
  use std::{
23
23
  collections::{HashMap, HashSet, VecDeque},
24
24
  sync::{
25
+ Arc,
25
26
  atomic::{AtomicU64, AtomicUsize, Ordering},
26
27
  mpsc::sync_channel,
27
- Arc,
28
28
  },
29
29
  time::Duration,
30
30
  };
31
31
  use temporal_client::WorkflowOptions;
32
- use temporal_sdk::{ActivityOptions, CancellableFuture, WfContext};
32
+ use temporal_sdk::{ActivityOptions, CancellableFuture, TimerOptions, WfContext};
33
33
  use temporal_sdk_core_api::{
34
- errors::PollWfError,
34
+ Worker as WorkerTrait,
35
+ errors::PollError,
35
36
  worker::{
36
37
  SlotMarkUsedContext, SlotReleaseContext, SlotReservationContext, SlotSupplier,
37
38
  SlotSupplierPermit, WorkflowSlotKind,
38
39
  },
39
- Worker as WorkerTrait,
40
40
  };
41
41
  use temporal_sdk_core_protos::{
42
+ DEFAULT_ACTIVITY_TYPE, DEFAULT_WORKFLOW_TYPE,
42
43
  coresdk::{
43
- activity_result::{self as ar, activity_resolution, ActivityResolution},
44
+ activity_result::{self as ar, ActivityResolution, activity_resolution},
44
45
  common::VersioningIntent,
45
46
  workflow_activation::{
46
- remove_from_cache::EvictionReason, workflow_activation_job, FireTimer,
47
- InitializeWorkflow, ResolveActivity, UpdateRandomSeed, WorkflowActivationJob,
47
+ FireTimer, InitializeWorkflow, ResolveActivity, UpdateRandomSeed,
48
+ WorkflowActivationJob, remove_from_cache::EvictionReason, workflow_activation_job,
48
49
  },
49
50
  workflow_commands::{
50
- update_response::Response, workflow_command, ActivityCancellationType, CancelTimer,
51
- CompleteWorkflowExecution, ContinueAsNewWorkflowExecution, FailWorkflowExecution,
52
- RequestCancelActivity, ScheduleActivity, SetPatchMarker, StartChildWorkflowExecution,
53
- UpdateResponse,
51
+ ActivityCancellationType, CancelTimer, CompleteWorkflowExecution,
52
+ ContinueAsNewWorkflowExecution, FailWorkflowExecution, RequestCancelActivity,
53
+ ScheduleActivity, SetPatchMarker, StartChildWorkflowExecution, UpdateResponse,
54
+ update_response::Response, workflow_command,
54
55
  },
55
56
  workflow_completion::WorkflowActivationCompletion,
56
57
  },
@@ -61,16 +62,16 @@ use temporal_sdk_core_protos::{
61
62
  enums::v1::{CommandType, EventType, WorkflowTaskFailedCause},
62
63
  failure::v1::Failure,
63
64
  history::v1::{
64
- history_event, TimerFiredEventAttributes,
65
- WorkflowPropertiesModifiedExternallyEventAttributes,
65
+ TimerFiredEventAttributes, WorkflowPropertiesModifiedExternallyEventAttributes,
66
+ history_event,
66
67
  },
68
+ sdk::v1::UserMetadata,
67
69
  workflowservice::v1::{
68
70
  GetWorkflowExecutionHistoryResponse, RespondWorkflowTaskCompletedResponse,
69
71
  },
70
72
  },
71
- DEFAULT_ACTIVITY_TYPE, DEFAULT_WORKFLOW_TYPE,
72
73
  };
73
- use temporal_sdk_core_test_utils::{fanout_tasks, start_timer_cmd, WorkerTestHelpers};
74
+ use temporal_sdk_core_test_utils::{WorkerTestHelpers, fanout_tasks, start_timer_cmd};
74
75
  use tokio::{
75
76
  join,
76
77
  sync::{Barrier, Semaphore},
@@ -139,11 +140,13 @@ async fn single_activity_completion(worker: Worker) {
139
140
  &[
140
141
  gen_assert_and_reply(
141
142
  &job_assert!(workflow_activation_job::Variant::InitializeWorkflow(_)),
142
- vec![ScheduleActivity {
143
- activity_id: "fake_activity".to_string(),
144
- ..default_act_sched()
145
- }
146
- .into()],
143
+ vec![
144
+ ScheduleActivity {
145
+ activity_id: "fake_activity".to_string(),
146
+ ..default_act_sched()
147
+ }
148
+ .into(),
149
+ ],
147
150
  ),
148
151
  gen_assert_and_reply(
149
152
  &job_assert!(workflow_activation_job::Variant::ResolveActivity(_)),
@@ -262,13 +265,15 @@ async fn scheduled_activity_cancellation_try_cancel(hist_batches: &'static [usiz
262
265
  &[
263
266
  gen_assert_and_reply(
264
267
  &job_assert!(workflow_activation_job::Variant::InitializeWorkflow(_)),
265
- vec![ScheduleActivity {
266
- seq: activity_seq,
267
- activity_id: activity_id.to_string(),
268
- cancellation_type: ActivityCancellationType::TryCancel as i32,
269
- ..default_act_sched()
270
- }
271
- .into()],
268
+ vec![
269
+ ScheduleActivity {
270
+ seq: activity_seq,
271
+ activity_id: activity_id.to_string(),
272
+ cancellation_type: ActivityCancellationType::TryCancel as i32,
273
+ ..default_act_sched()
274
+ }
275
+ .into(),
276
+ ],
272
277
  ),
273
278
  gen_assert_and_reply(
274
279
  &job_assert!(workflow_activation_job::Variant::SignalWorkflow(_)),
@@ -407,12 +412,14 @@ async fn cancelled_activity_timeout(hist_batches: &'static [usize]) {
407
412
  &[
408
413
  gen_assert_and_reply(
409
414
  &job_assert!(workflow_activation_job::Variant::InitializeWorkflow(_)),
410
- vec![ScheduleActivity {
411
- seq: activity_seq,
412
- activity_id: activity_id.to_string(),
413
- ..default_act_sched()
414
- }
415
- .into()],
415
+ vec![
416
+ ScheduleActivity {
417
+ seq: activity_seq,
418
+ activity_id: activity_id.to_string(),
419
+ ..default_act_sched()
420
+ }
421
+ .into(),
422
+ ],
416
423
  ),
417
424
  gen_assert_and_reply(
418
425
  &job_assert!(workflow_activation_job::Variant::SignalWorkflow(_)),
@@ -559,13 +566,15 @@ async fn verify_activity_cancellation(
559
566
  &[
560
567
  gen_assert_and_reply(
561
568
  &job_assert!(workflow_activation_job::Variant::InitializeWorkflow(_)),
562
- vec![ScheduleActivity {
563
- seq: activity_seq,
564
- activity_id: activity_seq.to_string(),
565
- cancellation_type: cancel_type as i32,
566
- ..default_act_sched()
567
- }
568
- .into()],
569
+ vec![
570
+ ScheduleActivity {
571
+ seq: activity_seq,
572
+ activity_id: activity_seq.to_string(),
573
+ cancellation_type: cancel_type as i32,
574
+ ..default_act_sched()
575
+ }
576
+ .into(),
577
+ ],
569
578
  ),
570
579
  gen_assert_and_reply(
571
580
  &job_assert!(workflow_activation_job::Variant::SignalWorkflow(_)),
@@ -627,13 +636,16 @@ async fn verify_activity_cancellation_wait_for_cancellation(activity_id: u32, wo
627
636
  &[
628
637
  gen_assert_and_reply(
629
638
  &job_assert!(workflow_activation_job::Variant::InitializeWorkflow(_)),
630
- vec![ScheduleActivity {
631
- seq: activity_id,
632
- activity_id: activity_id.to_string(),
633
- cancellation_type: ActivityCancellationType::WaitCancellationCompleted as i32,
634
- ..default_act_sched()
635
- }
636
- .into()],
639
+ vec![
640
+ ScheduleActivity {
641
+ seq: activity_id,
642
+ activity_id: activity_id.to_string(),
643
+ cancellation_type: ActivityCancellationType::WaitCancellationCompleted
644
+ as i32,
645
+ ..default_act_sched()
646
+ }
647
+ .into(),
648
+ ],
637
649
  ),
638
650
  gen_assert_and_reply(
639
651
  &job_assert!(workflow_activation_job::Variant::SignalWorkflow(_)),
@@ -810,13 +822,15 @@ async fn simple_timer_fail_wf_execution(hist_batches: &'static [usize]) {
810
822
  ),
811
823
  gen_assert_and_reply(
812
824
  &job_assert!(workflow_activation_job::Variant::FireTimer(_)),
813
- vec![FailWorkflowExecution {
814
- failure: Some(Failure {
815
- message: "I'm ded".to_string(),
816
- ..Default::default()
817
- }),
818
- }
819
- .into()],
825
+ vec![
826
+ FailWorkflowExecution {
827
+ failure: Some(Failure {
828
+ message: "I'm ded".to_string(),
829
+ ..Default::default()
830
+ }),
831
+ }
832
+ .into(),
833
+ ],
820
834
  ),
821
835
  ],
822
836
  )
@@ -1007,13 +1021,15 @@ async fn activity_not_canceled_when_also_completed_repro(hist_batches: &'static
1007
1021
  &[
1008
1022
  gen_assert_and_reply(
1009
1023
  &job_assert!(workflow_activation_job::Variant::InitializeWorkflow(_)),
1010
- vec![ScheduleActivity {
1011
- seq: activity_id,
1012
- activity_id: "act-1".to_string(),
1013
- cancellation_type: ActivityCancellationType::TryCancel as i32,
1014
- ..default_act_sched()
1015
- }
1016
- .into()],
1024
+ vec![
1025
+ ScheduleActivity {
1026
+ seq: activity_id,
1027
+ activity_id: "act-1".to_string(),
1028
+ cancellation_type: ActivityCancellationType::TryCancel as i32,
1029
+ ..default_act_sched()
1030
+ }
1031
+ .into(),
1032
+ ],
1017
1033
  ),
1018
1034
  gen_assert_and_reply(
1019
1035
  &job_assert!(workflow_activation_job::Variant::SignalWorkflow(_)),
@@ -1108,13 +1124,15 @@ async fn wft_timeout_repro(hist_batches: &'static [usize]) {
1108
1124
  &[
1109
1125
  gen_assert_and_reply(
1110
1126
  &job_assert!(workflow_activation_job::Variant::InitializeWorkflow(_)),
1111
- vec![ScheduleActivity {
1112
- seq: activity_id,
1113
- activity_id: activity_id.to_string(),
1114
- cancellation_type: ActivityCancellationType::TryCancel as i32,
1115
- ..default_act_sched()
1116
- }
1117
- .into()],
1127
+ vec![
1128
+ ScheduleActivity {
1129
+ seq: activity_id,
1130
+ activity_id: activity_id.to_string(),
1131
+ cancellation_type: ActivityCancellationType::TryCancel as i32,
1132
+ ..default_act_sched()
1133
+ }
1134
+ .into(),
1135
+ ],
1118
1136
  ),
1119
1137
  gen_assert_and_reply(
1120
1138
  &job_assert!(
@@ -1320,26 +1338,18 @@ async fn fail_wft_then_recover() {
1320
1338
  // Start an activity instead of a timer, triggering nondeterminism error
1321
1339
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
1322
1340
  act.run_id.clone(),
1323
- vec![ScheduleActivity {
1324
- activity_id: "fake_activity".to_string(),
1325
- ..default_act_sched()
1326
- }
1327
- .into()],
1341
+ vec![
1342
+ ScheduleActivity {
1343
+ activity_id: "fake_activity".to_string(),
1344
+ ..default_act_sched()
1345
+ }
1346
+ .into(),
1347
+ ],
1328
1348
  ))
1329
1349
  .await
1330
1350
  .unwrap();
1331
1351
  // We must handle an eviction now
1332
- let evict_act = core.poll_workflow_activation().await.unwrap();
1333
- assert_eq!(evict_act.run_id, act.run_id);
1334
- assert_matches!(
1335
- evict_act.jobs.as_slice(),
1336
- [WorkflowActivationJob {
1337
- variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
1338
- }]
1339
- );
1340
- core.complete_workflow_activation(WorkflowActivationCompletion::empty(evict_act.run_id))
1341
- .await
1342
- .unwrap();
1352
+ core.handle_eviction().await;
1343
1353
 
1344
1354
  // Workflow starting over, this time issue the right command
1345
1355
  let act = core.poll_workflow_activation().await.unwrap();
@@ -1530,6 +1540,7 @@ async fn failing_wft_doesnt_eat_permit_forever() {
1530
1540
  // row because we purposefully time out rather than spamming.
1531
1541
  for _ in 1..=2 {
1532
1542
  let activation = worker.poll_workflow_activation().await.unwrap();
1543
+ run_id.clone_from(&activation.run_id);
1533
1544
  // Issue a nonsense completion that will trigger a WFT failure
1534
1545
  worker
1535
1546
  .complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
@@ -1538,18 +1549,7 @@ async fn failing_wft_doesnt_eat_permit_forever() {
1538
1549
  ))
1539
1550
  .await
1540
1551
  .unwrap();
1541
- let activation = worker.poll_workflow_activation().await.unwrap();
1542
- assert_matches!(
1543
- activation.jobs.as_slice(),
1544
- [WorkflowActivationJob {
1545
- variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
1546
- },]
1547
- );
1548
- run_id.clone_from(&activation.run_id);
1549
- worker
1550
- .complete_workflow_activation(WorkflowActivationCompletion::empty(activation.run_id))
1551
- .await
1552
- .unwrap();
1552
+ worker.handle_eviction().await;
1553
1553
  }
1554
1554
  assert_eq!(worker.outstanding_workflow_tasks().await, 0);
1555
1555
  // We should be "out of work" because the mock service thinks we didn't complete the last task,
@@ -2043,7 +2043,7 @@ async fn autocompletes_wft_no_work() {
2043
2043
  // work
2044
2044
  assert_matches!(
2045
2045
  core.poll_workflow_activation().await.unwrap_err(),
2046
- PollWfError::ShutDown
2046
+ PollError::ShutDown
2047
2047
  );
2048
2048
 
2049
2049
  core.shutdown().await;
@@ -2600,6 +2600,7 @@ async fn _do_post_terminal_commands_test(
2600
2600
 
2601
2601
  let act = core.poll_workflow_activation().await.unwrap();
2602
2602
 
2603
+ core.initiate_shutdown();
2603
2604
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
2604
2605
  act.run_id,
2605
2606
  commands_sent_by_lang,
@@ -2608,7 +2609,7 @@ async fn _do_post_terminal_commands_test(
2608
2609
  .unwrap();
2609
2610
 
2610
2611
  let act = core.poll_workflow_activation().await;
2611
- assert_matches!(act.unwrap_err(), PollWfError::ShutDown);
2612
+ assert_matches!(act.unwrap_err(), PollError::ShutDown);
2612
2613
  core.shutdown().await;
2613
2614
  }
2614
2615
 
@@ -2810,7 +2811,7 @@ async fn poller_wont_run_ahead_of_task_slots() {
2810
2811
  // This should end up getting shut down after the other routine finishes tasks
2811
2812
  assert_matches!(
2812
2813
  worker.poll_workflow_activation().await.unwrap_err(),
2813
- PollWfError::ShutDown
2814
+ PollError::ShutDown
2814
2815
  );
2815
2816
  };
2816
2817
  // Wait for a bit concurrently with above, verify no extra tasks got taken, shutdown
@@ -3065,7 +3066,7 @@ async fn slot_provider_cant_hand_out_more_permits_than_cache_size() {
3065
3066
  // This should end up getting shut down after the other routine finishes tasks
3066
3067
  assert_matches!(
3067
3068
  worker.poll_workflow_activation().await.unwrap_err(),
3068
- PollWfError::ShutDown
3069
+ PollError::ShutDown
3069
3070
  );
3070
3071
  };
3071
3072
  // Wait for a bit concurrently with above, verify no extra tasks got taken, shutdown
@@ -3086,3 +3087,50 @@ async fn slot_provider_cant_hand_out_more_permits_than_cache_size() {
3086
3087
  // polling is not exceeding the task limit
3087
3088
  assert_eq!(popped_tasks.load(Ordering::Relaxed), 10);
3088
3089
  }
3090
+
3091
+ #[tokio::test]
3092
+ async fn pass_timer_summary_to_metadata() {
3093
+ let t = canned_histories::single_timer("1");
3094
+ let mut mock_cfg = MockPollCfg::from_hist_builder(t);
3095
+ let wf_id = mock_cfg.hists[0].wf_id.clone();
3096
+ let wf_type = DEFAULT_WORKFLOW_TYPE;
3097
+ let expected_user_metadata = Some(UserMetadata {
3098
+ summary: Some(b"timer summary".into()),
3099
+ details: None,
3100
+ });
3101
+ mock_cfg.completion_asserts_from_expectations(|mut asserts| {
3102
+ asserts
3103
+ .then(move |wft| {
3104
+ assert_eq!(wft.commands.len(), 1);
3105
+ assert_eq!(wft.commands[0].command_type(), CommandType::StartTimer);
3106
+ assert_eq!(wft.commands[0].user_metadata, expected_user_metadata)
3107
+ })
3108
+ .then(move |wft| {
3109
+ assert_eq!(wft.commands.len(), 1);
3110
+ assert_eq!(
3111
+ wft.commands[0].command_type(),
3112
+ CommandType::CompleteWorkflowExecution
3113
+ );
3114
+ });
3115
+ });
3116
+
3117
+ let mut worker = mock_sdk_cfg(mock_cfg, |_| {});
3118
+ worker.register_wf(wf_type, |ctx: WfContext| async move {
3119
+ ctx.timer(TimerOptions {
3120
+ duration: Duration::from_secs(1),
3121
+ summary: Some("timer summary".to_string()),
3122
+ })
3123
+ .await;
3124
+ Ok(().into())
3125
+ });
3126
+ worker
3127
+ .submit_wf(
3128
+ wf_id.to_owned(),
3129
+ wf_type.to_owned(),
3130
+ vec![],
3131
+ WorkflowOptions::default(),
3132
+ )
3133
+ .await
3134
+ .unwrap();
3135
+ worker.run_until_done().await.unwrap();
3136
+ }
@@ -13,7 +13,7 @@ use std::{
13
13
  use temporal_client::ClientOptionsBuilder;
14
14
  use tokio::{
15
15
  task::spawn_blocking,
16
- time::{sleep, Duration},
16
+ time::{Duration, sleep},
17
17
  };
18
18
  use tokio_util::io::{StreamReader, SyncIoBridge};
19
19
  use url::Url;
@@ -101,7 +101,7 @@ impl TemporalDevServerConfig {
101
101
  "frontend.enableUpdateWorkflowExecutionAsyncAccepted=true".to_owned(),
102
102
  ];
103
103
  if let Some(db_filename) = &self.db_filename {
104
- args.push("--filename".to_owned());
104
+ args.push("--db-filename".to_owned());
105
105
  args.push(db_filename.clone());
106
106
  }
107
107
  if let Some(ui_port) = self.ui_port {
@@ -270,6 +270,8 @@ pub enum EphemeralExe {
270
270
  version: EphemeralExeVersion,
271
271
  /// Destination directory or the user temp directory if none set.
272
272
  dest_dir: Option<String>,
273
+ /// How long to cache the download for. None means forever.
274
+ ttl: Option<Duration>,
273
275
  },
274
276
  }
275
277
 
@@ -309,7 +311,11 @@ impl EphemeralExe {
309
311
  }
310
312
  Ok(path)
311
313
  }
312
- EphemeralExe::CachedDownload { version, dest_dir } => {
314
+ EphemeralExe::CachedDownload {
315
+ version,
316
+ dest_dir,
317
+ ttl,
318
+ } => {
313
319
  let dest_dir = dest_dir
314
320
  .as_ref()
315
321
  .map(PathBuf::from)
@@ -334,8 +340,7 @@ impl EphemeralExe {
334
340
  dest.display()
335
341
  );
336
342
 
337
- // If it already exists, skip
338
- if dest.exists() {
343
+ if dest.exists() && remove_file_past_ttl(ttl, &dest)? {
339
344
  return Ok(dest);
340
345
  }
341
346
 
@@ -379,6 +384,7 @@ impl EphemeralExe {
379
384
  &info.archive_url,
380
385
  Path::new(&info.file_to_extract),
381
386
  &dest,
387
+ false,
382
388
  )
383
389
  .await?
384
390
  {
@@ -433,7 +439,7 @@ fn get_free_port(bind_ip: &str) -> io::Result<u16> {
433
439
  let (socket, _addr) = listen.accept()?;
434
440
 
435
441
  // Explicitly drop the socket to close the connection from the listening side first
436
- std::mem::drop(socket);
442
+ drop(socket);
437
443
  }
438
444
 
439
445
  Ok(addr.port())
@@ -447,6 +453,7 @@ async fn lazy_download_exe(
447
453
  uri: &str,
448
454
  file_to_extract: &Path,
449
455
  dest: &Path,
456
+ already_tried_cleaning_old: bool,
450
457
  ) -> anyhow::Result<bool> {
451
458
  // If it already exists, do not extract
452
459
  if dest.exists() {
@@ -474,7 +481,16 @@ async fn lazy_download_exe(
474
481
  // This match only gets Ok if the file was downloaded and extracted to the
475
482
  // temporary path
476
483
  match file {
477
- Err(err) if err.kind() == std::io::ErrorKind::AlreadyExists => {
484
+ Err(err) if err.kind() == io::ErrorKind::AlreadyExists => {
485
+ // If the download lock file exists but is old, delete it and try again, since it may
486
+ // have been left by an abandoned process.
487
+ if !already_tried_cleaning_old
488
+ && temp_dest.metadata()?.modified()?.elapsed()?.as_secs() > 90
489
+ {
490
+ std::fs::remove_file(temp_dest)?;
491
+ return Box::pin(lazy_download_exe(client, uri, file_to_extract, dest, true)).await;
492
+ }
493
+
478
494
  // Since it already exists, we'll try once a second for 20 seconds
479
495
  // to wait for it to be done, then return false so the caller can
480
496
  // try again.
@@ -530,7 +546,7 @@ async fn download_and_extract(
530
546
  // We have to map the error type to an io error
531
547
  let stream = resp
532
548
  .bytes_stream()
533
- .map(|item| item.map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err)));
549
+ .map(|item| item.map_err(|err| io::Error::new(io::ErrorKind::Other, err)));
534
550
 
535
551
  // Since our tar/zip impls use sync IO, we have to create a bridge and run
536
552
  // in a blocking closure.
@@ -574,12 +590,36 @@ async fn download_and_extract(
574
590
  .await?
575
591
  }
576
592
 
593
+ /// Remove the file if it's older than the TTL. Returns true if the current file can be re-used,
594
+ /// returns false if it was removed or should otherwise be re-downloaded.
595
+ fn remove_file_past_ttl(ttl: &Option<Duration>, dest: &PathBuf) -> Result<bool, anyhow::Error> {
596
+ match ttl {
597
+ None => return Ok(true),
598
+ Some(ttl) => {
599
+ if let Ok(mtime) = dest.metadata().and_then(|d| d.modified()) {
600
+ if mtime.elapsed().unwrap_or_default().lt(ttl) {
601
+ return Ok(true);
602
+ } else {
603
+ // Remove so we can re-download
604
+ std::fs::remove_file(dest)?;
605
+ }
606
+ }
607
+ // If we couldn't read the mtime something weird is probably up, so
608
+ // re-download
609
+ }
610
+ }
611
+ Ok(false)
612
+ }
613
+
577
614
  #[cfg(test)]
578
615
  mod tests {
579
- use super::get_free_port;
616
+ use super::{get_free_port, remove_file_past_ttl};
580
617
  use std::{
581
618
  collections::HashSet,
619
+ env::temp_dir,
620
+ fs::File,
582
621
  net::{TcpListener, TcpStream},
622
+ time::{Duration, SystemTime},
583
623
  };
584
624
 
585
625
  #[test]
@@ -609,6 +649,22 @@ mod tests {
609
649
  }
610
650
  }
611
651
 
652
+ #[tokio::test]
653
+ async fn respects_file_ttl() {
654
+ let rand_fname = format!("{}", rand::random::<u64>());
655
+ let temp_dir = temp_dir();
656
+
657
+ let dest_file_path = temp_dir.join(format!("core-test-{}", &rand_fname));
658
+ let dest_file = File::create(&dest_file_path).unwrap();
659
+ let set_time_to = SystemTime::now() - Duration::from_secs(100);
660
+ dest_file.set_modified(set_time_to).unwrap();
661
+
662
+ remove_file_past_ttl(&Some(Duration::from_secs(60)), &dest_file_path).unwrap();
663
+
664
+ // file should be gone
665
+ assert!(!dest_file_path.exists());
666
+ }
667
+
612
668
  fn try_listen_and_dial_on(host: &str, port: u16) -> std::io::Result<()> {
613
669
  let listener = TcpListener::bind((host, port))?;
614
670
  let _stream = TcpStream::connect((host, port))?;
@@ -617,7 +673,7 @@ mod tests {
617
673
  let (socket, _addr) = listener.accept()?;
618
674
 
619
675
  // Explicitly drop the socket to close the connection from the listening side first
620
- std::mem::drop(socket);
676
+ drop(socket);
621
677
 
622
678
  Ok(())
623
679
  }