@temporalio/core-bridge 1.4.4 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/Cargo.lock +327 -419
  2. package/Cargo.toml +1 -1
  3. package/index.js +25 -2
  4. package/lib/errors.d.ts +22 -0
  5. package/lib/errors.js +65 -0
  6. package/lib/errors.js.map +1 -0
  7. package/lib/index.d.ts +440 -0
  8. package/lib/index.js +8 -0
  9. package/lib/index.js.map +1 -0
  10. package/package.json +11 -5
  11. package/releases/aarch64-apple-darwin/index.node +0 -0
  12. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  13. package/releases/x86_64-apple-darwin/index.node +0 -0
  14. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  15. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  16. package/sdk-core/.buildkite/docker/Dockerfile +1 -1
  17. package/sdk-core/.buildkite/docker/docker-compose.yaml +2 -2
  18. package/sdk-core/bridge-ffi/Cargo.toml +1 -1
  19. package/sdk-core/bridge-ffi/include/sdk-core-bridge.h +0 -25
  20. package/sdk-core/bridge-ffi/src/lib.rs +29 -108
  21. package/sdk-core/bridge-ffi/src/wrappers.rs +35 -25
  22. package/sdk-core/client/Cargo.toml +1 -1
  23. package/sdk-core/client/src/lib.rs +12 -20
  24. package/sdk-core/client/src/raw.rs +9 -8
  25. package/sdk-core/client/src/retry.rs +100 -23
  26. package/sdk-core/core/Cargo.toml +5 -5
  27. package/sdk-core/core/benches/workflow_replay.rs +13 -10
  28. package/sdk-core/core/src/abstractions.rs +22 -22
  29. package/sdk-core/core/src/core_tests/activity_tasks.rs +1 -1
  30. package/sdk-core/core/src/core_tests/local_activities.rs +228 -6
  31. package/sdk-core/core/src/core_tests/queries.rs +247 -89
  32. package/sdk-core/core/src/core_tests/workers.rs +2 -2
  33. package/sdk-core/core/src/core_tests/workflow_cancels.rs +1 -1
  34. package/sdk-core/core/src/core_tests/workflow_tasks.rs +46 -27
  35. package/sdk-core/core/src/lib.rs +139 -32
  36. package/sdk-core/core/src/replay/mod.rs +185 -41
  37. package/sdk-core/core/src/telemetry/log_export.rs +190 -0
  38. package/sdk-core/core/src/telemetry/metrics.rs +184 -139
  39. package/sdk-core/core/src/telemetry/mod.rs +296 -318
  40. package/sdk-core/core/src/telemetry/prometheus_server.rs +4 -3
  41. package/sdk-core/core/src/test_help/mod.rs +9 -7
  42. package/sdk-core/core/src/worker/activities/local_activities.rs +2 -1
  43. package/sdk-core/core/src/worker/activities.rs +40 -23
  44. package/sdk-core/core/src/worker/client/mocks.rs +1 -1
  45. package/sdk-core/core/src/worker/client.rs +30 -4
  46. package/sdk-core/core/src/worker/mod.rs +22 -18
  47. package/sdk-core/core/src/worker/workflow/driven_workflow.rs +10 -19
  48. package/sdk-core/core/src/worker/workflow/history_update.rs +99 -25
  49. package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +1 -5
  50. package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +1 -5
  51. package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +1 -5
  52. package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +1 -5
  53. package/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +1 -5
  54. package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +2 -6
  55. package/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +1 -5
  56. package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +18 -21
  57. package/sdk-core/core/src/worker/workflow/machines/mod.rs +12 -38
  58. package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +178 -0
  59. package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +1 -5
  60. package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +1 -5
  61. package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +1 -5
  62. package/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +8 -2
  63. package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +1 -5
  64. package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +232 -216
  65. package/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +1 -6
  66. package/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +4 -4
  67. package/sdk-core/core/src/worker/workflow/managed_run.rs +13 -5
  68. package/sdk-core/core/src/worker/workflow/mod.rs +61 -9
  69. package/sdk-core/core/src/worker/workflow/wft_poller.rs +2 -2
  70. package/sdk-core/core/src/worker/workflow/workflow_stream.rs +56 -11
  71. package/sdk-core/core-api/Cargo.toml +4 -3
  72. package/sdk-core/core-api/src/lib.rs +1 -43
  73. package/sdk-core/core-api/src/telemetry.rs +147 -0
  74. package/sdk-core/core-api/src/worker.rs +13 -0
  75. package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +1 -1
  76. package/sdk-core/histories/evict_while_la_running_no_interference-23_history.bin +0 -0
  77. package/sdk-core/histories/evict_while_la_running_no_interference-85_history.bin +0 -0
  78. package/sdk-core/protos/api_upstream/.github/CODEOWNERS +1 -1
  79. package/sdk-core/protos/api_upstream/buf.yaml +0 -3
  80. package/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +3 -7
  81. package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +8 -0
  82. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +1 -2
  83. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +2 -0
  84. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +3 -0
  85. package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +13 -0
  86. package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +19 -59
  87. package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +0 -19
  88. package/sdk-core/protos/api_upstream/temporal/api/schedule/v1/message.proto +108 -29
  89. package/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +2 -2
  90. package/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +1 -0
  91. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +47 -8
  92. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +15 -1
  93. package/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +2 -0
  94. package/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +8 -1
  95. package/sdk-core/sdk/src/interceptors.rs +36 -3
  96. package/sdk-core/sdk/src/lib.rs +7 -4
  97. package/sdk-core/sdk/src/workflow_context.rs +13 -2
  98. package/sdk-core/sdk-core-protos/src/history_builder.rs +47 -1
  99. package/sdk-core/sdk-core-protos/src/history_info.rs +22 -22
  100. package/sdk-core/sdk-core-protos/src/lib.rs +49 -27
  101. package/sdk-core/test-utils/Cargo.toml +1 -0
  102. package/sdk-core/test-utils/src/lib.rs +81 -29
  103. package/sdk-core/tests/integ_tests/metrics_tests.rs +37 -0
  104. package/sdk-core/tests/integ_tests/polling_tests.rs +0 -13
  105. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +145 -4
  106. package/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +53 -0
  107. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +106 -20
  108. package/sdk-core/tests/integ_tests/workflow_tests.rs +18 -8
  109. package/sdk-core/tests/main.rs +6 -4
  110. package/src/conversions.rs +52 -47
  111. package/src/errors.rs +28 -86
  112. package/src/helpers.rs +3 -4
  113. package/src/lib.rs +2 -2
  114. package/src/runtime.rs +132 -61
  115. package/src/testing.rs +7 -4
  116. package/src/worker.rs +67 -50
  117. package/ts/errors.ts +55 -0
  118. package/{index.d.ts → ts/index.ts} +121 -15
  119. package/sdk-core/core/src/log_export.rs +0 -62
  120. package/sdk-core/core/src/worker/workflow/machines/mutable_side_effect_state_machine.rs +0 -127
  121. package/sdk-core/core/src/worker/workflow/machines/side_effect_state_machine.rs +0 -71
  122. package/sdk-core/protos/api_upstream/temporal/api/cluster/v1/message.proto +0 -83
  123. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/cluster.proto +0 -40
