@temporalio/core-bridge 1.8.6 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (213) hide show
  1. package/Cargo.lock +670 -594
  2. package/Cargo.toml +2 -1
  3. package/lib/errors.js +6 -6
  4. package/lib/errors.js.map +1 -1
  5. package/lib/index.d.ts +17 -44
  6. package/lib/index.js.map +1 -1
  7. package/package.json +5 -6
  8. package/releases/aarch64-apple-darwin/index.node +0 -0
  9. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  10. package/releases/x86_64-apple-darwin/index.node +0 -0
  11. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  12. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  13. package/sdk-core/.github/workflows/heavy.yml +4 -0
  14. package/sdk-core/.github/workflows/per-pr.yml +96 -0
  15. package/sdk-core/ARCHITECTURE.md +1 -1
  16. package/sdk-core/Cargo.toml +10 -0
  17. package/sdk-core/LICENSE.txt +0 -2
  18. package/sdk-core/README.md +37 -21
  19. package/sdk-core/client/Cargo.toml +7 -4
  20. package/sdk-core/client/src/lib.rs +274 -142
  21. package/sdk-core/client/src/metrics.rs +68 -57
  22. package/sdk-core/client/src/raw.rs +191 -45
  23. package/sdk-core/client/src/retry.rs +20 -0
  24. package/sdk-core/client/src/worker_registry/mod.rs +264 -0
  25. package/sdk-core/client/src/workflow_handle/mod.rs +2 -1
  26. package/sdk-core/core/Cargo.toml +17 -19
  27. package/sdk-core/core/src/core_tests/activity_tasks.rs +4 -2
  28. package/sdk-core/core/src/core_tests/child_workflows.rs +7 -7
  29. package/sdk-core/core/src/core_tests/mod.rs +1 -0
  30. package/sdk-core/core/src/core_tests/queries.rs +42 -1
  31. package/sdk-core/core/src/core_tests/replay_flag.rs +29 -39
  32. package/sdk-core/core/src/core_tests/updates.rs +73 -0
  33. package/sdk-core/core/src/core_tests/workflow_tasks.rs +52 -1
  34. package/sdk-core/core/src/ephemeral_server/mod.rs +34 -11
  35. package/sdk-core/core/src/internal_flags.rs +7 -1
  36. package/sdk-core/core/src/lib.rs +19 -36
  37. package/sdk-core/core/src/protosext/mod.rs +12 -4
  38. package/sdk-core/core/src/protosext/protocol_messages.rs +102 -0
  39. package/sdk-core/core/src/replay/mod.rs +99 -48
  40. package/sdk-core/core/src/telemetry/log_export.rs +161 -28
  41. package/sdk-core/core/src/telemetry/metrics.rs +869 -248
  42. package/sdk-core/core/src/telemetry/mod.rs +153 -257
  43. package/sdk-core/core/src/telemetry/prometheus_server.rs +36 -31
  44. package/sdk-core/core/src/test_help/mod.rs +64 -5
  45. package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +12 -2
  46. package/sdk-core/core/src/worker/activities.rs +276 -10
  47. package/sdk-core/core/src/worker/client/mocks.rs +18 -0
  48. package/sdk-core/core/src/worker/client.rs +16 -3
  49. package/sdk-core/core/src/worker/mod.rs +45 -28
  50. package/sdk-core/core/src/worker/slot_provider.rs +175 -0
  51. package/sdk-core/core/src/worker/workflow/driven_workflow.rs +27 -34
  52. package/sdk-core/core/src/worker/workflow/history_update.rs +5 -2
  53. package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +71 -95
  54. package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +34 -22
  55. package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +50 -34
  56. package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +106 -92
  57. package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +22 -21
  58. package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +386 -499
  59. package/sdk-core/core/src/worker/workflow/machines/mod.rs +12 -2
  60. package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +33 -26
  61. package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +198 -215
  62. package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +67 -63
  63. package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +88 -119
  64. package/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +3 -1
  65. package/sdk-core/core/src/worker/workflow/machines/update_state_machine.rs +411 -0
  66. package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +27 -26
  67. package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +319 -94
  68. package/sdk-core/core/src/worker/workflow/managed_run.rs +179 -132
  69. package/sdk-core/core/src/worker/workflow/mod.rs +129 -58
  70. package/sdk-core/core/src/worker/workflow/run_cache.rs +16 -26
  71. package/sdk-core/core/src/worker/workflow/workflow_stream/saved_wf_inputs.rs +2 -2
  72. package/sdk-core/core/src/worker/workflow/workflow_stream.rs +48 -43
  73. package/sdk-core/core-api/Cargo.toml +8 -7
  74. package/sdk-core/core-api/src/lib.rs +4 -12
  75. package/sdk-core/core-api/src/telemetry/metrics.rs +334 -0
  76. package/sdk-core/core-api/src/telemetry.rs +53 -42
  77. package/sdk-core/core-api/src/worker.rs +7 -0
  78. package/sdk-core/{.buildkite/docker → docker}/docker-compose.yaml +1 -1
  79. package/sdk-core/etc/dynamic-config.yaml +11 -1
  80. package/sdk-core/fsm/LICENSE.txt +0 -2
  81. package/sdk-core/fsm/rustfsm_procmacro/Cargo.toml +1 -1
  82. package/sdk-core/fsm/rustfsm_procmacro/LICENSE.txt +0 -2
  83. package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +1 -3
  84. package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +2 -2
  85. package/sdk-core/fsm/rustfsm_trait/LICENSE.txt +0 -2
  86. package/sdk-core/sdk/Cargo.toml +2 -2
  87. package/sdk-core/sdk/src/lib.rs +85 -7
  88. package/sdk-core/sdk/src/workflow_context/options.rs +4 -0
  89. package/sdk-core/sdk/src/workflow_context.rs +43 -15
  90. package/sdk-core/sdk/src/workflow_future.rs +334 -204
  91. package/sdk-core/sdk-core-protos/Cargo.toml +3 -3
  92. package/sdk-core/sdk-core-protos/build.rs +14 -14
  93. package/sdk-core/sdk-core-protos/protos/api_upstream/.buildkite/Dockerfile +2 -0
  94. package/sdk-core/sdk-core-protos/protos/api_upstream/Makefile +99 -0
  95. package/sdk-core/sdk-core-protos/protos/api_upstream/api-linter.yaml +56 -0
  96. package/sdk-core/sdk-core-protos/protos/api_upstream/buf.gen.yaml +20 -0
  97. package/sdk-core/sdk-core-protos/protos/api_upstream/buf.lock +11 -0
  98. package/sdk-core/sdk-core-protos/protos/api_upstream/buf.yaml +18 -0
  99. package/sdk-core/sdk-core-protos/protos/api_upstream/google/api/annotations.proto +31 -0
  100. package/sdk-core/sdk-core-protos/protos/api_upstream/google/api/http.proto +379 -0
  101. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/any.proto +162 -0
  102. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/descriptor.proto +1212 -0
  103. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/duration.proto +115 -0
  104. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/empty.proto +51 -0
  105. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/timestamp.proto +144 -0
  106. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/wrappers.proto +123 -0
  107. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/batch/v1/message.proto +12 -9
  108. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/command/v1/message.proto +11 -13
  109. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/common/v1/message.proto +33 -4
  110. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/failed_cause.proto +2 -0
  111. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/reset.proto +4 -4
  112. package/sdk-core/{protos/api_upstream/build/tools.go → sdk-core-protos/protos/api_upstream/temporal/api/export/v1/message.proto} +22 -6
  113. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/filter/v1/message.proto +2 -4
  114. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/history/v1/message.proto +21 -23
  115. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/namespace/v1/message.proto +2 -4
  116. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/operatorservice/v1/request_response.proto +2 -0
  117. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/operatorservice/v1/service.proto +4 -0
  118. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/replication/v1/message.proto +1 -3
  119. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/schedule/v1/message.proto +36 -20
  120. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +13 -0
  121. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/sdk/v1/workflow_metadata.proto +66 -0
  122. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/taskqueue/v1/message.proto +2 -4
  123. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/update/v1/message.proto +1 -1
  124. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/version/v1/message.proto +2 -3
  125. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/workflow/v1/message.proto +24 -22
  126. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/workflowservice/v1/request_response.proto +84 -32
  127. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/workflowservice/v1/service.proto +205 -47
  128. package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +57 -0
  129. package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +27 -0
  130. package/sdk-core/sdk-core-protos/src/history_builder.rs +67 -2
  131. package/sdk-core/sdk-core-protos/src/history_info.rs +1 -1
  132. package/sdk-core/sdk-core-protos/src/lib.rs +76 -3
  133. package/sdk-core/sdk-core-protos/src/utilities.rs +14 -0
  134. package/sdk-core/test-utils/Cargo.toml +6 -1
  135. package/sdk-core/test-utils/src/canned_histories.rs +3 -57
  136. package/sdk-core/test-utils/src/interceptors.rs +46 -0
  137. package/sdk-core/test-utils/src/lib.rs +106 -38
  138. package/sdk-core/tests/integ_tests/metrics_tests.rs +110 -15
  139. package/sdk-core/tests/integ_tests/queries_tests.rs +174 -3
  140. package/sdk-core/tests/integ_tests/update_tests.rs +908 -0
  141. package/sdk-core/tests/integ_tests/visibility_tests.rs +4 -4
  142. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +44 -1
  143. package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +1 -1
  144. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +1 -1
  145. package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +4 -4
  146. package/sdk-core/tests/integ_tests/workflow_tests/eager.rs +61 -0
  147. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +27 -2
  148. package/sdk-core/tests/integ_tests/workflow_tests.rs +142 -3
  149. package/sdk-core/tests/main.rs +2 -1
  150. package/sdk-core/tests/runner.rs +15 -2
  151. package/src/conversions.rs +107 -96
  152. package/src/helpers.rs +74 -0
  153. package/src/runtime.rs +29 -15
  154. package/src/worker.rs +14 -61
  155. package/ts/index.ts +23 -54
  156. package/sdk-core/.buildkite/docker/Dockerfile +0 -9
  157. package/sdk-core/.buildkite/docker/build.sh +0 -5
  158. package/sdk-core/.buildkite/docker/docker-compose-ci.yaml +0 -27
  159. package/sdk-core/.buildkite/pipeline.yml +0 -57
  160. package/sdk-core/.github/workflows/semgrep.yml +0 -25
  161. package/sdk-core/client/LICENSE.txt +0 -23
  162. package/sdk-core/core/LICENSE.txt +0 -23
  163. package/sdk-core/core/src/worker/workflow/bridge.rs +0 -35
  164. package/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +0 -215
  165. package/sdk-core/core-api/LICENSE.txt +0 -23
  166. package/sdk-core/protos/api_upstream/.buildkite/Dockerfile +0 -2
  167. package/sdk-core/protos/api_upstream/Makefile +0 -80
  168. package/sdk-core/protos/api_upstream/api-linter.yaml +0 -40
  169. package/sdk-core/protos/api_upstream/buf.yaml +0 -9
  170. package/sdk-core/protos/api_upstream/build/go.mod +0 -7
  171. package/sdk-core/protos/api_upstream/build/go.sum +0 -5
  172. package/sdk-core/protos/api_upstream/go.mod +0 -6
  173. package/sdk-core/protos/testsrv_upstream/dependencies/gogoproto/gogo.proto +0 -141
  174. package/sdk-core/sdk/LICENSE.txt +0 -23
  175. package/sdk-core/sdk-core-protos/LICENSE.txt +0 -23
  176. /package/sdk-core/{.buildkite/docker → docker}/docker-compose-telem.yaml +0 -0
  177. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.buildkite/docker-compose.yml +0 -0
  178. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.buildkite/pipeline.yml +0 -0
  179. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.github/CODEOWNERS +0 -0
  180. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  181. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.github/workflows/publish-docs.yml +0 -0
  182. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.github/workflows/trigger-api-go-update.yml +0 -0
  183. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/LICENSE +0 -0
  184. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/README.md +0 -0
  185. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/batch_operation.proto +0 -0
  186. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/command_type.proto +0 -0
  187. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/common.proto +0 -0
  188. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/event_type.proto +0 -0
  189. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/namespace.proto +0 -0
  190. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/query.proto +0 -0
  191. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/schedule.proto +0 -0
  192. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/task_queue.proto +0 -0
  193. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/update.proto +0 -0
  194. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/workflow.proto +0 -0
  195. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/errordetails/v1/message.proto +0 -0
  196. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/failure/v1/message.proto +0 -0
  197. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/protocol/v1/message.proto +0 -0
  198. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/query/v1/message.proto +0 -0
  199. /package/sdk-core/{protos → sdk-core-protos/protos}/google/rpc/status.proto +0 -0
  200. /package/sdk-core/{protos → sdk-core-protos/protos}/grpc/health/v1/health.proto +0 -0
  201. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/activity_result/activity_result.proto +0 -0
  202. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/activity_task/activity_task.proto +0 -0
  203. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/child_workflow/child_workflow.proto +0 -0
  204. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/common/common.proto +0 -0
  205. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/core_interface.proto +0 -0
  206. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/external_data/external_data.proto +0 -0
  207. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +0 -0
  208. /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/Makefile +0 -0
  209. /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/api-linter.yaml +0 -0
  210. /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/buf.yaml +0 -0
  211. /package/sdk-core/{protos/api_upstream → sdk-core-protos/protos/testsrv_upstream}/dependencies/gogoproto/gogo.proto +0 -0
  212. /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +0 -0
  213. /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/temporal/api/testservice/v1/service.proto +0 -0
