@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
@@ -256,6 +256,17 @@ service WorkflowService {
256
256
  rpc TerminateWorkflowExecution (TerminateWorkflowExecutionRequest) returns (TerminateWorkflowExecutionResponse) {
257
257
  }
258
258
 
259
+ // DeleteWorkflowExecution asynchronously deletes a specific Workflow Execution (when
260
+ // WorkflowExecution.run_id is provided) or the latest Workflow Execution (when
261
+ // WorkflowExecution.run_id is not provided). If the Workflow Execution is Running, it will be
262
+ // terminated before deletion.
263
+ // (-- api-linter: core::0135::method-signature=disabled
264
+ // aip.dev/not-precedent: DeleteNamespace RPC doesn't follow Google API format. --)
265
+ // (-- api-linter: core::0135::response-message-name=disabled
266
+ // aip.dev/not-precedent: DeleteNamespace RPC doesn't follow Google API format. --)
267
+ rpc DeleteWorkflowExecution (DeleteWorkflowExecutionRequest) returns (DeleteWorkflowExecutionResponse) {
268
+ }
269
+
259
270
  // ListOpenWorkflowExecutions is a visibility API to list the open executions in a specific namespace.
260
271
  rpc ListOpenWorkflowExecutions (ListOpenWorkflowExecutionsRequest) returns (ListOpenWorkflowExecutionsResponse) {
261
272
  }
@@ -369,12 +380,15 @@ service WorkflowService {
369
380
  rpc ListSchedules (ListSchedulesRequest) returns (ListSchedulesResponse) {
370
381
  }
371
382
 
383
+ // Allows users to specify a graph of worker build id based versions on a
384
+ // per task queue basis. Versions are ordered, and may be either compatible
385
+ // with some extant version, or a new incompatible version.
372
386
  // (-- api-linter: core::0134::response-message-name=disabled
373
387
  // aip.dev/not-precedent: UpdateWorkerBuildIdOrdering RPC doesn't follow Google API format. --)
374
388
  // (-- api-linter: core::0134::method-signature=disabled
375
389
  // aip.dev/not-precedent: UpdateWorkerBuildIdOrdering RPC doesn't follow Google API format. --)
376
390
  rpc UpdateWorkerBuildIdOrdering (UpdateWorkerBuildIdOrderingRequest) returns (UpdateWorkerBuildIdOrderingResponse) {}
377
- // This could / maybe should just be part of `DescribeTaskQueue`, but is broken out here to show easily.
391
+ // Fetches the worker build id versioning graph for some task queue.
378
392
  rpc GetWorkerBuildIdOrdering (GetWorkerBuildIdOrderingRequest) returns (GetWorkerBuildIdOrderingResponse) {}
379
393
 
380
394
  // Invokes the specified update function on user workflow code.
@@ -119,6 +119,8 @@ message StartWorkflow {
119
119
  temporal.api.common.v1.Memo memo = 21;
120
120
  // Search attributes created/updated when this workflow was started
121
121
  temporal.api.common.v1.SearchAttributes search_attributes = 22;
122
+ // When the workflow execution started event was first written
123
+ google.protobuf.Timestamp start_time = 23;
122
124
  }
123
125
 
124
126
  /// Notify a workflow that a timer has fired
@@ -35,6 +35,7 @@ message WorkflowCommand {
35
35
  ScheduleLocalActivity schedule_local_activity = 16;
36
36
  RequestCancelLocalActivity request_cancel_local_activity = 17;
37
37
  UpsertWorkflowSearchAttributes upsert_workflow_search_attributes = 18;
38
+ ModifyWorkflowProperties modify_workflow_properties = 19;
38
39
  }
39
40
  }
40
41
 
@@ -54,7 +55,6 @@ message ScheduleActivity {
54
55
  uint32 seq = 1;
55
56
  string activity_id = 2;
56
57
  string activity_type = 3;
57
- string namespace = 4;
58
58
  // The name of the task queue to place this activity request in
59
59
  string task_queue = 5;
60
60
  map<string, temporal.api.common.v1.Payload> headers = 6;
@@ -295,3 +295,10 @@ message UpsertWorkflowSearchAttributes {
295
295
  /// value?
296
296
  map<string, temporal.api.common.v1.Payload> search_attributes = 1;
297
297
  }
298
+
299
+ message ModifyWorkflowProperties {
300
+ // If set, update the workflow memo with the provided values. The values will be merged with
301
+ // the existing memo. If the user wants to delete values, a default/empty Payload should be
302
+ // used as the value for the key being deleted.
303
+ temporal.api.common.v1.Memo upserted_memo = 1;
304
+ }
@@ -1,7 +1,11 @@
1
1
  //! User-definable interceptors are defined in this module
2
2
 
3
3
  use crate::Worker;
4
- use temporal_sdk_core_protos::coresdk::workflow_completion::WorkflowActivationCompletion;
4
+ use anyhow::bail;
5
+ use temporal_sdk_core_protos::coresdk::{
6
+ workflow_activation::{remove_from_cache::EvictionReason, WorkflowActivation},
7
+ workflow_completion::WorkflowActivationCompletion,
8
+ };
5
9
 
6
10
  /// Implementors can intercept certain actions that happen within the Worker.
7
11
  ///
@@ -10,8 +14,37 @@ use temporal_sdk_core_protos::coresdk::workflow_completion::WorkflowActivationCo
10
14
  pub trait WorkerInterceptor {
11
15
  /// Called every time a workflow activation completes (just before sending the completion to
12
16
  /// core).
13
- async fn on_workflow_activation_completion(&self, completion: &WorkflowActivationCompletion);
17
+ async fn on_workflow_activation_completion(&self, _completion: &WorkflowActivationCompletion) {}
14
18
  /// Called after the worker has initiated shutdown and the workflow/activity polling loops
15
19
  /// have exited, but just before waiting for the inner core worker shutdown
16
- fn on_shutdown(&self, sdk_worker: &Worker);
20
+ fn on_shutdown(&self, _sdk_worker: &Worker) {}
21
+ /// Called every time a workflow is about to be activated
22
+ async fn on_workflow_activation(
23
+ &self,
24
+ _activation: &WorkflowActivation,
25
+ ) -> Result<(), anyhow::Error> {
26
+ Ok(())
27
+ }
28
+ }
29
+
30
+ /// An interceptor which causes the worker's run function to exit early if nondeterminism errors are
31
+ /// encountered
32
+ pub struct FailOnNondeterminismInterceptor {}
33
+ #[async_trait::async_trait(?Send)]
34
+ impl WorkerInterceptor for FailOnNondeterminismInterceptor {
35
+ async fn on_workflow_activation(
36
+ &self,
37
+ activation: &WorkflowActivation,
38
+ ) -> Result<(), anyhow::Error> {
39
+ if matches!(
40
+ activation.eviction_reason(),
41
+ Some(EvictionReason::Nondeterminism)
42
+ ) {
43
+ bail!(
44
+ "Workflow is being evicted because of nondeterminism! {}",
45
+ activation
46
+ );
47
+ }
48
+ Ok(())
49
+ }
17
50
  }
@@ -10,8 +10,8 @@
10
10
  //! ```no_run
11
11
  //! use std::{str::FromStr, sync::Arc};
12
12
  //! use temporal_sdk::{sdk_client_options, ActContext, Worker};
13
- //! use temporal_sdk_core::{init_worker, telemetry_init, TelemetryOptionsBuilder, Url};
14
- //! use temporal_sdk_core_api::worker::WorkerConfigBuilder;
13
+ //! use temporal_sdk_core::{init_worker, Url, CoreRuntime};
14
+ //! use temporal_sdk_core_api::{worker::WorkerConfigBuilder, telemetry::TelemetryOptionsBuilder};
15
15
  //!
16
16
  //! #[tokio::main]
17
17
  //! async fn main() -> Result<(), Box<dyn std::error::Error>> {
@@ -20,14 +20,14 @@
20
20
  //! let client = server_options.connect("default", None, None).await?;
21
21
  //!
22
22
  //! let telemetry_options = TelemetryOptionsBuilder::default().build()?;
23
- //! telemetry_init(&telemetry_options)?;
23
+ //! let runtime = CoreRuntime::new_assume_tokio(telemetry_options)?;
24
24
  //!
25
25
  //! let worker_config = WorkerConfigBuilder::default()
26
26
  //! .namespace("default")
27
27
  //! .task_queue("task_queue")
28
28
  //! .build()?;
29
29
  //!
30
- //! let core_worker = init_worker(worker_config, client);
30
+ //! let core_worker = init_worker(&runtime, worker_config, client)?;
31
31
  //!
32
32
  //! let mut worker = Worker::new_from_core(Arc::new(core_worker), "task_queue");
33
33
  //! worker.register_activity(
@@ -279,6 +279,9 @@ impl Worker {
279
279
  }
280
280
  o => o?,
281
281
  };
282
+ if let Some(ref i) = common.worker_interceptor {
283
+ i.on_workflow_activation(&activation).await?;
284
+ }
282
285
  if let Some(wf_fut) = wf_half.workflow_activation_handler(
283
286
  common,
284
287
  shutdown_token.clone(),
@@ -34,11 +34,11 @@ use temporal_sdk_core_protos::{
34
34
  workflow_commands::{
35
35
  request_cancel_external_workflow_execution as cancel_we,
36
36
  signal_external_workflow_execution as sig_we, workflow_command,
37
- RequestCancelExternalWorkflowExecution, SetPatchMarker,
37
+ ModifyWorkflowProperties, RequestCancelExternalWorkflowExecution, SetPatchMarker,
38
38
  SignalExternalWorkflowExecution, StartTimer, UpsertWorkflowSearchAttributes,
39
39
  },
40
40
  },
41
- temporal::api::common::v1::Payload,
41
+ temporal::api::common::v1::{Memo, Payload},
42
42
  };
43
43
  use tokio::sync::{mpsc, oneshot, watch};
44
44
  use tokio_stream::wrappers::UnboundedReceiverStream;
@@ -297,6 +297,17 @@ impl WfContext {
297
297
  ))
