@temporalio/core-bridge 1.14.2-canary-release-testing.0 → 1.16.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 (233) hide show
  1. package/Cargo.lock +794 -650
  2. package/bridge-macros/src/derive_tryintojs.rs +40 -0
  3. package/lib/native.d.ts +24 -3
  4. package/package.json +4 -4
  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/.github/workflows/per-pr.yml +6 -6
  11. package/sdk-core/AGENTS.md +42 -31
  12. package/sdk-core/Cargo.toml +4 -1
  13. package/sdk-core/README.md +19 -13
  14. package/sdk-core/crates/client/Cargo.toml +4 -0
  15. package/sdk-core/crates/client/README.md +139 -0
  16. package/sdk-core/crates/client/src/async_activity_handle.rs +297 -0
  17. package/sdk-core/crates/client/src/callback_based.rs +7 -0
  18. package/sdk-core/crates/client/src/errors.rs +294 -0
  19. package/sdk-core/crates/client/src/{raw.rs → grpc.rs} +370 -159
  20. package/sdk-core/crates/client/src/lib.rs +920 -1326
  21. package/sdk-core/crates/client/src/metrics.rs +24 -33
  22. package/sdk-core/crates/client/src/options_structs.rs +457 -0
  23. package/sdk-core/crates/client/src/replaceable.rs +5 -4
  24. package/sdk-core/crates/client/src/request_extensions.rs +8 -9
  25. package/sdk-core/crates/client/src/retry.rs +99 -54
  26. package/sdk-core/crates/client/src/{worker/mod.rs → worker.rs} +104 -29
  27. package/sdk-core/crates/client/src/workflow_handle.rs +826 -0
  28. package/sdk-core/crates/common/Cargo.toml +62 -3
  29. package/sdk-core/crates/common/build.rs +742 -12
  30. package/sdk-core/crates/common/protos/api_upstream/.github/workflows/ci.yml +2 -0
  31. package/sdk-core/crates/common/protos/api_upstream/.github/workflows/create-release.yml +0 -5
  32. package/sdk-core/crates/common/protos/api_upstream/Makefile +2 -1
  33. package/sdk-core/crates/common/protos/api_upstream/README.md +8 -0
  34. package/sdk-core/crates/common/protos/api_upstream/cmd/check-path-conflicts/main.go +137 -0
  35. package/sdk-core/crates/common/protos/api_upstream/openapi/openapiv2.json +3329 -2647
  36. package/sdk-core/crates/common/protos/api_upstream/openapi/openapiv3.yaml +2734 -708
  37. package/sdk-core/crates/common/protos/api_upstream/temporal/api/activity/v1/message.proto +155 -3
  38. package/sdk-core/crates/common/protos/api_upstream/temporal/api/command/v1/message.proto +26 -0
  39. package/sdk-core/crates/common/protos/api_upstream/temporal/api/common/v1/message.proto +8 -1
  40. package/sdk-core/crates/common/protos/api_upstream/temporal/api/deployment/v1/message.proto +27 -1
  41. package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/activity.proto +81 -0
  42. package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/event_type.proto +4 -0
  43. package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +4 -0
  44. package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +15 -0
  45. package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/workflow.proto +63 -15
  46. package/sdk-core/crates/common/protos/api_upstream/temporal/api/errordetails/v1/message.proto +8 -0
  47. package/sdk-core/crates/common/protos/api_upstream/temporal/api/failure/v1/message.proto +1 -0
  48. package/sdk-core/crates/common/protos/api_upstream/temporal/api/history/v1/message.proto +111 -17
  49. package/sdk-core/crates/common/protos/api_upstream/temporal/api/namespace/v1/message.proto +21 -0
  50. package/sdk-core/crates/common/protos/api_upstream/temporal/api/nexus/v1/message.proto +20 -1
  51. package/sdk-core/crates/common/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +4 -0
  52. package/sdk-core/crates/common/protos/api_upstream/temporal/api/schedule/v1/message.proto +2 -2
  53. package/sdk-core/crates/common/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +2 -0
  54. package/sdk-core/crates/common/protos/api_upstream/temporal/api/worker/v1/message.proto +4 -7
  55. package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflow/v1/message.proto +80 -22
  56. package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +347 -23
  57. package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +242 -43
  58. package/sdk-core/crates/common/protos/local/temporal/sdk/core/core_interface.proto +15 -0
  59. package/sdk-core/crates/common/protos/local/temporal/sdk/core/nexus/nexus.proto +9 -2
  60. package/sdk-core/crates/common/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +8 -0
  61. package/sdk-core/crates/common/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +22 -5
  62. package/sdk-core/crates/common/src/activity_definition.rs +20 -0
  63. package/sdk-core/crates/common/src/data_converters.rs +770 -0
  64. package/sdk-core/crates/common/src/envconfig.rs +5 -0
  65. package/sdk-core/crates/common/src/lib.rs +15 -211
  66. package/sdk-core/crates/common/src/payload_visitor.rs +648 -0
  67. package/sdk-core/crates/common/src/priority.rs +110 -0
  68. package/sdk-core/crates/common/src/protos/canned_histories.rs +19 -0
  69. package/sdk-core/crates/common/src/protos/history_builder.rs +45 -0
  70. package/sdk-core/crates/common/src/protos/history_info.rs +2 -0
  71. package/sdk-core/crates/common/src/protos/mod.rs +134 -27
  72. package/sdk-core/crates/common/src/protos/task_token.rs +3 -3
  73. package/sdk-core/crates/common/src/protos/utilities.rs +11 -0
  74. package/sdk-core/crates/{sdk-core → common}/src/telemetry/log_export.rs +11 -16
  75. package/sdk-core/crates/common/src/telemetry/metrics/core.rs +125 -0
  76. package/sdk-core/crates/common/src/telemetry/metrics.rs +272 -225
  77. package/sdk-core/crates/{sdk-core → common}/src/telemetry/otel.rs +8 -13
  78. package/sdk-core/crates/{sdk-core → common}/src/telemetry/prometheus_meter.rs +49 -50
  79. package/sdk-core/crates/{sdk-core → common}/src/telemetry/prometheus_server.rs +2 -3
  80. package/sdk-core/crates/common/src/telemetry.rs +278 -19
  81. package/sdk-core/crates/common/src/worker.rs +68 -636
  82. package/sdk-core/crates/common/src/workflow_definition.rs +60 -0
  83. package/sdk-core/crates/macros/Cargo.toml +5 -1
  84. package/sdk-core/crates/macros/src/activities_definitions.rs +585 -0
  85. package/sdk-core/crates/macros/src/fsm_impl.rs +507 -0
  86. package/sdk-core/crates/macros/src/lib.rs +138 -512
  87. package/sdk-core/crates/macros/src/macro_utils.rs +106 -0
  88. package/sdk-core/crates/macros/src/workflow_definitions.rs +1224 -0
  89. package/sdk-core/crates/sdk/Cargo.toml +19 -6
  90. package/sdk-core/crates/sdk/README.md +415 -0
  91. package/sdk-core/crates/sdk/src/activities.rs +417 -0
  92. package/sdk-core/crates/sdk/src/interceptors.rs +1 -1
  93. package/sdk-core/crates/sdk/src/lib.rs +759 -442
  94. package/sdk-core/crates/sdk/src/workflow_context/options.rs +64 -35
  95. package/sdk-core/crates/sdk/src/workflow_context.rs +1033 -289
  96. package/sdk-core/crates/sdk/src/workflow_future.rs +277 -213
  97. package/sdk-core/crates/sdk/src/workflows.rs +711 -0
  98. package/sdk-core/crates/sdk-core/Cargo.toml +59 -65
  99. package/sdk-core/crates/sdk-core/benches/workflow_replay_bench.rs +45 -54
  100. package/sdk-core/crates/sdk-core/machine_coverage/ActivityMachine_Coverage.puml +1 -1
  101. package/sdk-core/crates/sdk-core/src/abstractions.rs +6 -10
  102. package/sdk-core/crates/sdk-core/src/core_tests/activity_tasks.rs +6 -5
  103. package/sdk-core/crates/sdk-core/src/core_tests/mod.rs +22 -21
  104. package/sdk-core/crates/sdk-core/src/core_tests/queries.rs +21 -25
  105. package/sdk-core/crates/sdk-core/src/core_tests/replay_flag.rs +7 -10
  106. package/sdk-core/crates/sdk-core/src/core_tests/updates.rs +14 -17
  107. package/sdk-core/crates/sdk-core/src/core_tests/workers.rs +647 -27
  108. package/sdk-core/crates/sdk-core/src/core_tests/workflow_tasks.rs +46 -41
  109. package/sdk-core/crates/sdk-core/src/ephemeral_server/mod.rs +13 -16
  110. package/sdk-core/crates/sdk-core/src/histfetch.rs +20 -10
  111. package/sdk-core/crates/sdk-core/src/lib.rs +60 -123
  112. package/sdk-core/crates/sdk-core/src/pollers/mod.rs +4 -9
  113. package/sdk-core/crates/sdk-core/src/pollers/poll_buffer.rs +411 -32
  114. package/sdk-core/crates/sdk-core/src/protosext/mod.rs +2 -2
  115. package/sdk-core/crates/sdk-core/src/replay/mod.rs +14 -5
  116. package/sdk-core/crates/sdk-core/src/telemetry/metrics.rs +183 -198
  117. package/sdk-core/crates/sdk-core/src/telemetry/mod.rs +3 -281
  118. package/sdk-core/crates/sdk-core/src/test_help/integ_helpers.rs +35 -16
  119. package/sdk-core/crates/sdk-core/src/test_help/unit_helpers.rs +3 -6
  120. package/sdk-core/crates/sdk-core/src/worker/activities/activity_heartbeat_manager.rs +1 -0
  121. package/sdk-core/crates/sdk-core/src/worker/activities/local_activities.rs +11 -14
  122. package/sdk-core/crates/sdk-core/src/worker/activities.rs +16 -19
  123. package/sdk-core/crates/sdk-core/src/worker/client/mocks.rs +11 -5
  124. package/sdk-core/crates/sdk-core/src/worker/client.rs +104 -86
  125. package/sdk-core/crates/sdk-core/src/worker/heartbeat.rs +10 -14
  126. package/sdk-core/crates/sdk-core/src/worker/mod.rs +1175 -241
  127. package/sdk-core/crates/sdk-core/src/worker/nexus.rs +150 -23
  128. package/sdk-core/crates/sdk-core/src/worker/slot_provider.rs +2 -2
  129. package/sdk-core/crates/sdk-core/src/worker/tuner/fixed_size.rs +2 -2
  130. package/sdk-core/crates/sdk-core/src/worker/tuner/resource_based.rs +25 -27
  131. package/sdk-core/crates/sdk-core/src/worker/tuner.rs +64 -44
  132. package/sdk-core/crates/sdk-core/src/worker/workflow/driven_workflow.rs +9 -3
  133. package/sdk-core/crates/sdk-core/src/worker/workflow/machines/patch_state_machine.rs +5 -8
  134. package/sdk-core/crates/sdk-core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +21 -22
  135. package/sdk-core/crates/sdk-core/src/worker/workflow/machines/workflow_machines.rs +28 -4
  136. package/sdk-core/crates/sdk-core/src/worker/workflow/managed_run.rs +20 -41
  137. package/sdk-core/crates/sdk-core/src/worker/workflow/mod.rs +50 -9
  138. package/sdk-core/crates/sdk-core/src/worker/workflow/run_cache.rs +4 -7
  139. package/sdk-core/crates/sdk-core/src/worker/workflow/wft_extraction.rs +2 -4
  140. package/sdk-core/crates/sdk-core/src/worker/workflow/wft_poller.rs +8 -9
  141. package/sdk-core/crates/sdk-core/src/worker/workflow/workflow_stream.rs +1 -3
  142. package/sdk-core/crates/sdk-core/tests/activities_procmacro.rs +6 -0
  143. package/sdk-core/crates/sdk-core/tests/activities_trybuild/basic_pass.rs +54 -0
  144. package/sdk-core/crates/sdk-core/tests/activities_trybuild/invalid_self_type_fail.rs +18 -0
  145. package/sdk-core/crates/sdk-core/tests/activities_trybuild/invalid_self_type_fail.stderr +5 -0
  146. package/sdk-core/crates/sdk-core/tests/activities_trybuild/missing_context_fail.rs +14 -0
  147. package/sdk-core/crates/sdk-core/tests/activities_trybuild/missing_context_fail.stderr +5 -0
  148. package/sdk-core/crates/sdk-core/tests/activities_trybuild/multi_arg_pass.rs +48 -0
  149. package/sdk-core/crates/sdk-core/tests/activities_trybuild/no_input_pass.rs +14 -0
  150. package/sdk-core/crates/sdk-core/tests/activities_trybuild/no_return_type_pass.rs +19 -0
  151. package/sdk-core/crates/sdk-core/tests/cloud_tests.rs +14 -5
  152. package/sdk-core/crates/sdk-core/tests/common/activity_functions.rs +55 -0
  153. package/sdk-core/crates/sdk-core/tests/common/mod.rs +281 -236
  154. package/sdk-core/crates/sdk-core/tests/common/workflows.rs +41 -28
  155. package/sdk-core/crates/sdk-core/tests/global_metric_tests.rs +9 -14
  156. package/sdk-core/crates/sdk-core/tests/heavy_tests/fuzzy_workflow.rs +73 -66
  157. package/sdk-core/crates/sdk-core/tests/heavy_tests.rs +306 -268
  158. package/sdk-core/crates/sdk-core/tests/integ_tests/async_activity_client_tests.rs +230 -0
  159. package/sdk-core/crates/sdk-core/tests/integ_tests/client_tests.rs +94 -57
  160. package/sdk-core/crates/sdk-core/tests/integ_tests/data_converter_tests.rs +381 -0
  161. package/sdk-core/crates/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +37 -38
  162. package/sdk-core/crates/sdk-core/tests/integ_tests/heartbeat_tests.rs +49 -40
  163. package/sdk-core/crates/sdk-core/tests/integ_tests/metrics_tests.rs +447 -300
  164. package/sdk-core/crates/sdk-core/tests/integ_tests/pagination_tests.rs +50 -45
  165. package/sdk-core/crates/sdk-core/tests/integ_tests/polling_tests.rs +157 -157
  166. package/sdk-core/crates/sdk-core/tests/integ_tests/queries_tests.rs +103 -89
  167. package/sdk-core/crates/sdk-core/tests/integ_tests/update_tests.rs +609 -463
  168. package/sdk-core/crates/sdk-core/tests/integ_tests/visibility_tests.rs +80 -62
  169. package/sdk-core/crates/sdk-core/tests/integ_tests/worker_heartbeat_tests.rs +389 -265
  170. package/sdk-core/crates/sdk-core/tests/integ_tests/worker_tests.rs +250 -185
  171. package/sdk-core/crates/sdk-core/tests/integ_tests/worker_versioning_tests.rs +52 -49
  172. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_client_tests.rs +180 -0
  173. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/activities.rs +437 -327
  174. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +82 -58
  175. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +56 -30
  176. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +364 -251
  177. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/client_interactions.rs +552 -0
  178. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +110 -46
  179. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +243 -149
  180. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/eager.rs +98 -32
  181. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +1475 -1040
  182. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +73 -43
  183. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/nexus.rs +402 -245
  184. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/patches.rs +343 -207
  185. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/queries.rs +415 -0
  186. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/replay.rs +96 -36
  187. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/resets.rs +155 -140
  188. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/signals.rs +183 -113
  189. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +85 -44
  190. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/timers.rs +142 -48
  191. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +73 -56
  192. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests.rs +365 -242
  193. package/sdk-core/crates/sdk-core/tests/main.rs +22 -16
  194. package/sdk-core/crates/sdk-core/tests/manual_tests.rs +233 -187
  195. package/sdk-core/crates/sdk-core/tests/runner.rs +4 -6
  196. package/sdk-core/crates/sdk-core/tests/shared_tests/mod.rs +73 -27
  197. package/sdk-core/crates/sdk-core/tests/shared_tests/priority.rs +107 -84
  198. package/sdk-core/crates/sdk-core/tests/workflows_procmacro.rs +6 -0
  199. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/async_query_fail.rs +26 -0
  200. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/async_query_fail.stderr +5 -0
  201. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/basic_pass.rs +49 -0
  202. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/minimal_pass.rs +21 -0
  203. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/mut_query_fail.rs +26 -0
  204. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/mut_query_fail.stderr +5 -0
  205. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/sync_run_fail.rs +21 -0
  206. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/sync_run_fail.stderr +5 -0
  207. package/sdk-core/crates/sdk-core-c-bridge/Cargo.toml +8 -1
  208. package/sdk-core/crates/sdk-core-c-bridge/include/temporal-sdk-core-c-bridge.h +37 -26
  209. package/sdk-core/crates/sdk-core-c-bridge/src/client.rs +180 -87
  210. package/sdk-core/crates/sdk-core-c-bridge/src/lib.rs +89 -5
  211. package/sdk-core/crates/sdk-core-c-bridge/src/metric.rs +10 -16
  212. package/sdk-core/crates/sdk-core-c-bridge/src/runtime.rs +59 -67
  213. package/sdk-core/crates/sdk-core-c-bridge/src/testing.rs +10 -10
  214. package/sdk-core/crates/sdk-core-c-bridge/src/tests/context.rs +57 -22
  215. package/sdk-core/crates/sdk-core-c-bridge/src/tests/mod.rs +108 -12
  216. package/sdk-core/crates/sdk-core-c-bridge/src/tests/utils.rs +9 -52
  217. package/sdk-core/crates/sdk-core-c-bridge/src/worker.rs +74 -91
  218. package/sdk-core/rustfmt.toml +2 -1
  219. package/src/client.rs +206 -289
  220. package/src/helpers/try_into_js.rs +88 -2
  221. package/src/metrics.rs +277 -35
  222. package/src/runtime.rs +94 -45
  223. package/src/testing.rs +9 -16
  224. package/src/worker.rs +86 -68
  225. package/ts/native.ts +39 -3
  226. package/sdk-core/crates/client/src/workflow_handle/mod.rs +0 -212
  227. package/sdk-core/crates/common/src/errors.rs +0 -85
  228. package/sdk-core/crates/common/tests/worker_task_types_test.rs +0 -129
  229. package/sdk-core/crates/macros/LICENSE.txt +0 -21
  230. package/sdk-core/crates/sdk/src/activity_context.rs +0 -238
  231. package/sdk-core/crates/sdk/src/app_data.rs +0 -37
  232. package/sdk-core/crates/sdk-core/tests/integ_tests/activity_functions.rs +0 -5
  233. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/appdata_propagation.rs +0 -61
