@temporalio/core-bridge 1.11.2 → 1.11.4

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 (119) hide show
  1. package/Cargo.lock +396 -489
  2. package/Cargo.toml +3 -2
  3. package/lib/errors.d.ts +2 -0
  4. package/lib/errors.js +7 -3
  5. package/lib/errors.js.map +1 -1
  6. package/lib/index.d.ts +8 -2
  7. package/lib/index.js.map +1 -1
  8. package/lib/worker-tuner.d.ts +111 -1
  9. package/package.json +3 -3
  10. package/releases/aarch64-apple-darwin/index.node +0 -0
  11. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  12. package/releases/x86_64-apple-darwin/index.node +0 -0
  13. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  14. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  15. package/sdk-core/.github/workflows/per-pr.yml +3 -3
  16. package/sdk-core/Cargo.toml +0 -1
  17. package/sdk-core/client/Cargo.toml +1 -2
  18. package/sdk-core/client/src/lib.rs +21 -13
  19. package/sdk-core/client/src/metrics.rs +1 -1
  20. package/sdk-core/client/src/raw.rs +46 -1
  21. package/sdk-core/core/Cargo.toml +7 -7
  22. package/sdk-core/core/benches/workflow_replay.rs +1 -1
  23. package/sdk-core/core/src/abstractions/take_cell.rs +1 -1
  24. package/sdk-core/core/src/abstractions.rs +98 -10
  25. package/sdk-core/core/src/core_tests/activity_tasks.rs +8 -2
  26. package/sdk-core/core/src/core_tests/local_activities.rs +1 -1
  27. package/sdk-core/core/src/core_tests/mod.rs +3 -3
  28. package/sdk-core/core/src/core_tests/updates.rs +104 -9
  29. package/sdk-core/core/src/core_tests/workers.rs +72 -3
  30. package/sdk-core/core/src/core_tests/workflow_tasks.rs +6 -7
  31. package/sdk-core/core/src/debug_client.rs +78 -0
  32. package/sdk-core/core/src/ephemeral_server/mod.rs +15 -5
  33. package/sdk-core/core/src/lib.rs +30 -4
  34. package/sdk-core/core/src/pollers/mod.rs +1 -1
  35. package/sdk-core/core/src/pollers/poll_buffer.rs +7 -7
  36. package/sdk-core/core/src/replay/mod.rs +4 -4
  37. package/sdk-core/core/src/telemetry/log_export.rs +2 -2
  38. package/sdk-core/core/src/telemetry/metrics.rs +69 -1
  39. package/sdk-core/core/src/telemetry/otel.rs +2 -2
  40. package/sdk-core/core/src/test_help/mod.rs +3 -3
  41. package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +3 -3
  42. package/sdk-core/core/src/worker/activities/activity_task_poller_stream.rs +1 -1
  43. package/sdk-core/core/src/worker/activities/local_activities.rs +68 -24
  44. package/sdk-core/core/src/worker/activities.rs +26 -15
  45. package/sdk-core/core/src/worker/client/mocks.rs +10 -4
  46. package/sdk-core/core/src/worker/client.rs +17 -0
  47. package/sdk-core/core/src/worker/mod.rs +71 -13
  48. package/sdk-core/core/src/worker/slot_provider.rs +5 -7
  49. package/sdk-core/core/src/worker/tuner/fixed_size.rs +4 -3
  50. package/sdk-core/core/src/worker/tuner/resource_based.rs +171 -32
  51. package/sdk-core/core/src/worker/tuner.rs +18 -6
  52. package/sdk-core/core/src/worker/workflow/history_update.rs +43 -13
  53. package/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +6 -6
  54. package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +6 -5
  55. package/sdk-core/core/src/worker/workflow/managed_run.rs +3 -3
  56. package/sdk-core/core/src/worker/workflow/mod.rs +13 -7
  57. package/sdk-core/core/src/worker/workflow/wft_extraction.rs +7 -7
  58. package/sdk-core/core/src/worker/workflow/wft_poller.rs +2 -2
  59. package/sdk-core/core/src/worker/workflow/workflow_stream.rs +11 -11
  60. package/sdk-core/core-api/Cargo.toml +1 -0
  61. package/sdk-core/core-api/src/worker.rs +84 -30
  62. package/sdk-core/sdk/Cargo.toml +1 -2
  63. package/sdk-core/sdk/src/lib.rs +1 -1
  64. package/sdk-core/sdk/src/workflow_context.rs +9 -8
  65. package/sdk-core/sdk/src/workflow_future.rs +19 -14
  66. package/sdk-core/sdk-core-protos/Cargo.toml +2 -0
  67. package/sdk-core/sdk-core-protos/build.rs +6 -1
  68. package/sdk-core/sdk-core-protos/protos/api_upstream/buf.yaml +1 -0
  69. package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv2.json +3207 -158
  70. package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv3.yaml +2934 -118
  71. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/activity/v1/message.proto +67 -0
  72. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/common/v1/message.proto +47 -1
  73. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/event_type.proto +6 -7
  74. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +2 -0
  75. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/reset.proto +5 -3
  76. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +3 -3
  77. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/update.proto +14 -13
  78. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/failure/v1/message.proto +1 -3
  79. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/history/v1/message.proto +22 -0
  80. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/nexus/v1/message.proto +13 -2
  81. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +26 -6
  82. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/schedule/v1/message.proto +5 -0
  83. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/sdk/v1/workflow_metadata.proto +6 -0
  84. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +46 -12
  85. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/update/v1/message.proto +18 -19
  86. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflow/v1/message.proto +27 -0
  87. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +192 -19
  88. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +279 -12
  89. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/activity_result/activity_result.proto +1 -1
  90. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/activity_task/activity_task.proto +1 -1
  91. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +1 -1
  92. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/common/common.proto +1 -1
  93. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/core_interface.proto +17 -1
  94. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/external_data/external_data.proto +1 -1
  95. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +1 -1
  96. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +1 -1
  97. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +1 -1
  98. package/sdk-core/sdk-core-protos/src/lib.rs +30 -6
  99. package/sdk-core/test-utils/Cargo.toml +1 -2
  100. package/sdk-core/test-utils/src/lib.rs +2 -2
  101. package/sdk-core/tests/heavy_tests.rs +1 -1
  102. package/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +2 -2
  103. package/sdk-core/tests/integ_tests/metrics_tests.rs +144 -7
  104. package/sdk-core/tests/integ_tests/queries_tests.rs +1 -1
  105. package/sdk-core/tests/integ_tests/update_tests.rs +109 -5
  106. package/sdk-core/tests/integ_tests/worker_tests.rs +44 -8
  107. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +1 -1
  108. package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +1 -1
  109. package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +1 -1
  110. package/sdk-core/tests/integ_tests/workflow_tests.rs +3 -2
  111. package/src/conversions/slot_supplier_bridge.rs +287 -0
  112. package/src/conversions.rs +23 -15
  113. package/src/helpers.rs +35 -1
  114. package/src/runtime.rs +7 -3
  115. package/src/worker.rs +1 -1
  116. package/ts/errors.ts +9 -2
  117. package/ts/index.ts +19 -4
  118. package/ts/worker-tuner.ts +123 -1
  119. package/sdk-core/sdk-core-protos/protos/api_upstream/.gitmodules +0 -3