298
298
  }
299
299
 
300
+ /// Add or create a set of search attributes
301
+ pub fn upsert_memo(&self, attr_iter: impl IntoIterator<Item = (String, Payload)>) {
302
+ self.send(RustWfCmd::NewNonblockingCmd(
303
+ workflow_command::Variant::ModifyWorkflowProperties(ModifyWorkflowProperties {
304
+ upserted_memo: Some(Memo {
305
+ fields: HashMap::from_iter(attr_iter.into_iter()),
306
+ }),
307
+ }),
308
+ ))
309
+ }
310
+
300
311
  /// Return a stream that produces values when the named signal is sent to this workflow
301
312
  pub fn make_signal_channel(&self, signal_name: impl Into<String>) -> DrainableSignalStream {
302
313
  let (tx, rx) = mpsc::unbounded_channel();
@@ -10,9 +10,10 @@ use crate::{
10
10
  },
11
11
  temporal::api::{
12
12
  common::v1::{Payload, Payloads, WorkflowExecution, WorkflowType},
13
- enums::v1::{EventType, WorkflowTaskFailedCause},
13
+ enums::v1::{EventType, TaskQueueKind, WorkflowTaskFailedCause},
14
14
  failure::v1::{failure, CanceledFailureInfo, Failure},
15
15
  history::v1::{history_event::Attributes, *},
16
+ taskqueue::v1::TaskQueue,
16
17
  },
17
18
  HistoryInfo,
18
19
  };