@@ -1,21 +1,17 @@
1
- #[cfg(test)]
2
- mod managed_wf_test;
3
-
4
- #[cfg(test)]
5
- pub(crate) use managed_wf_test::ManagedWFFunc;
6
-
7
1
  use crate::{
8
2
  abstractions::dbg_panic,
9
- protosext::WorkflowActivationExt,
3
+ protosext::{protocol_messages::IncomingProtocolMessage, WorkflowActivationExt},
10
4
  worker::{
11
5
  workflow::{
12
- history_update::HistoryPaginator, machines::WorkflowMachines, ActivationAction,
13
- ActivationCompleteOutcome, ActivationCompleteResult, ActivationOrAuto,
14
- EvictionRequestResult, FailedActivationWFTReport, HeartbeatTimeoutMsg, HistoryUpdate,
15
- LocalActivityRequestSink, LocalResolution, NextPageReq, OutgoingServerCommands,
16
- OutstandingActivation, OutstandingTask, PermittedWFT, RequestEvictMsg, RunBasics,
6
+ history_update::HistoryPaginator,
7
+ machines::{MachinesWFTResponseContent, WorkflowMachines},
8
+ ActivationAction, ActivationCompleteOutcome, ActivationCompleteResult,
9
+ ActivationOrAuto, BufferedTasks, DrivenWorkflow, EvictionRequestResult,
10
+ FailedActivationWFTReport, HeartbeatTimeoutMsg, HistoryUpdate,
11
+ LocalActivityRequestSink, LocalResolution, NextPageReq, OutstandingActivation,
12
+ OutstandingTask, PermittedWFT, RequestEvictMsg, RunBasics,
17
13
  ServerCommandsWithWorkflowInfo, WFCommand, WFMachinesError, WFTReportStatus,
18
- WorkflowBridge, WorkflowTaskInfo, WFT_HEARTBEAT_TIMEOUT_FRACTION,
14
+ WorkflowTaskInfo, WFT_HEARTBEAT_TIMEOUT_FRACTION,
19
15
  },
20
16
  LocalActRequest, LEGACY_QUERY_ID,
21
17
  },
@@ -24,6 +20,7 @@ use crate::{
24
20
  use futures_util::future::AbortHandle;
25
21
  use std::{
26
22
  collections::HashSet,
23
+ mem,
27
24
  ops::Add,
28
25
  rc::Rc,
29
26
  sync::mpsc::Sender,
@@ -51,11 +48,11 @@ pub(super) type RunUpdateAct = Option<ActivationOrAuto>;
51
48
  /// remain that way.
52
49
  #[derive(derive_more::DebugCustom)]
53
50
  #[debug(
54
- fmt = "ManagedRun {{ wft: {:?}, activation: {:?}, buffered_resp: {:?} \
51
+ fmt = "ManagedRun {{ wft: {:?}, activation: {:?}, task_buffer: {:?} \
55
52
  trying_to_evict: {} }}",
56
53
  wft,
57
54
  activation,
58
- buffered_resp,
55
+ task_buffer,
59
56
  "trying_to_evict.is_some()"
60
57
  )]