@@ -4,7 +4,7 @@ use crate::{
4
4
  protosext::ValidPollWFTQResponse,
5
5
  MetricsContext,
6
6
  };
7
- use futures::{stream, Stream};
7
+ use futures_util::{stream, Stream};
8
8
  use temporal_sdk_core_api::worker::WorkflowSlotKind;
9
9
  use temporal_sdk_core_protos::temporal::api::workflowservice::v1::PollWorkflowTaskQueueResponse;
10
10
 
@@ -78,7 +78,7 @@ mod tests {
78
78
  abstractions::tests::fixed_size_permit_dealer, pollers::MockPermittedPollBuffer,
79
79
  test_help::mock_poller,
80
80
  };
81
- use futures::{pin_mut, StreamExt};
81
+ use futures_util::{pin_mut, StreamExt};
82
82
  use std::sync::Arc;
83
83
  use temporal_sdk_core_api::worker::WorkflowSlotKind;
84
84
 
@@ -8,7 +8,7 @@ use crate::{
8
8
  },
9
9
  MetricsContext,
10
10
  };
11
- use futures::{stream, stream::PollNext, Stream, StreamExt};
11
+ use futures_util::{stream, stream::PollNext, Stream, StreamExt};
12
12
  use std::{collections::VecDeque, fmt::Debug, future, sync::Arc};