@@ -1,13 +1,21 @@
1
1
  use crate::{
2
- ERROR_RETURNED_DUE_TO_SHORT_CIRCUIT, MESSAGE_TOO_LARGE_KEY, NamespacedClient, Result,
3
- RetryOptions,
4
- raw::IsUserLongPoll,
2
+ ERROR_RETURNED_DUE_TO_SHORT_CIRCUIT, MESSAGE_TOO_LARGE_KEY,
3
+ grpc::IsUserLongPoll,
5
4
  request_extensions::{IsWorkerTaskLongPoll, NoRetryOnMatching, RetryConfigForCall},
6
5
  };
7
- use backoff::{Clock, SystemClock, backoff::Backoff, exponential::ExponentialBackoff};
6
+ use backoff::{
7
+ Clock, SystemClock,
8
+ backoff::Backoff,
9
+ exponential::{self, ExponentialBackoff},
10
+ };
8
11
  use futures_retry::{ErrorHandler, FutureRetry, RetryPolicy};
9
- use std::{error::Error, fmt::Debug, future::Future, sync::Arc, time::Duration};
10
- use tonic::{Code, Request};
12
+ use std::{
13
+ error::Error,
14
+ fmt::Debug,
15
+ future::Future,
16
+ time::{Duration, Instant},
17
+ };
18
+ use tonic::Code;
11
19
 