61
58
  pub(super) struct ManagedRun {
@@ -76,11 +73,14 @@ pub(super) struct ManagedRun {
76
73
  wft: Option<OutstandingTask>,
77
74
  /// An outstanding activation to lang
78
75
  activation: Option<OutstandingActivation>,
79
- /// If set, it indicates there is a buffered poll response from the server that applies to this
80
- /// run. This can happen when lang takes too long to complete a task and the task times out, for
81
- /// example. Upon next completion, the buffered response will be removed and can be made ready
82
- /// to be returned from polling
83
- buffered_resp: Option<PermittedWFT>,
76
+ /// Contains buffered poll responses from the server that apply to this run. This can happen
77
+ /// when:
78
+ /// * Lang takes too long to complete a task and the task times out
79
+ /// * Many queries are submitted concurrently and reach this worker (in this case, multiple
80
+ /// tasks can be outstanding)
81
+ /// * Multiple speculative tasks (ex: for updates) may also exist at once (but only the
82
+ /// latest one will matter).
83
+ task_buffer: BufferedTasks,
84
84
  /// Is set if an eviction has been requested for this run
85
85
  trying_to_evict: Option<RequestEvictMsg>,
86
86
 
@@ -96,24 +96,27 @@ pub(super) struct ManagedRun {
96
96
  impl ManagedRun {
97
97
  pub(super) fn new(
98
98
  basics: RunBasics,
99
+ wft: PermittedWFT,
99
100
  local_activity_request_sink: Rc<dyn LocalActivityRequestSink>,
100
- ) -> Self {
101
+ ) -> (Self, RunUpdateAct) {
101
102
  let metrics = basics.metrics.clone();
102
103
  let wfm = WorkflowManager::new(basics);
103
- Self {
104
+ let mut me = Self {
104
105
  wfm,
105
106
  local_activity_request_sink,
106
107
  waiting_on_la: None,
107
108
  am_broken: false,
108
109
  wft: None,
109
110
  activation: None,
110
- buffered_resp: None,
111
+ task_buffer: Default::default(),
111
112
  trying_to_evict: None,
112
113
  recorded_span_ids: Default::default(),
113
114
  metrics,
114
115
  paginator: None,
115
116
  completion_waiting_on_page_fetch: None,
116
- }
117
+ };
118
+ let rua = me.incoming_wft(wft);
119
+ (me, rua)
117
120
  }
118
121
 
119
122
  /// Returns true if there are pending jobs that need to be sent to lang.
@@ -162,10 +165,10 @@ impl ManagedRun {
162
165
 
163
166
  let work = pwft.work;
164
167
  debug!(
165
- run_id = %work.execution.run_id,
166
168
  task_token = %&work.task_token,
167
169
  update = ?work.update,
168
170
  has_legacy_query = %work.legacy_query.is_some(),
171
+ messages = ?work.messages,
169
172
  attempt = %work.attempt,
170
173
  "Applying new workflow task from server"
171
174
  );
@@ -192,6 +195,7 @@ impl ManagedRun {
192
195
  complete_resp_chan: None,
193
196
  });
194
197
  }
198
+ let was_legacy_query = legacy_query_from_poll.is_some();
195
199
  if let Some(lq) = legacy_query_from_poll {
196
200
  pending_queries.push(lq);
197
201
  }
@@ -204,10 +208,20 @@ impl ManagedRun {
204
208
  permit: pwft.permit,
205
209
  });
206
210
 
211
+ if was_legacy_query
212
+ && work.update.wft_started_id == 0
213
+ && work.update.previous_wft_started_id < self.wfm.machines.get_last_wft_started_id()
214
+ {
215
+ return Ok(Some(ActivationOrAuto::AutoFail {
216
+ run_id: self.run_id().to_string(),
217
+ machines_err: WFMachinesError::Fatal("Query expired".to_string()),
218
+ }));
219
+ }
220
+
207
221
  // The update field is only populated in the event we hit the cache
208
222
  let activation = if work.update.is_real() {
209
223
  self.metrics.sticky_cache_hit();
210
- self.wfm.feed_history_from_server(work.update)?
224
+ self.wfm.new_work_from_server(work.update, work.messages)?
211
225
  } else {
212
226
  let r = self.wfm.get_next_activation()?;
213
227
  if r.jobs.is_empty() {
@@ -266,10 +280,16 @@ impl ManagedRun {
266
280
  let retme = self.wft.take();
267
281
 
268
282
  // Only record latency metrics if we genuinely reported to server
269
- if matches!(report_status, WFTReportStatus::Reported) {
283
+ if let WFTReportStatus::Reported {
284
+ reset_last_started_to,
285
+ } = report_status
286
+ {
270
287
  if let Some(ot) = &retme {
271
288
  self.metrics.wf_task_latency(ot.start_time.elapsed());
272
289
  }
290
+ if let Some(id) = reset_last_started_to {
291
+ self.wfm.machines.reset_last_started_id(id);
292
+ }
273
293
  // Tell the LA manager that we're done with the WFT
274
294
  self.local_activity_request_sink.sink_reqs(vec![
275
295
  LocalActRequest::IndicateWorkflowTaskCompleted(self.wfm.machines.run_id.clone()),
@@ -403,17 +423,18 @@ impl ManagedRun {
403
423
  } else {
404
424
  // First strip out query responses from other commands that actually affect machines
405
425
  // Would be prettier with `drain_filter`
406
- let mut i = 0;
407
426
  let mut query_responses = vec![];
408
- while i < commands.len() {
409
- if matches!(commands[i], WFCommand::QueryResponse(_)) {
410
- if let WFCommand::QueryResponse(qr) = commands.remove(i) {
427
+ commands = std::mem::take(&mut commands)
428
+ .into_iter()
429
+ .filter_map(|x| {
430
+ if let WFCommand::QueryResponse(qr) = x {
411
431
  query_responses.push(qr);
432
+ None
433
+ } else {
434
+ Some(x)
412
435
  }
413
- } else {
414
- i += 1;
415
- }
416
- }
436
+ })
437
+ .collect();
417
438
 
418
439
  if activation_was_only_eviction && !commands.is_empty() {
419
440
  dbg_panic!("Reply to an eviction only containing an eviction included commands");
@@ -491,14 +512,15 @@ impl ManagedRun {
491
512
  }
492
513
 
493
514
  /// Called whenever either core lang cannot complete a workflow activation. EX: Nondeterminism
494
- /// or user code threw/panicked, respectively. The `cause` and `reason` fields are determined
495
- /// inside core always. The `failure` field may come from lang. `resp_chan` will be used to
496
- /// unblock the completion call when everything we need to do to fulfill it has happened.
515
+ /// or user code threw/panicked. The `cause` and `reason` fields are determined inside core
516
+ /// always. The `failure` field may come from lang. `resp_chan` will be used to unblock the
517
+ /// completion call when everything we need to do to fulfill it has happened.
497
518
  pub(super) fn failed_completion(
498
519
  &mut self,
499
520
  cause: WorkflowTaskFailedCause,
500
521
  reason: EvictionReason,
501
522
  failure: workflow_completion::Failure,
523
+ is_auto_fail: bool,
502
524
  resp_chan: Option<oneshot::Sender<ActivationCompleteResult>>,
503
525
  ) -> RunUpdateAct {
504
526
  let tt = if let Some(tt) = self.wft.as_ref().map(|t| t.info.task_token.clone()) {
@@ -514,24 +536,39 @@ impl ManagedRun {
514
536
 
515
537
  self.metrics.wf_task_failed();
516
538
  let message = format!("Workflow activation completion failed: {:?}", &failure);
517
- // Blow up any cached data associated with the workflow
518
- let evict_req_outcome = self.request_eviction(RequestEvictMsg {
519
- run_id: self.run_id().to_string(),
520
- message,
521
- reason,
522
- auto_reply_fail_tt: None,
523
- });
524
- let should_report = match &evict_req_outcome {
525
- EvictionRequestResult::EvictionRequested(Some(attempt), _)
526
- | EvictionRequestResult::EvictionAlreadyRequested(Some(attempt)) => *attempt <= 1,
527
- _ => false,
539
+ // We don't want to fail queries that could otherwise be retried
540
+ let is_no_report_query_fail = self.pending_work_is_legacy_query()
541
+ && is_auto_fail
542
+ && matches!(
543
+ reason,
544
+ EvictionReason::Unspecified | EvictionReason::PaginationOrHistoryFetch
545
+ );
546
+ let (should_report, rur) = if is_no_report_query_fail {
547
+ (false, None)
548
+ } else {
549
+ // Blow up any cached data associated with the workflow
550
+ let evict_req_outcome = self.request_eviction(RequestEvictMsg {
551
+ run_id: self.run_id().to_string(),
552
+ message,
553
+ reason,
554
+ auto_reply_fail_tt: None,
555
+ });
556
+ let should_report = match &evict_req_outcome {
557
+ EvictionRequestResult::EvictionRequested(Some(attempt), _)
558
+ | EvictionRequestResult::EvictionAlreadyRequested(Some(attempt)) => *attempt <= 1,
559
+ _ => false,
560
+ };
561
+ let rur = evict_req_outcome.into_run_update_resp();
562
+ (should_report, rur)
528
563
  };
529
- let rur = evict_req_outcome.into_run_update_resp();
530
- // If the outstanding WFT is a legacy query task, report that we need to fail it
531
564
  let outcome = if self.pending_work_is_legacy_query() {
532
- ActivationCompleteOutcome::ReportWFTFail(
533
- FailedActivationWFTReport::ReportLegacyQueryFailure(tt, failure),
534
- )
565
+ if is_no_report_query_fail {
566
+ ActivationCompleteOutcome::WFTFailedDontReport
567
+ } else {
568
+ ActivationCompleteOutcome::ReportWFTFail(
569
+ FailedActivationWFTReport::ReportLegacyQueryFailure(tt, failure),
570
+ )
571
+ }
535
572
  } else if should_report {
536
573
  ActivationCompleteOutcome::ReportWFTFail(FailedActivationWFTReport::Report(
537
574
  tt, cause, failure,
@@ -543,17 +580,30 @@ impl ManagedRun {
543
580
  rur
544
581
  }
545
582
 
546
- /// Delete the currently tracked workflow activation and return it, if any. Should be called
547
- /// after the processing of the activation completion, and WFT reporting.
548
- pub(super) fn delete_activation(
583
+ /// Must be called after the processing of the activation completion and WFT reporting.
584
+ ///
585
+ /// It will delete the currently tracked workflow activation (if there is one) and `pred`
586
+ /// evaluates to true. In the event the activation was an eviction, the bool part of the return
587
+ /// tuple is true. The [BufferedTasks] part will contain any buffered tasks that may still exist
588
+ /// and need to be instantiated into a new instance of the run, if a `wft_from_complete` was
589
+ /// provided, it will supersede any real WFTs in the buffer as by definition those are now
590
+ /// out-of-date.
591
+ pub(super) fn finish_activation(
549
592
  &mut self,
550
593
  pred: impl FnOnce(&OutstandingActivation) -> bool,
551
- ) -> Option<OutstandingActivation> {
552
- if self.activation().map(pred).unwrap_or_default() {
553
- self.activation.take()
594
+ ) -> (bool, BufferedTasks) {
595
+ let evict = if self.activation().map(pred).unwrap_or_default() {
596
+ let act = self.activation.take();
597
+ act.map(|a| a.has_eviction()).unwrap_or_default()
554
598
  } else {
555
- None
556
- }
599
+ false
600
+ };
601
+ let buffered = if evict {
602
+ mem::take(&mut self.task_buffer)
603
+ } else {
604
+ Default::default()
605
+ };
606
+ (evict, buffered)
557
607
  }
558
608
 
559
609
  /// Called when local activities resolve
@@ -570,7 +620,7 @@ impl ManagedRun {
570
620
  fn _process_completion(
571
621
  &mut self,
572
622
  completion: RunActivationCompletion,
573
- new_update: Option<HistoryUpdate>,
623
+ update_from_new_page: Option<HistoryUpdate>,
574
624
  ) -> Result<Option<FulfillableActivationComplete>, RunUpdateErr> {
575
625
  let data = CompletionDataForWFT {
576
626
  task_token: completion.task_token,
@@ -595,8 +645,7 @@ impl ManagedRun {
595
645
  // Send commands from lang into the machines then check if the workflow run needs
596
646
  // another activation and mark it if so
597
647
  self.wfm.push_commands_and_iterate(completion.commands)?;
598
- // If there was a new update included as part of the completion, apply it.
599
- if let Some(update) = new_update {
648
+ if let Some(update) = update_from_new_page {
600
649
  self.wfm.feed_history_from_new_page(update)?;
601
650
  }
602
651
  // Don't bother applying the next task if we're evicting at the end of this activation
@@ -683,7 +732,7 @@ impl ManagedRun {
683
732
  } else {
684
733
  None
685
734
  };
686
- self.update_to_acts(Ok(maybe_act).map(Into::into))
735
+ self.update_to_acts(Ok(maybe_act.into()))
687
736
  }
688
737
  /// Returns `true` if autocompletion should be issued, which will actually cause us to end up
689
738
  /// in [completion] again, at which point we'll start a new heartbeat timeout, which will
@@ -726,7 +775,7 @@ impl ManagedRun {
726
775
  let buffered = if ignore_buffered {
727
776
  false
728
777
  } else {
729
- self.buffered_resp.is_some()
778
+ self.task_buffer.has_tasks()
730
779
  };
731
780
  trace!(wft=self.wft.is_some(), buffered=?buffered, more_work=?self.more_pending_work(),
732
781
  act_work, evict_work, "Does run have pending work?");
@@ -740,12 +789,11 @@ impl ManagedRun {
740
789
  work: PermittedWFT,
741
790
  ) -> Option<PermittedWFT> {
742
791
  let about_to_issue_evict = self.trying_to_evict.is_some();
743
- let has_wft = self.wft().is_some();
744
792
  let has_activation = self.activation().is_some();
745
- if has_wft || has_activation || about_to_issue_evict || self.more_pending_work() {
793
+ if has_activation || about_to_issue_evict || self.more_pending_work() {
746
794
  debug!(run_id = %self.run_id(),
747
- "Got new WFT for a run with outstanding work, buffering it");
748
- self.buffered_resp = Some(work);
795
+ "Got new WFT for a run with outstanding work, buffering it act: {:?} wft: {:?} about to evict: {:?}", &self.activation(), &self.wft, about_to_issue_evict);
796
+ self.task_buffer.buffer(work);
749
797
  None
750
798
  } else {
751
799
  Some(work)
@@ -754,12 +802,7 @@ impl ManagedRun {
754
802
 
755
803
  /// Returns true if there is a buffered workflow task for this run.
756
804
  pub(super) fn has_buffered_wft(&self) -> bool {
757
- self.buffered_resp.is_some()
758
- }
759
-
760
- /// Removes and returns the buffered workflow task, if any.
761
- pub(super) fn take_buffered_wft(&mut self) -> Option<PermittedWFT> {
762
- self.buffered_resp.take()
805
+ self.task_buffer.has_tasks()
763
806
  }
764
807
 
765
808
  pub(super) fn request_eviction(&mut self, info: RequestEvictMsg) -> EvictionRequestResult {
@@ -776,6 +819,7 @@ impl ManagedRun {
776
819
  WorkflowTaskFailedCause::Unspecified,
777
820
  info.reason,
778
821
  Failure::application_failure(info.message, false).into(),
822
+ true,
779
823
  c.resp_chan,
780
824
  );
781
825
  return EvictionRequestResult::EvictionRequested(attempts, run_upd);
@@ -799,6 +843,7 @@ impl ManagedRun {
799
843
  }
800
844
  self.recorded_span_ids.insert(spid);
801
845
 
846
+ span.record("run_id", self.run_id());
802
847
  if let Some(wid) = self.wft().map(|wft| &wft.info.wf_id) {
803
848
  span.record("workflow_id", wid.as_str());
804
849
  }
@@ -868,11 +913,11 @@ impl ManagedRun {
868
913
  }
869
914
 
870
915
  match r {
871
- // After each run update, check if it's ready to handle any buffered poll
916
+ // After each run update, check if it's ready to handle any buffered task
872
917
  None | Some(ActivationOrAuto::Autocomplete { .. })
873
918
  if !self.has_any_pending_work(false, true) =>
874
919
  {
875
- if let Some(bufft) = self.buffered_resp.take() {
920
+ if let Some(bufft) = self.task_buffer.get_next_wft() {
876
921
  self.incoming_wft(bufft)
877
922
  } else {
878
923
  None
@@ -899,6 +944,7 @@ impl ManagedRun {
899
944
  fail_cause,
900
945
  fail.source.evict_reason(),
901
946
  Failure::application_failure(wft_fail_str, false).into(),
947
+ true,
902
948
  Some(resp_chan),
903
949
  )
904
950
  } else {
@@ -946,18 +992,16 @@ impl ManagedRun {
946
992
  data: CompletionDataForWFT,
947
993
  due_to_heartbeat_timeout: bool,
948
994
  ) -> FulfillableActivationComplete {
949
- let mut outgoing_cmds = self.wfm.get_server_commands();
950
- if data.activation_was_only_eviction && !outgoing_cmds.commands.is_empty() {
951
- if self.am_broken {
952
- // If we broke there could be commands in the pipe that we didn't get a chance to
953
- // handle properly during replay, just wipe them all out.
954
- outgoing_cmds.commands = vec![];
955
- } else {
956
- dbg_panic!(
957
- "There should not be any outgoing commands when preparing a completion response \
958
- if the activation was only an eviction. This is an SDK bug."
959
- );
960
- }
995
+ let mut machines_wft_response = self.wfm.prepare_for_wft_response();
996
+ if data.activation_was_only_eviction
997
+ && (machines_wft_response.commands().peek().is_some()
998
+ || machines_wft_response.has_messages())
999
+ && !self.am_broken
1000
+ {
1001
+ dbg_panic!(
1002
+ "There should not be any outgoing commands or messages when preparing a completion \
1003
+ response if the activation was only an eviction. This is an SDK bug."
1004
+ );
961
1005
  }
962
1006
 
963
1007
  let query_responses = data.query_responses;
@@ -970,34 +1014,50 @@ impl ManagedRun {
970
1014
  // saw the final event in the workflow, or if we are playing back for the express purpose of
971
1015
  // fulfilling a query. If the activation we sent was *only* an eviction, don't send that
972
1016
  // either.
973
- let should_respond = !(self.wfm.machines.has_pending_jobs()
974
- || outgoing_cmds.replaying
1017
+ let should_respond = !(machines_wft_response.has_pending_jobs
1018
+ || machines_wft_response.replaying
975
1019
  || is_query_playback
976
1020
  || data.activation_was_only_eviction
977
- || self.wfm.machines.have_seen_terminal_event);
1021
+ || machines_wft_response.have_seen_terminal_event);
978
1022
  // If there are pending LA resolutions, and we're responding to a query here,
979
1023
  // we want to make sure to force a new task, as otherwise once we tell lang about
980
1024
  // the LA resolution there wouldn't be any task to reply to with the result of iterating
981
1025
  // the workflow.
982
- if has_query_responses && self.wfm.machines.has_pending_la_resolutions() {
1026
+ if has_query_responses && machines_wft_response.have_pending_la_resolutions {
983
1027
  force_new_wft = true;
984
1028
  }
985
1029
 
986
1030
  let outcome = if should_respond || has_query_responses {
1031
+ // If we broke there could be commands or messages in the pipe that we didn't
1032
+ // get a chance to handle properly during replay. Don't send them.
1033
+ let (commands, messages) = if self.am_broken && data.activation_was_only_eviction {
1034
+ (vec![], vec![])
1035
+ } else {
1036
+ (
1037
+ machines_wft_response.commands().collect(),
1038
+ machines_wft_response.messages(),
1039
+ )
1040
+ };
1041
+
987
1042
  ActivationCompleteOutcome::ReportWFTSuccess(ServerCommandsWithWorkflowInfo {
988
1043
  task_token: data.task_token,
989
1044
  action: ActivationAction::WftComplete {
990
1045
  force_new_wft,
991
- commands: outgoing_cmds.commands,
1046
+ commands,
1047
+ messages,
992
1048
  query_responses,
993
- sdk_metadata: self.wfm.machines.get_metadata_for_wft_complete(),
1049
+ sdk_metadata: machines_wft_response.metadata_for_complete(),
994
1050
  },
995
1051
  })
996
1052
  } else {
997
1053
  ActivationCompleteOutcome::DoNothing
998
1054
  };
999
1055
  FulfillableActivationComplete {
1000
- result: self.build_activation_complete_result(outcome),
1056
+ result: ActivationCompleteResult {
1057
+ outcome,
1058
+ most_recently_processed_event: machines_wft_response.last_processed_event as usize,
1059
+ replaying: machines_wft_response.replaying,
1060
+ },
1001
1061
  resp_chan,
1002
1062
  }
1003
1063
  }
@@ -1023,7 +1083,12 @@ impl ManagedRun {
1023
1083
  ) {
1024
1084
  if let Some(chan) = chan {
1025
1085
  if chan
1026
- .send(self.build_activation_complete_result(outcome))
1086
+ .send(ActivationCompleteResult {
1087
+ outcome,
1088
+ most_recently_processed_event: self.most_recently_processed_event_number()
1089
+ as usize,
1090
+ replaying: self.wfm.machines.replaying,
1091
+ })
1027
1092
  .is_err()
1028
1093
  {
1029
1094
  let warnstr = "The workflow task completer went missing! This likely indicates an \
@@ -1040,17 +1105,6 @@ impl ManagedRun {
1040
1105
  }
1041
1106
  }
1042
1107
 
1043
- fn build_activation_complete_result(
1044
- &self,
1045
- outcome: ActivationCompleteOutcome,
1046
- ) -> ActivationCompleteResult {
1047
- ActivationCompleteResult {
1048
- outcome,
1049
- most_recently_processed_event: self.most_recently_processed_event_number() as usize,
1050
- replaying: self.wfm.machines.replaying,
1051
- }
1052
- }
1053
-
1054
1108
  /// Returns true if the handle is currently processing a WFT which contains a legacy query.
1055
1109
  fn pending_work_is_legacy_query(&self) -> bool {
1056
1110
  // Either we know because there is a pending legacy query, or it's already been drained and
@@ -1160,33 +1214,30 @@ impl WorkflowManager {
1160
1214
  /// Create a new workflow manager given workflow history and execution info as would be found
1161
1215
  /// in [PollWorkflowTaskQueueResponse]
1162
1216
  fn new(basics: RunBasics) -> Self {
1163
- let (wfb, cmd_sink) = WorkflowBridge::new();
1164
- let state_machines = WorkflowMachines::new(basics, Box::new(wfb).into());
1217
+ let (wfb, cmd_sink) = DrivenWorkflow::new();
1218
+ let state_machines = WorkflowMachines::new(basics, wfb);
1165
1219
  Self {
1166
1220
  machines: state_machines,
1167
1221
  command_sink: Some(cmd_sink),
1168
1222
  }
1169
1223
  }
1170
1224
 
1171
- #[cfg(test)]
1172
- const fn new_from_machines(workflow_machines: WorkflowMachines) -> Self {
1173
- Self {
1174
- machines: workflow_machines,
1175
- command_sink: None,
1176
- }
1177
- }
1178
-
1179
- /// Given history that was just obtained from the server, pipe it into this workflow's machines.
1225
+ /// Given info that was just obtained from a new WFT from server, pipe it into this workflow's
1226
+ /// machines.
1180
1227
  ///
1181
1228
  /// Should only be called when a workflow has caught up on replay (or is just beginning). It
1182
1229
  /// will return a workflow activation if one is needed.
1183
- fn feed_history_from_server(&mut self, update: HistoryUpdate) -> Result<WorkflowActivation> {
1184
- self.machines.new_history_from_server(update)?;
1230
+ fn new_work_from_server(
1231
+ &mut self,
1232
+ update: HistoryUpdate,
1233
+ messages: Vec<IncomingProtocolMessage>,
1234
+ ) -> Result<WorkflowActivation> {
1235
+ self.machines.new_work_from_server(update, messages)?;
1185
1236
  self.get_next_activation()
1186
1237
  }
1187
1238
 
1188
1239
  /// Update the machines with some events from fetching another page of history. Does *not*
1189
- /// attempt to pull the next activation, unlike [Self::feed_history_from_server].
1240
+ /// attempt to pull the next activation, unlike [Self::new_work_from_server].
1190
1241
  fn feed_history_from_new_page(&mut self, update: HistoryUpdate) -> Result<()> {
1191
1242
  self.machines.new_history_from_server(update)
1192
1243
  }
@@ -1243,14 +1294,10 @@ impl WorkflowManager {
1243
1294
  Ok(self.machines.has_pending_jobs())
1244
1295
  }
1245
1296
 
1246
- /// Typically called after [get_next_activation], use this to retrieve commands to be sent to
1247
- /// the server which have been generated by the machines. Does *not* drain those commands.
1248
- /// See [WorkflowMachines::get_commands].
1249
- fn get_server_commands(&self) -> OutgoingServerCommands {
1250
- OutgoingServerCommands {
1251
- commands: self.machines.get_commands(),
1252
- replaying: self.machines.replaying,
1253
- }
1297
+ /// Must be called when we're ready to respond to a WFT after handling catching up on replay
1298
+ /// and handling all activation completions from lang.
1299
+ fn prepare_for_wft_response(&mut self) -> MachinesWFTResponseContent {
1300
+ self.machines.prepare_for_wft_response()
1254
1301
  }
1255
1302
 
1256
1303
  /// Remove and return all queued local activities. Once this is called, they need to be