@@ -38,6 +39,27 @@ pub struct TestHistoryBuilder {
38
39
  }
39
40
 
40
41
  impl TestHistoryBuilder {
42
+ pub fn from_history(events: Vec<HistoryEvent>) -> Self {
43
+ let find_matching_id = |etype: EventType| {
44
+ events
45
+ .iter()
46
+ .rev()
47
+ .find(|e| e.event_type() == etype)
48
+ .map(|e| e.event_id)
49
+ .unwrap_or_default()
50
+ };
51
+ Self {
52
+ current_event_id: events.last().map(|e| e.event_id).unwrap_or_default(),
53
+ workflow_task_scheduled_event_id: find_matching_id(EventType::WorkflowTaskScheduled),
54
+ final_workflow_task_started_event_id: find_matching_id(EventType::WorkflowTaskStarted),
55
+ previous_task_completed_id: find_matching_id(EventType::WorkflowTaskCompleted),
56
+ original_run_id: extract_original_run_id_from_events(&events)
57
+ .expect("Run id must be discoverable")
58
+ .to_string(),
59
+ events,
60
+ }
61
+ }
62
+
41
63
  /// Add an event by type with attributes. Bundles both into a [HistoryEvent] with an id that is
42
64
  /// incremented on each call to add.
43
65
  pub fn add(&mut self, event_type: EventType, attribs: Attributes) {
@@ -450,6 +472,26 @@ impl TestHistoryBuilder {
450
472
  .unwrap()
451
473
  }
452
474
 
475
+ /// Alter the workflow type of the history
476
+ pub fn set_wf_type(&mut self, name: &str) {
477
+ if let Some(Attributes::WorkflowExecutionStartedEventAttributes(wes)) =
478
+ self.events.get_mut(0).and_then(|e| e.attributes.as_mut())
479
+ {
480
+ wes.workflow_type = Some(WorkflowType {
481
+ name: name.to_string(),
482
+ })
483
+ }
484
+ }
485
+
486
+ /// Alter some specific event. You can easily craft nonsense histories this way, use carefully.
487
+ pub fn modify_event(&mut self, event_id: i64, modifier: impl FnOnce(&mut HistoryEvent)) {
488
+ let he = self
489
+ .events
490
+ .get_mut((event_id - 1) as usize)
491
+ .expect("Event must be present");
492
+ modifier(he);
493
+ }
494
+
453
495
  fn build_and_push_event(&mut self, event_type: EventType, attribs: Attributes) {
454
496
  self.current_event_id += 1;
455
497
  let evt = HistoryEvent {
@@ -492,6 +534,10 @@ pub fn default_wes_attribs() -> WorkflowExecutionStartedEventAttributes {
492
534
  .try_into()
493
535
  .expect("5 secs is a valid duration"),
494
536
  ),
537
+ task_queue: Some(TaskQueue {
538
+ name: "q".to_string(),
539
+ kind: TaskQueueKind::Normal as i32,
540
+ }),
495
541
  ..Default::default()
496
542
  }
497
543
  }
@@ -1,7 +1,7 @@
1
1
  use crate::temporal::api::{
2
2
  common::v1::WorkflowType,
3
3
  enums::v1::{EventType, TaskQueueKind},
4
- history::v1::{history_event, History, HistoryEvent},
4
+ history::v1::{history_event, History, HistoryEvent, WorkflowExecutionStartedEventAttributes},
5
5
  taskqueue::v1::TaskQueue,
6
6
  workflowservice::v1::{GetWorkflowExecutionHistoryResponse, PollWorkflowTaskQueueResponse},
7
7
  };
@@ -18,6 +18,7 @@ pub struct HistoryInfo {
18
18
  events: Vec<HistoryEvent>,
19
19
  wf_task_count: usize,
20
20
  wf_type: String,
21
+ wf_exe_started_attrs: WorkflowExecutionStartedEventAttributes,
21
22
  }
22
23
 
23
24
  type Result<T, E = anyhow::Error> = std::result::Result<T, E>;
@@ -36,20 +37,18 @@ impl HistoryInfo {
36
37
  let mut workflow_task_started_event_id = 0;
37
38
  let mut wf_task_count = 0;
38
39
  let mut history = events.iter().peekable();
39
-
40
- let wf_type = match &events.get(0).unwrap().attributes {
40
+ let started_attrs = match &events.get(0).unwrap().attributes {
41
41
  Some(history_event::Attributes::WorkflowExecutionStartedEventAttributes(attrs)) => {
42
- attrs
43
- .workflow_type
44
- .as_ref()
45
- .ok_or_else(|| {
46
- anyhow!("No workflow type defined in execution started attributes")
47
- })?
48
- .name
49
- .clone()
42
+ attrs.clone()
50
43
  }
51
44
  _ => bail!("First event in history was not workflow execution started!"),
52
45
  };
46
+ let wf_type = started_attrs
47
+ .workflow_type
48
+ .as_ref()
49
+ .ok_or_else(|| anyhow!("No workflow type defined in execution started attributes"))?
50
+ .name
51
+ .clone();
53
52
 
54
53
  let mut events = vec![];
55
54
  while let Some(event) = history.next() {
@@ -87,6 +86,7 @@ impl HistoryInfo {
87
86
  events,
88
87
  wf_task_count,
89
88
  wf_type,
89
+ wf_exe_started_attrs: started_attrs,
90
90
  });
91
91
  }
92
92
  } else if next_event.is_some() && !next_is_failed_or_timeout_or_term {
@@ -108,6 +108,7 @@ impl HistoryInfo {
108
108
  events,
109
109
  wf_task_count,
110
110
  wf_type,
111
+ wf_exe_started_attrs: started_attrs,
111
112
  });
112
113
  }
113
114
  // No more events
@@ -135,16 +136,9 @@ impl HistoryInfo {
135
136
  &self.events
136
137
  }
137
138
 
138
- /// Attempt to extract run id from internal events. If the first event is not workflow execution
139
- /// started, it will panic.
139
+ /// Extract run id from the workflow execution started attributes.
140
140
  pub fn orig_run_id(&self) -> &str {
141
- if let Some(history_event::Attributes::WorkflowExecutionStartedEventAttributes(wes)) =
142
- &self.events[0].attributes
143
- {
144
- &wes.original_execution_run_id
145
- } else {
146
- panic!("First event is wrong type")
147
- }
141
+ &self.wf_exe_started_attrs.original_execution_run_id
148
142
  }
149
143
 
150
144
  /// Return total workflow task count in this history
@@ -155,7 +149,7 @@ impl HistoryInfo {
155
149
  /// Create a workflow task polling response containing all the events in this history and a
156
150
  /// randomly generated task token. Caller should attach a meaningful `workflow_execution` if
157
151
  /// needed.
158
- pub fn as_poll_wft_response(&self, task_q: impl Into<String>) -> PollWorkflowTaskQueueResponse {
152
+ pub fn as_poll_wft_response(&self) -> PollWorkflowTaskQueueResponse {
159
153
  let task_token: [u8; 16] = thread_rng().gen();
160
154
  PollWorkflowTaskQueueResponse {
161
155
  history: Some(History {
@@ -166,7 +160,13 @@ impl HistoryInfo {
166
160
  name: self.wf_type.clone(),
167
161
  }),
168
162
  workflow_execution_task_queue: Some(TaskQueue {
169
- name: task_q.into(),
163
+ name: self
164
+ .wf_exe_started_attrs
165
+ .task_queue
166
+ .as_ref()
167
+ .unwrap()
168
+ .name
169
+ .clone(),
170
170
  kind: TaskQueueKind::Normal as i32,
171
171
  }),
172
172
  previous_started_event_id: self.previous_started_event_id,
@@ -66,7 +66,7 @@ pub mod coresdk {
66
66
  "ActivityTaskCompletion(token: {}",
67
67
  fmt_tt(&self.task_token),
68
68
  )?;
69
- if let Some(r) = self.result.as_ref() {
69
+ if let Some(r) = self.result.as_ref().and_then(|r| r.status.as_ref()) {
70
70
  write!(f, ", {}", r)?;
71
71
  } else {
72
72
  write!(f, ", missing result")?;
@@ -120,21 +120,20 @@ pub mod coresdk {
120
120
  }
121
121
  }
122
122
 
123
- impl Display for ActivityExecutionResult {
123
+ impl Display for aer::Status {
124
124
  fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
125
125
  write!(f, "ActivityExecutionResult(")?;
126
- match self.status.as_ref() {
127
- None => write!(f, "missing result)"),
128
- Some(aer::Status::Completed(v)) => {
126
+ match self {
127
+ aer::Status::Completed(v) => {
129
128
  write!(f, "{})", v)
130
129
  }
131
- Some(aer::Status::Failed(v)) => {
130
+ aer::Status::Failed(v) => {
132
131
  write!(f, "{})", v)
133
132
  }
134
- Some(aer::Status::Cancelled(v)) => {
133
+ aer::Status::Cancelled(v) => {
135
134
  write!(f, "{})", v)
136
135
  }
137
- Some(aer::Status::WillCompleteAsync(_)) => {
136
+ aer::Status::WillCompleteAsync(_) => {
138
137
  write!(f, "Will complete async)")
139
138
  }
140
139
  }
@@ -405,6 +404,7 @@ pub mod coresdk {
405
404
  query::v1::WorkflowQuery,
406
405
  },
407
406
  };
407
+ use prost_types::Timestamp;
408
408
  use std::{
409
409
  collections::HashMap,
410
410
  fmt::{Display, Formatter},
@@ -600,6 +600,7 @@ pub mod coresdk {
600
600
  attrs: WorkflowExecutionStartedEventAttributes,
601
601
  workflow_id: String,
602
602
  randomness_seed: u64,
603
+ start_time: Timestamp,
603
604
  ) -> StartWorkflow {
604
605
  StartWorkflow {
605
606
  workflow_type: attrs.workflow_type.map(|wt| wt.name).unwrap_or_default(),
@@ -633,6 +634,7 @@ pub mod coresdk {
633
634
  cron_schedule_to_schedule_interval: attrs.first_workflow_task_backoff,
634
635
  memo: attrs.memo,
635
636
  search_attributes: attrs.search_attributes,
637
+ start_time: Some(start_time),
636
638
  }
637
639
  }
638
640
  }
@@ -800,6 +802,16 @@ pub mod coresdk {
800
802
  }
801
803
  }
802
804
 
805
+ impl Display for ModifyWorkflowProperties {
806
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
807
+ write!(
808
+ f,
809
+ "ModifyWorkflowProperties(upserted memo keys: {:?})",
810
+ self.upserted_memo.as_ref().map(|m| m.fields.keys())
811
+ )
812
+ }
813
+ }
814
+
803
815
  impl QueryResult {
804
816
  /// Helper to construct the Temporal API query result types.
805
817
  pub fn into_components(self) -> (String, QueryResultType, Option<Payloads>, String) {
@@ -1320,11 +1332,6 @@ pub mod coresdk {
1320
1332
  // This is disgusting, but unclear to me how to avoid it. TODO: Discuss w/ prost maintainer
1321
1333
  pub mod temporal {
1322
1334
  pub mod api {
1323
- pub mod cluster {
1324
- pub mod v1 {
1325
- tonic::include_proto!("temporal.api.cluster.v1");
1326
- }
1327
- }
1328
1335
  pub mod batch {
1329
1336
  pub mod v1 {
1330
1337
  tonic::include_proto!("temporal.api.batch.v1");
@@ -1414,6 +1421,16 @@ pub mod temporal {
1414
1421
  }
1415
1422
  }
1416
1423
 
1424
+ impl From<workflow_commands::ModifyWorkflowProperties> for command::Attributes {
1425
+ fn from(s: workflow_commands::ModifyWorkflowProperties) -> Self {
1426
+ Self::ModifyWorkflowPropertiesCommandAttributes(
1427
+ ModifyWorkflowPropertiesCommandAttributes {
1428
+ upserted_memo: s.upserted_memo.map(Into::into),
1429
+ },
1430
+ )
1431
+ }
1432
+ }
1433
+
1417
1434
  impl From<workflow_commands::CancelTimer> for command::Attributes {
1418
1435
  fn from(s: workflow_commands::CancelTimer) -> Self {
1419
1436
  Self::CancelTimerCommandAttributes(CancelTimerCommandAttributes {
@@ -1647,14 +1664,7 @@ pub mod temporal {
1647
1664
 
1648
1665
  impl History {
1649
1666
  pub fn extract_run_id_from_start(&self) -> Result<&str, anyhow::Error> {
1650
- if let Some(
1651
- history_event::Attributes::WorkflowExecutionStartedEventAttributes(wes),
1652
- ) = self.events.get(0).and_then(|x| x.attributes.as_ref())
1653
- {
1654
- Ok(&wes.original_execution_run_id)
1655
- } else {
1656
- bail!("First event is not WorkflowExecutionStarted?!?")
1657
- }
1667
+ extract_original_run_id_from_events(&self.events)
1658
1668
  }
1659
1669
 
1660
1670
  /// Returns the event id of the final event in the history. Will return 0 if
@@ -1664,6 +1674,18 @@ pub mod temporal {
1664
1674
  }
1665
1675
  }
1666
1676
 
1677
+ pub fn extract_original_run_id_from_events(
1678
+ events: &[HistoryEvent],
1679
+ ) -> Result<&str, anyhow::Error> {
1680
+ if let Some(Attributes::WorkflowExecutionStartedEventAttributes(wes)) =
1681
+ events.get(0).and_then(|x| x.attributes.as_ref())
1682
+ {
1683
+ Ok(&wes.original_execution_run_id)
1684
+ } else {
1685
+ bail!("First event is not WorkflowExecutionStarted?!?")
1686
+ }
1687
+ }
1688
+
1667
1689
  impl HistoryEvent {
1668
1690
  /// Returns true if this is an event created to mirror a command
1669
1691
  pub fn is_command_event(&self) -> bool {
@@ -1820,12 +1842,12 @@ pub mod temporal {
1820
1842
  tonic::include_proto!("temporal.api.workflowservice.v1");
1821
1843
 
1822
1844
  macro_rules! sched_to_start_impl {
1823
- () => {
1824
- /// Return the duration of the task schedule time to its start time if both
1825
- /// are set and time went forward.
1845
+ ($sched_field:ident) => {
1846
+ /// Return the duration of the task schedule time (current attempt) to its
1847
+ /// start time if both are set and time went forward.
1826
1848
  pub fn sched_to_start(&self) -> Option<Duration> {
1827
1849
  if let Some((sch, st)) =
1828
- self.scheduled_time.clone().zip(self.started_time.clone())
1850
+ self.$sched_field.clone().zip(self.started_time.clone())
1829
1851
  {
1830
1852
  let sch: Result<SystemTime, _> = sch.try_into();
1831
1853
  let st: Result<SystemTime, _> = st.try_into();
@@ -1839,7 +1861,7 @@ pub mod temporal {
1839
1861
  }
1840
1862
 
1841
1863
  impl PollWorkflowTaskQueueResponse {
1842
- sched_to_start_impl!();
1864
+ sched_to_start_impl!(scheduled_time);
1843
1865
  }
1844
1866
 
1845
1867
  impl Display for PollWorkflowTaskQueueResponse {
@@ -1881,7 +1903,7 @@ pub mod temporal {
1881
1903
  }
1882
1904
 
1883
1905
  impl PollActivityTaskQueueResponse {
1884
- sched_to_start_impl!();
1906
+ sched_to_start_impl!(current_attempt_scheduled_time);
1885
1907
  }
1886
1908
 
1887
1909
  impl QueryWorkflowResponse {
@@ -14,6 +14,7 @@ async-trait = "0.1"
14
14
  base64 = "0.13"
15
15
  futures = "0.3"
16
16
  log = "0.4"
17
+ once_cell = "1.16"
17
18
  parking_lot = "0.12"
18
19
  prost = "0.11"
19
20
  prost-types = "0.11"