12
20
  /// List of gRPC error codes that client will retry.
13
21
  #[doc(hidden)]
@@ -22,44 +30,77 @@ pub const RETRYABLE_ERROR_CODES: [Code; 7] = [
22
30
  ];
23
31
  const LONG_POLL_FATAL_GRACE: Duration = Duration::from_secs(60);
24
32
 
25
- /// A wrapper for a [crate::WorkflowClientTrait] or [crate::WorkflowService] implementor which
26
- /// performs auto-retries
27
- #[derive(Debug, Clone)]
28
- pub struct RetryClient<SG> {
29
- client: SG,
30
- retry_config: Arc<RetryOptions>,
33
+ /// Configuration for retrying requests to the server
34
+ #[derive(Clone, Debug, PartialEq)]
35
+ pub struct RetryOptions {
36
+ /// initial wait time before the first retry.
37
+ pub initial_interval: Duration,
38
+ /// randomization jitter that is used as a multiplier for the current retry interval
39
+ /// and is added or subtracted from the interval length.
40
+ pub randomization_factor: f64,
41
+ /// rate at which retry time should be increased, until it reaches max_interval.
42
+ pub multiplier: f64,
43
+ /// maximum amount of time to wait between retries.
44
+ pub max_interval: Duration,
45
+ /// maximum total amount of time requests should be retried for, if None is set then no limit
46
+ /// will be used.
47
+ pub max_elapsed_time: Option<Duration>,
48
+ /// maximum number of retry attempts.
49
+ pub max_retries: usize,
31
50
  }
32
51
 
33
- impl<SG> RetryClient<SG> {
34
- /// Use the provided retry config with the provided client
35
- pub fn new(client: SG, retry_config: RetryOptions) -> Self {
52
+ impl Default for RetryOptions {
53
+ fn default() -> Self {
36
54
  Self {
37
- client,
38
- retry_config: Arc::new(retry_config),
55
+ initial_interval: Duration::from_millis(100), // 100 ms wait by default.
56
+ randomization_factor: 0.2, // +-20% jitter.
57
+ multiplier: 1.7, // each next retry delay will increase by 70%
58
+ max_interval: Duration::from_secs(5), // until it reaches 5 seconds.
59
+ max_elapsed_time: Some(Duration::from_secs(10)), // 10 seconds total allocated time for all retries.
60
+ max_retries: 10,
39
61
  }
40
62
  }
41
63
  }
42
64
 
43
- impl<SG> RetryClient<SG> {
44
- /// Return the inner client type
45
- pub fn get_client(&self) -> &SG {
46
- &self.client
65
+ impl RetryOptions {
66
+ pub(crate) const fn task_poll_retry_policy() -> Self {
67
+ Self {
68
+ initial_interval: Duration::from_millis(200),
69
+ randomization_factor: 0.2,
70
+ multiplier: 2.0,
71
+ max_interval: Duration::from_secs(10),
72
+ max_elapsed_time: None,
73
+ max_retries: 0,
74
+ }
47
75
  }
48
76
 
49
- /// Return the inner client type mutably
50
- pub fn get_client_mut(&mut self) -> &mut SG {
51
- &mut self.client
77
+ pub(crate) const fn throttle_retry_policy() -> Self {
78
+ Self {
79
+ initial_interval: Duration::from_secs(1),
80
+ randomization_factor: 0.2,
81
+ multiplier: 2.0,
82
+ max_interval: Duration::from_secs(10),
83
+ max_elapsed_time: None,
84
+ max_retries: 0,
85
+ }
52
86
  }
53
87
 
54
- /// Disable retry and return the inner client type
55
- pub fn into_inner(self) -> SG {
56
- self.client
88
+ /// A retry policy that never retires
89
+ pub const fn no_retries() -> Self {
90
+ Self {
91
+ initial_interval: Duration::from_secs(0),
92
+ randomization_factor: 0.0,
93
+ multiplier: 1.0,
94
+ max_interval: Duration::from_secs(0),
95
+ max_elapsed_time: None,
96
+ max_retries: 1,
97
+ }
57
98
  }
58
99
 
59
100
  pub(crate) fn get_call_info<R>(
60
101
  &self,
61
102
  call_name: &'static str,
62
- request: Option<&Request<R>>,
103
+ request: Option<&tonic::Request<R>>,
63
104
  ) -> CallInfo {
64
105
  let mut call_type = CallType::Normal;
65
106
  let mut retry_short_circuit = None;
@@ -80,7 +121,7 @@ impl<SG> RetryClient<SG> {
80
121
  } else if call_type == CallType::TaskLongPoll {
81
122
  RetryOptions::task_poll_retry_policy()
82
123
  } else {
83
- (*self.retry_config).clone()
124
+ self.clone()
84
125
  };
85
126
  CallInfo {
86
127
  call_type,
@@ -90,32 +131,38 @@ impl<SG> RetryClient<SG> {
90
131
  }
91
132
  }
92
133
 
93
- pub(crate) fn make_future_retry<R, F, Fut>(
94
- info: CallInfo,
95
- factory: F,
96
- ) -> FutureRetry<F, TonicErrorHandler<SystemClock>>
97
- where
98
- F: FnMut() -> Fut + Unpin,
99
- Fut: Future<Output = Result<R>>,
100
- {
101
- FutureRetry::new(
102
- factory,
103
- TonicErrorHandler::new(info, RetryOptions::throttle_retry_policy()),
104
- )
134
+ pub(crate) fn into_exp_backoff<C>(self, clock: C) -> exponential::ExponentialBackoff<C> {
135
+ exponential::ExponentialBackoff {
136
+ current_interval: self.initial_interval,
137
+ initial_interval: self.initial_interval,
138
+ randomization_factor: self.randomization_factor,
139
+ multiplier: self.multiplier,
140
+ max_interval: self.max_interval,
141
+ max_elapsed_time: self.max_elapsed_time,
142
+ clock,
143
+ start_time: Instant::now(),
144
+ }
105
145
  }
106
146
  }
107
147
 
108
- impl<SG> NamespacedClient for RetryClient<SG>
109
- where
110
- SG: NamespacedClient,
111
- {
112
- fn namespace(&self) -> String {
113
- self.client.namespace()
148
+ impl From<RetryOptions> for backoff::ExponentialBackoff {
149
+ fn from(c: RetryOptions) -> Self {
150
+ c.into_exp_backoff(SystemClock::default())
114
151
  }
152
+ }
115
153
 
116
- fn identity(&self) -> String {
117
- self.client.identity()
118
- }
154
+ pub(crate) fn make_future_retry<R, F, Fut>(
155
+ info: CallInfo,
156
+ factory: F,
157
+ ) -> FutureRetry<F, TonicErrorHandler<SystemClock>>
158
+ where
159
+ F: FnMut() -> Fut + Unpin,
160
+ Fut: Future<Output = Result<R, tonic::Status>>,
161
+ {
162
+ FutureRetry::new(
163
+ factory,
164
+ TonicErrorHandler::new(info, RetryOptions::throttle_retry_policy()),
165
+ )
119
166
  }
120
167
 
121
168
  #[derive(Debug)]
@@ -525,12 +572,11 @@ mod tests {
525
572
  ) {
526
573
  // A bit odd, but we don't need a real client to test the retry client passes through the
527
574
  // correct retry config
528
- let fake_retry = RetryClient::new((), TEST_RETRY_CONFIG);
529
575
  let mut req = req.into_request();
530
576
  req.extensions_mut().insert(IsWorkerTaskLongPoll);
531
577
  for i in 1..=50 {
532
578
  let mut err_handler = TonicErrorHandler::new(
533
- fake_retry.get_call_info::<R>(call_name, Some(&req)),
579
+ TEST_RETRY_CONFIG.get_call_info::<R>(call_name, Some(&req)),
534
580
  RetryOptions::throttle_retry_policy(),
535
581
  );
536
582
  let result = err_handler.handle(i, Status::new(Code::Unknown, "Ahh"));
@@ -557,13 +603,12 @@ mod tests {
557
603
  )]
558
604
  (call_name, req): (&'static str, R),
559
605
  ) {
560
- let fake_retry = RetryClient::new((), TEST_RETRY_CONFIG);
561
606
  let mut req = req.into_request();
562
607
  req.extensions_mut().insert(IsWorkerTaskLongPoll);
563
608
  // For some reason we will get cancelled in these situations occasionally (always?) too
564
609
  for code in [Code::Cancelled, Code::DeadlineExceeded] {
565
610
  let mut err_handler = TonicErrorHandler::new(
566
- fake_retry.get_call_info::<R>(call_name, Some(&req)),
611
+ TEST_RETRY_CONFIG.get_call_info::<R>(call_name, Some(&req)),
567
612
  RetryOptions::throttle_retry_policy(),
568
613
  );
569
614
  for i in 1..=5 {
@@ -213,28 +213,48 @@ impl ClientWorkerSetImpl {
213
213
  Ok(())
214
214
  }
215
215
 
216
- fn unregister(
217
- &mut self,
218
- worker_instance_key: Uuid,
219
- ) -> Result<Arc<dyn ClientWorker + Send + Sync>, anyhow::Error> {
220
- let worker = self
221
- .all_workers
222
- .remove(&worker_instance_key)
223
- .ok_or_else(|| {
224
- anyhow::anyhow!("Worker with worker_instance_key {worker_instance_key} not found")
225
- })?;
216
+ /// Slot provider should be unregistered at the beginning of worker shutdown, in order to disable
217
+ /// eager workflow start.
218
+ fn unregister_slot_provider(&mut self, worker_instance_key: Uuid) -> Result<(), anyhow::Error> {
219
+ let worker = self.all_workers.get(&worker_instance_key).ok_or_else(|| {
220
+ anyhow::anyhow!("Worker not in all_workers during slot provider unregister")
221
+ })?;
226
222
 
227
223
  let slot_key = SlotKey::new(
228
224
  worker.namespace().to_string(),
229
225
  worker.task_queue().to_string(),
230
226
  );
231
-
232
227
  if let Some(slot_vec) = self.slot_providers.get_mut(&slot_key) {
233
228
  slot_vec.retain(|info| info.worker_id != worker_instance_key);
234
229
  if slot_vec.is_empty() {
235
230
  self.slot_providers.remove(&slot_key);
236
231
  }
237
232
  }
233
+ Ok(())
234
+ }
235
+
236
+ fn finalize_unregister(
237
+ &mut self,
238
+ worker_instance_key: Uuid,
239
+ ) -> Result<Arc<dyn ClientWorker + Send + Sync>, anyhow::Error> {
240
+ if let Some(worker) = self.all_workers.get(&worker_instance_key)
241
+ && let Some(slot_vec) = self.slot_providers.get(&SlotKey::new(
242
+ worker.namespace().to_string(),
243
+ worker.task_queue().to_string(),
244
+ ))
245
+ && slot_vec
246
+ .iter()
247
+ .any(|info| info.worker_id == worker_instance_key)
248
+ {
249
+ return Err(anyhow::anyhow!(
250
+ "Worker still in slot_providers during finalize"
251
+ ));
252
+ }
253
+
254
+ let worker = self
255
+ .all_workers
256
+ .remove(&worker_instance_key)
257
+ .ok_or_else(|| anyhow::anyhow!("Worker not found in all_workers"))?;
238
258
 
239
259
  if let Some(w) = self.shared_worker.get_mut(worker.namespace()) {
240
260
  let (callback, is_empty) = w.unregister_callback(worker.worker_instance_key());
@@ -278,7 +298,7 @@ pub trait SharedNamespaceWorkerTrait {
278
298
  /// Enables local workers to make themselves visible to a shared client instance.
279
299
  ///
280
300
  /// For slot managing, there can only be one worker registered per
281
- /// namespace+queue_name+client, others will return an error.
301
+ /// namespace+queue_name+connection, others will return an error.
282
302
  /// It also provides a convenient method to find compatible slots within the collection.
283
303
  pub struct ClientWorkerSet {
284
304
  worker_grouping_key: Uuid,
@@ -323,12 +343,24 @@ impl ClientWorkerSet {
323
343
  .register(worker, skip_client_worker_set_check)
324
344
  }
325
345
 
326
- /// Unregisters a local worker, typically when that worker starts shutdown.
327
- pub fn unregister_worker(
346
+ /// Disables Eager Workflow Start for this worker. This must be called before
347
+ /// `finalize_unregister`, otherwise `finalize_unregister` will return an err.
348
+ pub fn unregister_slot_provider(&self, worker_instance_key: Uuid) -> Result<(), anyhow::Error> {
349
+ self.worker_manager
350
+ .write()
351
+ .unregister_slot_provider(worker_instance_key)
352
+ }
353
+
354
+ /// Finalizes unregistering of worker from client. This must be called at the end of worker
355
+ /// shutdown in order to finalize shutdown for worker heartbeat properly. Must call after
356
+ /// `unregister_slot_provider`, otherwise an err will be returned.
357
+ pub fn finalize_unregister(
328
358
  &self,
329
359
  worker_instance_key: Uuid,
330
360
  ) -> Result<Arc<dyn ClientWorker + Send + Sync>, anyhow::Error> {
331
- self.worker_manager.write().unregister(worker_instance_key)
361
+ self.worker_manager
362
+ .write()
363
+ .finalize_unregister(worker_instance_key)
332
364
  }
333
365
 
334
366
  /// Returns the worker grouping key, which is unique for each worker.
@@ -651,14 +683,14 @@ mod tests {
651
683
  let worker_instance_key = mock_provider.worker_instance_key();
652
684
 
653
685
  let result = manager.register_worker(Arc::new(mock_provider), false);
654
- if result.is_ok() {
655
- successful_registrations += 1;
656
- worker_keys.push(worker_instance_key);
657
- } else {
686
+ if let Err(err) = result {
658
687
  // Should get error for overlapping worker task types
659
- assert!(result.unwrap_err().to_string().contains(
688
+ assert!(err.to_string().contains(
660
689
  "Registration of multiple workers with overlapping worker task types"
661
690
  ));
691
+ } else {
692
+ successful_registrations += 1;
693
+ worker_keys.push(worker_instance_key);
662
694
  }
663
695
  }
664
696
 
@@ -666,9 +698,12 @@ mod tests {
666
698
  assert_eq!(3, manager.num_providers());
667
699
 
668
700
  let count = worker_keys.iter().fold(0, |count, key| {
669
- manager.unregister_worker(*key).unwrap();
701
+ manager.unregister_slot_provider(*key).unwrap();
702
+ manager.finalize_unregister(*key).unwrap();
670
703
  // expect error since worker is already unregistered
671
- let result = manager.unregister_worker(*key);
704
+ let result = manager.unregister_slot_provider(*key);
705
+ assert!(result.is_err());
706
+ let result = manager.finalize_unregister(*key);
672
707
  assert!(result.is_err());
673
708
  count + 1
674
709
  });
@@ -896,7 +931,10 @@ mod tests {
896
931
  assert_eq!(providers[1].build_id, Some("build-1".to_string()));
897
932
  }
898
933
 
899
- manager.unregister_worker(worker2_instance_key).unwrap();
934
+ manager
935
+ .unregister_slot_provider(worker2_instance_key)
936
+ .unwrap();
937
+ manager.finalize_unregister(worker2_instance_key).unwrap();
900
938
 
901
939
  {
902
940
  let impl_ref = manager.worker_manager.read();
@@ -1016,7 +1054,10 @@ mod tests {
1016
1054
  drop(impl_ref);
1017
1055
 
1018
1056
  // Unregister first worker
1019
- manager.unregister_worker(worker_instance_key1).unwrap();
1057
+ manager
1058
+ .unregister_slot_provider(worker_instance_key1)
1059
+ .unwrap();
1060
+ manager.finalize_unregister(worker_instance_key1).unwrap();
1020
1061
 
1021
1062
  // After unregistering first worker: 1 slot provider, 1 heartbeat worker, shared worker still exists
1022
1063
  assert_eq!(1, manager.num_providers());
@@ -1036,7 +1077,10 @@ mod tests {
1036
1077
  drop(impl_ref);
1037
1078
 
1038
1079
  // Unregister second worker
1039
- manager.unregister_worker(worker_instance_key2).unwrap();
1080
+ manager
1081
+ .unregister_slot_provider(worker_instance_key2)
1082
+ .unwrap();
1083
+ manager.finalize_unregister(worker_instance_key2).unwrap();
1040
1084
 
1041
1085
  // After unregistering last worker: 0 slot providers, 0 heartbeat workers, shared worker is removed
1042
1086
  assert_eq!(0, manager.num_providers());
@@ -1447,8 +1491,11 @@ mod tests {
1447
1491
  );
1448
1492
 
1449
1493
  manager
1450
- .unregister_worker(wf_worker_key)
1451
- .expect("should unregister workflow worker");
1494
+ .unregister_slot_provider(wf_worker_key)
1495
+ .expect("should unregister slot provider for workflow worker");
1496
+ manager
1497
+ .finalize_unregister(wf_worker_key)
1498
+ .expect("should finalize unregister for workflow worker");
1452
1499
 
1453
1500
  // Activity worker should still be registered
1454
1501
  assert_eq!(1, manager.num_providers());
@@ -1460,9 +1507,37 @@ mod tests {
1460
1507
  );
1461
1508
 
1462
1509
  manager
1463
- .unregister_worker(act_worker_key)
1464
- .expect("should unregister activity worker");
1510
+ .unregister_slot_provider(act_worker_key)
1511
+ .expect("should unregister slot provider for activity worker");
1512
+ manager
1513
+ .finalize_unregister(act_worker_key)
1514
+ .expect("should finalize unregister for activity worker");
1465
1515
 
1466
1516
  assert_eq!(0, manager.num_providers());
1467
1517
  }
1518
+
1519
+ #[test]
1520
+ fn worker_unregister_order() {
1521
+ let manager = ClientWorkerSet::new();
1522
+ let worker = new_mock_provider_with_heartbeat(
1523
+ "namespace1".to_string(),
1524
+ "queue1".to_string(),
1525
+ true,
1526
+ None,
1527
+ );
1528
+ let worker_instance_key = worker.worker_instance_key();
1529
+ manager.register_worker(Arc::new(worker), false).unwrap();
1530
+
1531
+ let res = manager.finalize_unregister(worker_instance_key);
1532
+ assert!(res.is_err());
1533
+ let err_string = res.err().map(|e| e.to_string()).unwrap();
1534
+ assert!(err_string.contains("Worker still in slot_providers during finalize"));
1535
+
1536
+ // previous incorrect call to finalize_unregister should not cause any state leaks when
1537
+ // properly removed later
1538
+ manager
1539
+ .unregister_slot_provider(worker_instance_key)
1540
+ .unwrap();
1541
+ manager.finalize_unregister(worker_instance_key).unwrap();
1542
+ }
1468
1543
  }