@@ -101,32 +101,49 @@ impl<SG> RetryClient<SG> {
101
101
  F: FnMut() -> Fut + Unpin,
102
102
  Fut: Future<Output = Result<R>>,
103
103
  {
104
- FutureRetry::new(factory, TonicErrorHandler::new(rtc, call_name))
104
+ FutureRetry::new(
105
+ factory,
106
+ TonicErrorHandler::new(rtc, RetryConfig::throttle_retry_policy(), call_name),
107
+ )
105
108
  }
106
109
  }
107
110
 
108
111
  #[derive(Debug)]
109
112
  pub(crate) struct TonicErrorHandler<C: Clock> {
110
113
  backoff: ExponentialBackoff<C>,
114
+ throttle_backoff: ExponentialBackoff<C>,
111
115
  max_retries: usize,
112
116
  call_type: CallType,
113
117
  call_name: &'static str,
114
118
  }
115
119
  impl TonicErrorHandler<SystemClock> {
116
- fn new(cfg: RetryConfig, call_name: &'static str) -> Self {
117
- Self::new_with_clock(cfg, call_name, SystemClock::default())
120
+ fn new(cfg: RetryConfig, throttle_cfg: RetryConfig, call_name: &'static str) -> Self {
121
+ Self::new_with_clock(
122
+ cfg,
123
+ throttle_cfg,
124
+ call_name,
125
+ SystemClock::default(),
126
+ SystemClock::default(),
127
+ )
118
128
  }
119
129
  }
120
130
  impl<C> TonicErrorHandler<C>
121
131
  where
122
132
  C: Clock,
123
133
  {
124
- fn new_with_clock(cfg: RetryConfig, call_name: &'static str, clock: C) -> Self {
134
+ fn new_with_clock(
135
+ cfg: RetryConfig,
136
+ throttle_cfg: RetryConfig,
137
+ call_name: &'static str,
138
+ clock: C,
139
+ throttle_clock: C,
140
+ ) -> Self {
125
141
  Self {
126
142
  max_retries: cfg.max_retries,
127
143
  call_type: CallType::from_call_name(call_name),
128
144
  call_name,
129
145
  backoff: cfg.into_exp_backoff(clock),
146
+ throttle_backoff: throttle_cfg.into_exp_backoff(throttle_clock),
130
147
  }
131
148
  }
132
149
  const fn should_log_retry_warning(&self, cur_attempt: usize) -> bool {
@@ -184,10 +201,12 @@ where
184
201
  match self.backoff.next_backoff() {
185
202
  None => RetryPolicy::ForwardError(e), // None is returned when we've ran out of time
186
203
  Some(backoff) => {
187
- if cfg!(test) {
188
- // Allow unit tests to do lots of retries quickly. This does *not* apply
189
- // during integration testing, importantly.
190
- RetryPolicy::WaitRetry(Duration::from_millis(1))
204
+ // We treat ResourceExhausted as a special case and backoff more
205
+ // so we don't overload the server
206
+ if e.code() == Code::ResourceExhausted {
207
+ let extended_backoff =
208
+ backoff.max(self.throttle_backoff.next_backoff().unwrap_or_default());
209
+ RetryPolicy::WaitRetry(extended_backoff)
191
210
  } else {
192
211
  RetryPolicy::WaitRetry(backoff)
193
212
  }
@@ -529,6 +548,16 @@ mod tests {
529
548
  use std::{ops::Add, time::Instant};
530
549
  use tonic::Status;
531
550
 
551
+ /// Predefined retry configs with low durations to make unit tests faster
552
+ const TEST_RETRY_CONFIG: RetryConfig = RetryConfig {
553
+ initial_interval: Duration::from_millis(1),
554
+ randomization_factor: 0.0,
555
+ multiplier: 1.1,
556
+ max_interval: Duration::from_millis(2),
557
+ max_elapsed_time: None,
558
+ max_retries: 10,
559
+ };
560
+
532
561
  #[tokio::test]
533
562
  async fn non_retryable_errors() {
534
563
  for code in [
@@ -547,7 +576,7 @@ mod tests {
547
576
  .expect_cancel_activity_task()
548
577
  .returning(move |_, _| Err(Status::new(code, "non-retryable failure")))
549
578
  .times(1);
550
- let retry_client = RetryClient::new(mock_client, Default::default());
579
+ let retry_client = RetryClient::new(mock_client, TEST_RETRY_CONFIG);
551
580
  let result = retry_client
552
581
  .cancel_activity_task(vec![1].into(), None)
553
582
  .await;
@@ -575,12 +604,13 @@ mod tests {
575
604
  Code::Unimplemented,
576
605
  ] {
577
606
  for call_name in [POLL_WORKFLOW_METH_NAME, POLL_ACTIVITY_METH_NAME] {
578
- let retry_cfg = RetryConfig::poll_retry_policy();
579
607
  let mut err_handler = TonicErrorHandler {
580
- max_retries: retry_cfg.max_retries,
608
+ max_retries: TEST_RETRY_CONFIG.max_retries,
581
609
  call_type: CallType::LongPoll,
582
610
  call_name,
583
- backoff: retry_cfg.into_exp_backoff(FixedClock(Instant::now())),
611
+ backoff: TEST_RETRY_CONFIG.into_exp_backoff(FixedClock(Instant::now())),
612
+ throttle_backoff: TEST_RETRY_CONFIG
613
+ .into_exp_backoff(FixedClock(Instant::now())),
584
614
  };
585
615
  let result = err_handler.handle(1, Status::new(code, "Ahh"));
586
616
  assert_matches!(result, RetryPolicy::WaitRetry(_));
@@ -599,12 +629,13 @@ mod tests {
599
629
  async fn long_poll_retryable_errors_never_fatal() {
600
630
  for code in RETRYABLE_ERROR_CODES {
601
631
  for call_name in [POLL_WORKFLOW_METH_NAME, POLL_ACTIVITY_METH_NAME] {
602
- let retry_cfg = RetryConfig::poll_retry_policy();
603
632
  let mut err_handler = TonicErrorHandler {
604
- max_retries: retry_cfg.max_retries,
633
+ max_retries: TEST_RETRY_CONFIG.max_retries,
605
634
  call_type: CallType::LongPoll,
606
635
  call_name,
607
- backoff: retry_cfg.into_exp_backoff(FixedClock(Instant::now())),
636
+ backoff: TEST_RETRY_CONFIG.into_exp_backoff(FixedClock(Instant::now())),
637
+ throttle_backoff: TEST_RETRY_CONFIG
638
+ .into_exp_backoff(FixedClock(Instant::now())),
608
639
  };
609
640
  let result = err_handler.handle(1, Status::new(code, "Ahh"));
610
641
  assert_matches!(result, RetryPolicy::WaitRetry(_));
@@ -621,7 +652,12 @@ mod tests {
621
652
 
622
653
  #[tokio::test]
623
654
  async fn retryable_errors() {
624
- for code in RETRYABLE_ERROR_CODES {
655
+ // Take out retry exhausted since it gets a special policy which would make this take ages
656
+ for code in RETRYABLE_ERROR_CODES
657
+ .iter()
658
+ .copied()
659
+ .filter(|p| p != &Code::ResourceExhausted)
660
+ {
625
661
  let mut mock_client = MockWorkflowClientTrait::new();
626
662
  mock_client
627
663
  .expect_cancel_activity_task()
@@ -632,7 +668,7 @@ mod tests {
632
668
  .returning(|_, _| Ok(Default::default()))
633
669
  .times(1);
634
670
 
635
- let retry_client = RetryClient::new(mock_client, Default::default());
671
+ let retry_client = RetryClient::new(mock_client, TEST_RETRY_CONFIG);
636
672
  let result = retry_client
637
673
  .cancel_activity_task(vec![1].into(), None)
638
674
  .await;
@@ -641,15 +677,53 @@ mod tests {
641
677
  }
642
678
  }
643
679
 
680
+ #[tokio::test]
681
+ async fn retry_resource_exhausted() {
682
+ let mut err_handler = TonicErrorHandler {
683
+ max_retries: TEST_RETRY_CONFIG.max_retries,
684
+ call_type: CallType::Normal,
685
+ call_name: POLL_WORKFLOW_METH_NAME,
686
+ backoff: TEST_RETRY_CONFIG.into_exp_backoff(FixedClock(Instant::now())),
687
+ throttle_backoff: RetryConfig {
688
+ initial_interval: Duration::from_millis(2),
689
+ randomization_factor: 0.0,
690
+ multiplier: 4.0,
691
+ max_interval: Duration::from_millis(10),
692
+ max_elapsed_time: None,
693
+ max_retries: 10,
694
+ }
695
+ .into_exp_backoff(FixedClock(Instant::now())),
696
+ };
697
+ let result = err_handler.handle(1, Status::new(Code::ResourceExhausted, "leave me alone"));
698
+ match result {
699
+ RetryPolicy::WaitRetry(duration) => assert_eq!(duration, Duration::from_millis(2)),
700
+ _ => panic!(),
701
+ }
702
+ err_handler.backoff.clock.0 = err_handler.backoff.clock.0.add(Duration::from_millis(10));
703
+ err_handler.throttle_backoff.clock.0 = err_handler
704
+ .throttle_backoff
705
+ .clock
706
+ .0
707
+ .add(Duration::from_millis(10));
708
+ let result = err_handler.handle(2, Status::new(Code::ResourceExhausted, "leave me alone"));
709
+ match result {
710
+ RetryPolicy::WaitRetry(duration) => assert_eq!(duration, Duration::from_millis(8)),
711
+ _ => panic!(),
712
+ }
713
+ }
714
+
644
715
  #[tokio::test]
645
716
  async fn long_poll_retries_forever() {
646
717
  // A bit odd, but we don't need a real client to test the retry client passes through the
647
718
  // correct retry config
648
- let fake_retry = RetryClient::new((), Default::default());
719
+ let fake_retry = RetryClient::new((), TEST_RETRY_CONFIG);
649
720
  for i in 1..=50 {
650
721
  for call in [POLL_WORKFLOW_METH_NAME, POLL_ACTIVITY_METH_NAME] {
651
- let mut err_handler =
652
- TonicErrorHandler::new(fake_retry.get_retry_config(call), call);
722
+ let mut err_handler = TonicErrorHandler::new(
723
+ fake_retry.get_retry_config(call),
724
+ fake_retry.get_retry_config(call),
725
+ call,
726
+ );
653
727
  let result = err_handler.handle(i, Status::new(Code::Unknown, "Ahh"));
654
728
  assert_matches!(result, RetryPolicy::WaitRetry(_));
655
729
  }
@@ -658,12 +732,15 @@ mod tests {
658
732
 
659
733
  #[tokio::test]
660
734
  async fn long_poll_retries_deadline_exceeded() {
661
- let fake_retry = RetryClient::new((), Default::default());
735
+ let fake_retry = RetryClient::new((), TEST_RETRY_CONFIG);
662
736
  // For some reason we will get cancelled in these situations occasionally (always?) too
663
737
  for code in [Code::Cancelled, Code::DeadlineExceeded] {
664
738
  for call in [POLL_WORKFLOW_METH_NAME, POLL_ACTIVITY_METH_NAME] {
665
- let mut err_handler =
666
- TonicErrorHandler::new(fake_retry.get_retry_config(call), call);
739
+ let mut err_handler = TonicErrorHandler::new(
740
+ fake_retry.get_retry_config(call),
741
+ fake_retry.get_retry_config(call),
742
+ call,
743
+ );
667
744
  for i in 1..=5 {
668
745
  let result = err_handler.handle(i, Status::new(code, "retryable failure"));
669
746
  assert_matches!(result, RetryPolicy::WaitRetry(_));
@@ -20,7 +20,7 @@ async-trait = "0.1"
20
20
  base64 = "0.13"
21
21
  crossbeam = "0.8"
22
22
  dashmap = "5.0"
23
- derive_builder = "0.11"
23
+ derive_builder = "0.12"
24
24
  derive_more = "0.99"
25
25
  enum_dispatch = "0.3"
26
26
  flate2 = "1.0"
@@ -34,7 +34,7 @@ lazy_static = "1.4"
34
34
  log = "0.4"
35
35
  lru = "0.8"
36
36
  mockall = "0.11"
37
- nix = "0.25"
37
+ nix = "0.26"
38
38
  once_cell = "1.5"
39
39
  opentelemetry = { version = "0.18", features = ["rt-tokio"] }
40
40
  opentelemetry-otlp = { version = "0.11", features = ["tokio", "metrics"] }
@@ -45,7 +45,7 @@ prost = "0.11"
45
45
  prost-types = "0.11"
46
46
  rand = "0.8.3"
47
47
  reqwest = { version = "0.11", features = ["json", "stream", "rustls-tls", "tokio-rustls"], default-features = false }
48
- ringbuf = "0.2"
48
+ ringbuf = "0.3"
49
49
  serde = "1.0"
50
50
  serde_json = "1.0"
51
51
  siphasher = "0.3"
@@ -59,7 +59,7 @@ tonic = { version = "0.8", features = ["tls", "tls-roots"] }
59
59
  tracing = { version = "0.1", features = ["log-always"] }
60
60
  tracing-futures = "0.2"
61
61
  tracing-opentelemetry = "0.18"
62
- tracing-subscriber = { version = "0.3", features = ["parking_lot", "env-filter"] }
62
+ tracing-subscriber = { version = "0.3", features = ["parking_lot", "env-filter", "registry"] }
63
63
  url = "2.2"
64
64
  uuid = { version = "1.1", features = ["v4"] }
65
65
  zip = "0.6"
@@ -86,7 +86,7 @@ version = "0.1"
86
86
  assert_matches = "1.4"
87
87
  bimap = "0.6.1"
88
88
  criterion = "0.4"
89
- rstest = "0.15"
89
+ rstest = "0.16"
90
90
  temporal-sdk-core-test-utils = { path = "../test-utils" }
91
91
  temporal-sdk = { path = "../sdk" }
92
92
 
@@ -1,29 +1,30 @@
1
1
  use criterion::{criterion_group, criterion_main, Criterion};
2
2
  use futures::StreamExt;
3
3
  use std::time::Duration;
4
- use temporal_sdk::{WfContext, Worker, WorkflowFunction};
5
- use temporal_sdk_core::{telemetry_init, TelemetryOptionsBuilder};
4
+ use temporal_sdk::{WfContext, WorkflowFunction};
5
+ use temporal_sdk_core::replay::HistoryForReplay;
6
6
  use temporal_sdk_core_protos::DEFAULT_WORKFLOW_TYPE;
7
- use temporal_sdk_core_test_utils::{canned_histories, init_core_replay_preloaded};
7
+ use temporal_sdk_core_test_utils::{canned_histories, replay_sdk_worker};
8
8
 
9
9
  pub fn criterion_benchmark(c: &mut Criterion) {
10
10
  let tokio_runtime = tokio::runtime::Builder::new_current_thread()
11
11
  .enable_time()
12
12
  .build()
13
13
  .unwrap();
14
- telemetry_init(&TelemetryOptionsBuilder::default().build().unwrap()).unwrap();
15
14
  let _g = tokio_runtime.enter();
16
15
 
17
16
  let num_timers = 10;
18
17
  let t = canned_histories::long_sequential_timers(num_timers as usize);
19
- let hist = t.get_full_history_info().unwrap().into();
18
+ let hist = HistoryForReplay::new(
19
+ t.get_full_history_info().unwrap().into(),
20
+ "whatever".to_string(),
21
+ );
20
22
 
21
23
  c.bench_function("Small history replay", |b| {
22
24
  b.iter(|| {
23
25
  tokio_runtime.block_on(async {
24
26
  let func = timers_wf(num_timers);
25
- let (worker, _) = init_core_replay_preloaded("replay_bench", &hist);
26
- let mut worker = Worker::new_from_core(worker, "replay_bench".to_string());
27
+ let mut worker = replay_sdk_worker([hist.clone()]);
27
28
  worker.register_wf(DEFAULT_WORKFLOW_TYPE, func);
28
29
  worker.run().await.unwrap();
29
30
  })
@@ -32,14 +33,16 @@ pub fn criterion_benchmark(c: &mut Criterion) {
32
33
 
33
34
  let num_tasks = 50;
34
35
  let t = canned_histories::lots_of_big_signals(num_tasks);
35
- let hist = t.get_full_history_info().unwrap().into();
36
+ let hist = HistoryForReplay::new(
37
+ t.get_full_history_info().unwrap().into(),
38
+ "whatever".to_string(),
39
+ );
36
40
 
37
41
  c.bench_function("Large payloads history replay", |b| {
38
42
  b.iter(|| {
39
43
  tokio_runtime.block_on(async {
40
44
  let func = big_signals_wf(num_tasks);
41
- let (worker, _) = init_core_replay_preloaded("large_hist_bench", &hist);
42
- let mut worker = Worker::new_from_core(worker, "large_hist_bench".to_string());
45
+ let mut worker = replay_sdk_worker([hist.clone()]);
43
46
  worker.register_wf(DEFAULT_WORKFLOW_TYPE, func);
44
47
  worker.run().await.unwrap();
45
48
  })
@@ -4,10 +4,9 @@ use crate::MetricsContext;
4
4
  use futures::{stream, Stream, StreamExt};
5
5
  use std::{
6
6
  fmt::{Debug, Formatter},
7
- future::Future,
8
7
  sync::Arc,
9
8
  };
10
- use tokio::sync::{AcquireError, Notify, OwnedSemaphorePermit, Semaphore, TryAcquireError};
9
+ use tokio::sync::{AcquireError, OwnedSemaphorePermit, Semaphore, TryAcquireError};
11
10
 
12
11
  /// Wraps a [Semaphore] with a function call that is fed the available permits any time a permit is
13
12
  /// acquired or restored through the provided methods
@@ -82,24 +81,29 @@ impl Debug for OwnedMeteredSemPermit {
82
81
  }
83
82
 
84
83
  /// From the input stream, create a new stream which only pulls from the input stream when allowed.
85
- /// When allowed is determined by the passed in `proceeder` which must return a future every time
86
- /// it's called. The input stream is only pulled from when that future resolves.
87
- pub(crate) fn stream_when_allowed<S, F, FF>(
84
+ /// When allowed is determined by the passed in `proceeder` emitting an item. The input stream is
85
+ /// only pulled from when that future resolves.
86
+ ///
87
+ /// This is *almost* identical to `zip`, but does not terminate early if the input stream closes.
88
+ /// The proceeder must allow the poll before the returned stream closes. If the proceeder terminates
89
+ /// the overall stream will terminate.
90
+ pub(crate) fn stream_when_allowed<S, AS>(
88
91
  input: S,
89
- proceeder: FF,
90
- ) -> impl Stream<Item = (S::Item, F::Output)>
92
+ proceeder: AS,
93
+ ) -> impl Stream<Item = (S::Item, AS::Item)>
91
94
  where
92
95
  S: Stream + Send + 'static,
93
- F: Future,
94
- FF: FnMut() -> F,
96
+ AS: Stream + Send + 'static,
95
97
  {
96
- let acceptable_notify = Arc::new(Notify::new());
97
- acceptable_notify.notify_one();
98
98
  let stream = stream::unfold(
99
- (proceeder, input.boxed()),
99
+ (proceeder.boxed(), input.boxed()),
100
100
  |(mut proceeder, mut input)| async {
101
- let v = proceeder().await;
102
- input.next().await.map(|i| ((i, v), (proceeder, input)))
101
+ let v = proceeder.next().await;
102
+ if let Some(v) = v {
103
+ input.next().await.map(|i| ((i, v), (proceeder, input)))
104
+ } else {
105
+ None
106
+ }
103
107
  },
104
108
  );
105
109
  stream
@@ -108,7 +112,7 @@ where
108
112
  macro_rules! dbg_panic {
109
113
  ($($arg:tt)*) => {
110
114
  error!($($arg)*);
111
- debug_assert!(true, $($arg)*);
115
+ debug_assert!(false, $($arg)*);
112
116
  };
113
117
  }
114
118
  pub(crate) use dbg_panic;
@@ -117,19 +121,15 @@ pub(crate) use dbg_panic;
117
121
  mod tests {
118
122
  use super::*;
119
123
  use futures::pin_mut;
120
- use std::{cell::RefCell, task::Poll};
124
+ use std::task::Poll;
121
125
  use tokio::sync::mpsc::unbounded_channel;
126
+ use tokio_stream::wrappers::UnboundedReceiverStream;
122
127
 
123
- // This is fine. Test only / guaranteed to happen serially.
124
- #[allow(clippy::await_holding_refcell_ref)]
125
128
  #[test]
126
129
  fn stream_when_allowed_works() {
127
130
  let inputs = stream::iter([1, 2, 3]);
128
131
  let (allow_tx, allow_rx) = unbounded_channel();
129
- let allow_rx = RefCell::new(allow_rx);
130
- let when_allowed = stream_when_allowed(inputs, || async {
131
- allow_rx.borrow_mut().recv().await.unwrap()
132
- });
132
+ let when_allowed = stream_when_allowed(inputs, UnboundedReceiverStream::new(allow_rx));
133
133
 
134
134
  let waker = futures::task::noop_waker_ref();
135
135
  let mut cx = std::task::Context::from_waker(waker);
@@ -438,7 +438,7 @@ async fn many_concurrent_heartbeat_cancels() {
438
438
  #[tokio::test]
439
439
  async fn activity_timeout_no_double_resolve() {
440
440
  let t = canned_histories::activity_double_resolve_repro();
441
- let core = build_fake_worker("fake_wf_id", t, &[3]);
441
+ let core = build_fake_worker("fake_wf_id", t, [3]);
442
442
  let activity_id = 1;
443
443
 
444
444
  poll_and_reply(