13
13
  use temporal_sdk_core_api::errors::PollWfError;
14
14
  use temporal_sdk_core_protos::coresdk::workflow_activation::remove_from_cache::EvictionReason;
@@ -106,7 +106,7 @@ impl WFStream {
106
106
  let maybe_act = match action {
107
107
  WFStreamInput::NewWft(pwft) => {
108
108
  debug!(run_id=%pwft.work.execution.run_id, "New WFT");
109
- state.instantiate_or_update(pwft)
109
+ state.instantiate_or_update(*pwft)
110
110
  }
111
111
  WFStreamInput::Local(local_input) => {
112
112
  let _span_g = local_input.span.enter();
@@ -124,12 +124,12 @@ impl WFStream {
124
124
  }
125
125
  LocalInputs::FetchedPageCompletion { paginator, update } => {
126
126
  activations.extend(state.process_completion(
127
- NewOrFetchedComplete::Fetched(update, paginator),
127
+ NewOrFetchedComplete::Fetched(update, Box::new(paginator)),
128
128
  ));
129
129
  None // completions can return more than one activation
130
130
  }
131
131
  LocalInputs::PostActivation(report) => {
132
- state.process_post_activation(report)
132
+ state.process_post_activation(*report)
133
133
  }
134
134
  LocalInputs::LocalResolution(res) => state.local_resolution(res),
135
135
  LocalInputs::HeartbeatTimeout(hbt) => {
@@ -242,7 +242,7 @@ impl WFStream {
242
242
  cache. Will fetch history");
243
243
  self.metrics.sticky_cache_miss();
244
244
  return Err(HistoryFetchReq::Full(
245
- CacheMissFetchReq { original_wft: pwft },
245
+ Box::new(CacheMissFetchReq { original_wft: pwft }),
246
246
  self.history_fetch_refcounter.clone(),
247
247
  ));
248
248
  }
@@ -292,7 +292,7 @@ impl WFStream {
292
292
  ),
293
293
  },
294
294
  NewOrFetchedComplete::Fetched(update, paginator) => {
295
- rh.fetched_page_completion(update, paginator)
295
+ rh.fetched_page_completion(update, *paginator)
296
296
  }
297
297
  }
298
298
  .into_iter()
@@ -556,7 +556,7 @@ impl WFStream {
556
556
  /// All possible inputs to the [WFStream]
557
557
  #[derive(derive_more::From, Debug)]
558
558
  enum WFStreamInput {
559
- NewWft(PermittedWFT),
559
+ NewWft(Box<PermittedWFT>),
560
560
  Local(LocalInput),
561
561
  /// The stream given to us which represents the poller (or a mock) terminated.
562
562
  PollerDead,
@@ -595,7 +595,7 @@ pub(super) enum LocalInputs {
595
595
  update: HistoryUpdate,
596
596
  },
597
597
  LocalResolution(LocalResolutionMsg),
598
- PostActivation(PostActivationMsg),
598
+ PostActivation(Box<PostActivationMsg>),
599
599
  RequestEviction(RequestEvictMsg),
600
600
  HeartbeatTimeout(String),
601
601
  GetStateInfo(GetStateInfoMsg),
@@ -634,10 +634,10 @@ enum ExternalPollerInputs {
634
634
  impl From<ExternalPollerInputs> for WFStreamInput {
635
635
  fn from(l: ExternalPollerInputs) -> Self {
636
636
  match l {
637
- ExternalPollerInputs::NewWft(v) => WFStreamInput::NewWft(v),
637
+ ExternalPollerInputs::NewWft(v) => WFStreamInput::NewWft(Box::new(v)),
638
638
  ExternalPollerInputs::PollerDead => WFStreamInput::PollerDead,
639
639
  ExternalPollerInputs::PollerError(e) => WFStreamInput::PollerError(e),
640
- ExternalPollerInputs::FetchedUpdate(wft) => WFStreamInput::NewWft(wft),
640
+ ExternalPollerInputs::FetchedUpdate(wft) => WFStreamInput::NewWft(Box::new(wft)),
641
641
  ExternalPollerInputs::FailedFetch {
642
642
  run_id,
643
643
  err,
@@ -692,7 +692,7 @@ impl From<Result<WFTExtractorOutput, tonic::Status>> for ExternalPollerInputs {
692
692
  #[derive(Debug)]
693
693
  enum NewOrFetchedComplete {
694
694
  New(WFActCompleteMsg),
695
- Fetched(HistoryUpdate, HistoryPaginator),
695
+ Fetched(HistoryUpdate, Box<HistoryPaginator>),
696
696
  }
697
697
  impl NewOrFetchedComplete {
698
698
  fn run_id(&self) -> &str {
@@ -20,6 +20,7 @@ async-trait = "0.1"
20
20
  derive_builder = { workspace = true }
21
21
  derive_more = { workspace = true }
22
22
  opentelemetry = { workspace = true, optional = true }
23
+ prost = { workspace = true }
23
24
  prost-types = { workspace = true }
24
25
  serde_json = "1.0"
25
26
  thiserror = "1.0"
@@ -5,6 +5,9 @@ use std::{
5
5
  sync::Arc,
6
6
  time::Duration,
7
7
  };
8
+ use temporal_sdk_core_protos::coresdk::{
9
+ ActivitySlotInfo, LocalActivitySlotInfo, WorkflowSlotInfo,
10
+ };
8
11
 
9
12
  const MAX_CONCURRENT_WFT_POLLS_DEFAULT: usize = 5;
10
13
 
@@ -275,7 +278,8 @@ pub trait SlotSupplier {
275
278
  /// Block until a slot is available, then return a permit for the slot.
276
279
  async fn reserve_slot(&self, ctx: &dyn SlotReservationContext) -> SlotSupplierPermit;
277
280
 
278
- /// Try to immediately reserve a slot, returning None if one is not available
281
+ /// Try to immediately reserve a slot, returning None if one is not available. Implementations
282
+ /// must not block, or risk blocking the async event loop.
279
283
  fn try_reserve_slot(&self, ctx: &dyn SlotReservationContext) -> Option<SlotSupplierPermit>;
280
284
 
281
285
  /// Marks a slot as actually now being used. This is separate from reserving one because the
@@ -286,10 +290,10 @@ pub trait SlotSupplier {
286
290
  /// Users' implementation of this can choose to emit metrics, or otherwise leverage the
287
291
  /// information provided by the `info` parameter to be better able to make future decisions
288
292
  /// about whether a slot should be handed out.
289
- fn mark_slot_used(&self, info: <Self::SlotKind as SlotKind>::Info<'_>);
293
+ fn mark_slot_used(&self, ctx: &dyn SlotMarkUsedContext<SlotKind = Self::SlotKind>);
290
294
 
291
295
  /// Frees a slot.
292
- fn release_slot(&self);
296
+ fn release_slot(&self, ctx: &dyn SlotReleaseContext<SlotKind = Self::SlotKind>);
293
297
 
294
298
  /// If this implementation knows how many slots are available at any moment, it should return
295
299
  /// that here.
@@ -299,11 +303,39 @@ pub trait SlotSupplier {
299
303
  }
300
304
 
301
305
  pub trait SlotReservationContext: Send + Sync {
306
+ /// Returns the name of the task queue this worker is polling
307
+ fn task_queue(&self) -> &str;
308
+
309
+ /// Returns the identity of the worker
310
+ fn worker_identity(&self) -> &str;
311
+
312
+ /// Returns the build id of the worker
313
+ fn worker_build_id(&self) -> &str;
314
+
302
315
  /// Returns the number of currently outstanding slot permits, whether used or un-used.
303
316
  fn num_issued_slots(&self) -> usize;
317
+
318
+ /// Returns true iff this is a sticky poll for a workflow task
319
+ fn is_sticky(&self) -> bool;
320
+ }
321
+
322
+ pub trait SlotMarkUsedContext: Send + Sync {
323
+ type SlotKind: SlotKind;
324
+ /// The slot permit that is being used
325
+ fn permit(&self) -> &SlotSupplierPermit;
326
+ /// Returns the info of slot that was marked as used
327
+ fn info(&self) -> &<Self::SlotKind as SlotKind>::Info;
328
+ }
329
+
330
+ pub trait SlotReleaseContext: Send + Sync {
331
+ type SlotKind: SlotKind;
332
+ /// The slot permit that is being used
333
+ fn permit(&self) -> &SlotSupplierPermit;
334
+ /// Returns the info of slot that was released, if it was used
335
+ fn info(&self) -> Option<&<Self::SlotKind as SlotKind>::Info>;
304
336
  }
305
337
 
306
- #[derive(Default)]
338
+ #[derive(Default, Debug)]
307
339
  pub struct SlotSupplierPermit {
308
340
  user_data: Option<Box<dyn Any + Send + Sync>>,
309
341
  }
@@ -325,46 +357,68 @@ impl SlotSupplierPermit {
325
357
  }
326
358
  }
327
359
 
328
- pub struct WorkflowSlotInfo<'a> {
329
- pub workflow_type: &'a str,
330
- // etc...
331
- }
332
-
333
- pub struct ActivitySlotInfo<'a> {
334
- pub activity_type: &'a str,
335
- // etc...
336
- }
337
- pub struct LocalActivitySlotInfo<'a> {
338
- pub activity_type: &'a str,
339
- // etc...
360
+ #[derive(Debug, Copy, Clone, derive_more::Display, Eq, PartialEq)]
361
+ pub enum SlotKindType {
362
+ Workflow,
363
+ Activity,
364
+ LocalActivity,
340
365
  }
341
366
 
342
- #[derive(Debug)]
367
+ #[derive(Debug, Copy, Clone)]
343
368
  pub struct WorkflowSlotKind {}
344
- #[derive(Debug)]
369
+ #[derive(Debug, Copy, Clone)]
345
370
  pub struct ActivitySlotKind {}
346
- #[derive(Debug)]
371
+ #[derive(Debug, Copy, Clone)]
347
372
  pub struct LocalActivitySlotKind {}
373
+
374
+ pub enum SlotInfo<'a> {
375
+ Workflow(&'a WorkflowSlotInfo),
376
+ Activity(&'a ActivitySlotInfo),
377
+ LocalActivity(&'a LocalActivitySlotInfo),
378
+ }
379
+
380
+ pub trait SlotInfoTrait: prost::Message {
381
+ fn downcast(&self) -> SlotInfo;
382
+ }
383
+ impl SlotInfoTrait for WorkflowSlotInfo {
384
+ fn downcast(&self) -> SlotInfo {
385
+ SlotInfo::Workflow(self)
386
+ }
387
+ }
388
+ impl SlotInfoTrait for ActivitySlotInfo {
389
+ fn downcast(&self) -> SlotInfo {
390
+ SlotInfo::Activity(self)
391
+ }
392
+ }
393
+ impl SlotInfoTrait for LocalActivitySlotInfo {
394
+ fn downcast(&self) -> SlotInfo {
395
+ SlotInfo::LocalActivity(self)
396
+ }
397
+ }
398
+
348
399
  pub trait SlotKind {
349
- type Info<'a>;
350
- fn kind_name() -> &'static str;
400
+ type Info: SlotInfoTrait;
401
+
402
+ fn kind() -> SlotKindType;
351
403
  }
352
404
  impl SlotKind for WorkflowSlotKind {
353
- type Info<'a> = WorkflowSlotInfo<'a>;
405
+ type Info = WorkflowSlotInfo;
354
406
 
355
- fn kind_name() -> &'static str {
356
- "workflow"
407
+ fn kind() -> SlotKindType {
408
+ SlotKindType::Workflow
357
409
  }
358
410
  }
359
411
  impl SlotKind for ActivitySlotKind {
360
- type Info<'a> = ActivitySlotInfo<'a>;
361
- fn kind_name() -> &'static str {
362
- "activity"
412
+ type Info = ActivitySlotInfo;
413
+
414
+ fn kind() -> SlotKindType {
415
+ SlotKindType::Activity
363
416
  }
364
417
  }
365
418
  impl SlotKind for LocalActivitySlotKind {
366
- type Info<'a> = LocalActivitySlotInfo<'a>;
367
- fn kind_name() -> &'static str {
368
- "local_activity"
419
+ type Info = LocalActivitySlotInfo;
420
+
421
+ fn kind() -> SlotKindType {
422
+ SlotKindType::LocalActivity
369
423
  }
370
424
  }
@@ -14,9 +14,8 @@ categories = ["development-tools"]
14
14
  async-trait = "0.1"
15
15
  thiserror = "1.0"
16
16
  anyhow = "1.0"
17
- crossbeam-channel = "0.5"
18
17
  derive_more = { workspace = true }
19
- futures = "0.3"
18
+ futures-util = { version = "0.3", default-features = false }
20
19
  parking_lot = { version = "0.12", features = ["send_guard"] }
21
20
  prost-types = { version = "0.6", package = "prost-wkt-types" }
22
21
  serde = "1.0"
@@ -63,7 +63,7 @@ pub use workflow_context::{
63
63
  use crate::{interceptors::WorkerInterceptor, workflow_context::ChildWfCommon};
64
64
  use anyhow::{anyhow, bail, Context};
65
65
  use app_data::AppData;
66
- use futures::{future::BoxFuture, FutureExt, StreamExt, TryFutureExt, TryStreamExt};
66
+ use futures_util::{future::BoxFuture, FutureExt, StreamExt, TryFutureExt, TryStreamExt};
67
67
  use serde::Serialize;
68
68
  use std::{
69
69
  any::{Any, TypeId},
@@ -11,8 +11,7 @@ use crate::{
11
11
  IntoUpdateValidatorFunc, RustWfCmd, SignalExternalWfResult, TimerResult, UnblockEvent,
12
12
  Unblockable, UpdateFunctions,
13
13
  };
14
- use crossbeam_channel::{Receiver, Sender};
15
- use futures::{task::Context, FutureExt, Stream, StreamExt};
14
+ use futures_util::{task::Context, FutureExt, Stream, StreamExt};
16
15
  use parking_lot::{RwLock, RwLockReadGuard};
17
16
  use std::{
18
17
  collections::HashMap,
@@ -22,6 +21,7 @@ use std::{
22
21
  pin::Pin,
23
22
  sync::{
24
23
  atomic::{AtomicBool, Ordering},
24
+ mpsc::{Receiver, Sender},
25
25
  Arc,
26
26
  },
27
27
  task::Poll,
@@ -71,8 +71,8 @@ impl WfContext {
71
71
  args: Vec<Payload>,
72
72
  am_cancelled: watch::Receiver<bool>,
73
73
  ) -> (Self, Receiver<RustWfCmd>) {
74
- // We need to use a normal std channel since our receiving side is non-async
75
- let (chan, rx) = crossbeam_channel::unbounded();
74
+ // The receiving side is non-async
75
+ let (chan, rx) = std::sync::mpsc::channel();
76
76
  (
77
77
  Self {
78
78
  namespace,
@@ -344,6 +344,11 @@ impl WfContext {
344
344
  ))
345
345
  }
346
346
 
347
+ /// Buffer a command to be sent in the activation reply
348
+ pub(crate) fn send(&self, c: RustWfCmd) {
349
+ self.chan.send(c).expect("command channel intact");
350
+ }
351
+
347
352
  fn send_signal_wf(
348
353
  &self,
349
354
  target: sig_we::Target,
@@ -373,10 +378,6 @@ impl WfContext {
373
378
  fn cancel(&self, cancellable_id: CancellableID) {
374
379
  self.send(RustWfCmd::Cancel(cancellable_id));
375
380
  }
376
-
377
- fn send(&self, c: RustWfCmd) {
378
- self.chan.send(c).unwrap();
379
- }
380
381
  }
381
382
 
382
383
  struct WfCtxProtectedDat {
@@ -4,14 +4,14 @@ use crate::{
4
4
  WorkflowResult,
5
5
  };
6
6
  use anyhow::{anyhow, bail, Context as AnyhowContext, Error};
7
- use crossbeam_channel::Receiver;
8
- use futures::{future::BoxFuture, FutureExt};
7
+ use futures_util::{future::BoxFuture, FutureExt};
9
8
  use std::{
10
9
  collections::{hash_map::Entry, HashMap},
11
10
  future::Future,
12
11
  panic,
13
12
  panic::AssertUnwindSafe,
14
13
  pin::Pin,
14
+ sync::mpsc::Receiver,
15
15
  task::{Context, Poll},
16
16
  };
17
17
  use temporal_sdk_core_protos::{
@@ -397,22 +397,27 @@ impl Future for WorkflowFuture {
397
397
  // Drive update functions
398
398
  self.update_futures = std::mem::take(&mut self.update_futures)
399
399
  .into_iter()
400
- .filter_map(|(instance_id, mut update_fut)| {
401
- match update_fut.poll_unpin(cx) {
400
+ .filter_map(
401
+ |(instance_id, mut update_fut)| match update_fut.poll_unpin(cx) {
402
402
  Poll::Ready(v) => {
403
- activation_cmds.push(update_response(
404
- instance_id,
405
- match v {
406
- Ok(v) => update_response::Response::Completed(v),
407
- Err(e) => update_response::Response::Rejected(e.into()),
408
- },
409
- ));
410
- // Delete if we're done.
403
+ // Push into the command channel here rather than activation_cmds
404
+ // directly to avoid completing and update before any final un-awaited
405
+ // commands started from within it.
406
+ self.wf_ctx.send(
407
+ update_response(
408
+ instance_id,
409
+ match v {
410
+ Ok(v) => update_response::Response::Completed(v),
411
+ Err(e) => update_response::Response::Rejected(e.into()),
412
+ },
413
+ )
414
+ .into(),
415
+ );
411
416
  None
412
417
  }
413
418
  Poll::Pending => Some((instance_id, update_fut)),
414
- }
415
- })
419
+ },
420
+ )
416
421
  .collect();
417
422
 
418
423
  if self.poll_wf_future(cx, &run_id, &mut activation_cmds)? {
@@ -19,6 +19,7 @@ anyhow = "1.0"
19
19
  base64 = "0.22"
20
20
  derive_more = { workspace = true }
21
21
  prost = { workspace = true }
22
+ prost-types = { workspace = true }
22
23
  prost-wkt = "0.6"
23
24
  prost-wkt-types = "0.6"
24
25
  rand = { version = "0.8", optional = true }
@@ -30,6 +31,7 @@ uuid = { version = "1.1", features = ["v4"], optional = true }
30
31
 
31
32
  [build-dependencies]
32
33
  tonic-build = { workspace = true }
34
+ prost-build = "0.13"
33
35
  prost-wkt-build = "0.6"
34
36
 
35
37
  [lints]
@@ -112,8 +112,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
112
112
  ".google.protobuf.Value",
113
113
  "::prost_wkt_types::Value"
114
114
  )
115
+ .extern_path(
116
+ ".google.protobuf.FieldMask",
117
+ "::prost_wkt_types::FieldMask"
118
+ )
115
119
  .file_descriptor_set_path(descriptor_file)
116
- .compile(
120
+ .skip_debug("temporal.api.common.v1.Payload")
121
+ .compile_protos(
117
122
  &[
118
123
  "./protos/local/temporal/sdk/core/core_interface.proto",
119
124
  "./protos/api_upstream/temporal/api/workflowservice/v1/service.proto",
@@ -1,6 +1,7 @@
1
1
  version: v1
2
2
  deps:
3
3
  - buf.build/grpc-ecosystem/grpc-gateway
4
+ - buf.build/googleapis/googleapis
4
5
  build:
5
6
  excludes:
6
7
  # Buf won't accept a local dependency on the google protos but we need them