@temporalio/core-bridge 0.17.2 → 0.18.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 (170) hide show
  1. package/Cargo.lock +339 -226
  2. package/Cargo.toml +7 -3
  3. package/common.js +50 -0
  4. package/index.d.ts +7 -0
  5. package/index.js +12 -0
  6. package/package.json +7 -4
  7. package/releases/aarch64-apple-darwin/index.node +0 -0
  8. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  9. package/{index.node → releases/index.node} +0 -0
  10. package/releases/x86_64-apple-darwin/index.node +0 -0
  11. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  12. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  13. package/scripts/build.js +10 -50
  14. package/sdk-core/.buildkite/docker/Dockerfile +1 -1
  15. package/sdk-core/.buildkite/docker/docker-compose.yaml +2 -2
  16. package/sdk-core/.buildkite/pipeline.yml +2 -0
  17. package/sdk-core/Cargo.toml +1 -88
  18. package/sdk-core/README.md +30 -6
  19. package/sdk-core/bridge-ffi/Cargo.toml +24 -0
  20. package/sdk-core/bridge-ffi/LICENSE.txt +23 -0
  21. package/sdk-core/bridge-ffi/build.rs +25 -0
  22. package/sdk-core/bridge-ffi/include/sdk-core-bridge.h +216 -0
  23. package/sdk-core/bridge-ffi/src/lib.rs +829 -0
  24. package/sdk-core/bridge-ffi/src/wrappers.rs +193 -0
  25. package/sdk-core/client/Cargo.toml +32 -0
  26. package/sdk-core/{src/pollers/gateway.rs → client/src/lib.rs} +101 -195
  27. package/sdk-core/client/src/metrics.rs +89 -0
  28. package/sdk-core/client/src/mocks.rs +167 -0
  29. package/sdk-core/{src/pollers → client/src}/retry.rs +172 -14
  30. package/sdk-core/core/Cargo.toml +96 -0
  31. package/sdk-core/{src → core/src}/core_tests/activity_tasks.rs +193 -37
  32. package/sdk-core/{src → core/src}/core_tests/child_workflows.rs +14 -14
  33. package/sdk-core/{src → core/src}/core_tests/determinism.rs +8 -8
  34. package/sdk-core/core/src/core_tests/local_activities.rs +328 -0
  35. package/sdk-core/{src → core/src}/core_tests/mod.rs +6 -9
  36. package/sdk-core/{src → core/src}/core_tests/queries.rs +45 -52
  37. package/sdk-core/{src → core/src}/core_tests/replay_flag.rs +8 -12
  38. package/sdk-core/{src → core/src}/core_tests/workers.rs +120 -33
  39. package/sdk-core/{src → core/src}/core_tests/workflow_cancels.rs +16 -26
  40. package/sdk-core/{src → core/src}/core_tests/workflow_tasks.rs +264 -286
  41. package/sdk-core/core/src/lib.rs +374 -0
  42. package/sdk-core/{src → core/src}/log_export.rs +3 -27
  43. package/sdk-core/core/src/pending_activations.rs +162 -0
  44. package/sdk-core/{src → core/src}/pollers/mod.rs +4 -22
  45. package/sdk-core/{src → core/src}/pollers/poll_buffer.rs +1 -1
  46. package/sdk-core/core/src/protosext/mod.rs +396 -0
  47. package/sdk-core/core/src/replay/mod.rs +210 -0
  48. package/sdk-core/core/src/retry_logic.rs +144 -0
  49. package/sdk-core/{src → core/src}/telemetry/metrics.rs +3 -58
  50. package/sdk-core/{src → core/src}/telemetry/mod.rs +8 -8
  51. package/sdk-core/{src → core/src}/telemetry/prometheus_server.rs +0 -0
  52. package/sdk-core/{src → core/src}/test_help/mod.rs +34 -73
  53. package/sdk-core/{src → core/src}/worker/activities/activity_heartbeat_manager.rs +95 -42
  54. package/sdk-core/core/src/worker/activities/local_activities.rs +973 -0
  55. package/sdk-core/{src → core/src}/worker/activities.rs +52 -33
  56. package/sdk-core/{src → core/src}/worker/dispatcher.rs +8 -6
  57. package/sdk-core/{src → core/src}/worker/mod.rs +305 -195
  58. package/sdk-core/core/src/worker/wft_delivery.rs +81 -0
  59. package/sdk-core/{src → core/src}/workflow/bridge.rs +5 -2
  60. package/sdk-core/{src → core/src}/workflow/driven_workflow.rs +17 -7
  61. package/sdk-core/{src → core/src}/workflow/history_update.rs +33 -7
  62. package/sdk-core/{src → core/src/workflow}/machines/activity_state_machine.rs +26 -26
  63. package/sdk-core/{src → core/src/workflow}/machines/cancel_external_state_machine.rs +8 -11
  64. package/sdk-core/{src → core/src/workflow}/machines/cancel_workflow_state_machine.rs +19 -21
  65. package/sdk-core/{src → core/src/workflow}/machines/child_workflow_state_machine.rs +19 -21
  66. package/sdk-core/{src → core/src/workflow}/machines/complete_workflow_state_machine.rs +3 -5
  67. package/sdk-core/{src → core/src/workflow}/machines/continue_as_new_workflow_state_machine.rs +18 -18
  68. package/sdk-core/{src → core/src/workflow}/machines/fail_workflow_state_machine.rs +5 -6
  69. package/sdk-core/core/src/workflow/machines/local_activity_state_machine.rs +1451 -0
  70. package/sdk-core/{src → core/src/workflow}/machines/mod.rs +54 -107
  71. package/sdk-core/{src → core/src/workflow}/machines/mutable_side_effect_state_machine.rs +0 -0
  72. package/sdk-core/{src → core/src/workflow}/machines/patch_state_machine.rs +29 -30
  73. package/sdk-core/{src → core/src/workflow}/machines/side_effect_state_machine.rs +0 -0
  74. package/sdk-core/{src → core/src/workflow}/machines/signal_external_state_machine.rs +17 -19
  75. package/sdk-core/{src → core/src/workflow}/machines/timer_state_machine.rs +20 -21
  76. package/sdk-core/{src → core/src/workflow}/machines/transition_coverage.rs +5 -2
  77. package/sdk-core/{src → core/src/workflow}/machines/upsert_search_attributes_state_machine.rs +0 -0
  78. package/sdk-core/core/src/workflow/machines/workflow_machines/local_acts.rs +96 -0
  79. package/sdk-core/{src → core/src/workflow}/machines/workflow_machines.rs +344 -160
  80. package/sdk-core/{src → core/src/workflow}/machines/workflow_task_state_machine.rs +1 -1
  81. package/sdk-core/{src → core/src}/workflow/mod.rs +200 -39
  82. package/sdk-core/{src → core/src}/workflow/workflow_tasks/cache_manager.rs +0 -0
  83. package/sdk-core/{src → core/src}/workflow/workflow_tasks/concurrency_manager.rs +38 -5
  84. package/sdk-core/{src → core/src}/workflow/workflow_tasks/mod.rs +297 -81
  85. package/sdk-core/{test_utils → core-api}/Cargo.toml +10 -7
  86. package/sdk-core/{src → core-api/src}/errors.rs +42 -90
  87. package/sdk-core/core-api/src/lib.rs +158 -0
  88. package/sdk-core/{src/worker/config.rs → core-api/src/worker.rs} +18 -23
  89. package/sdk-core/etc/deps.svg +156 -0
  90. package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +5 -5
  91. package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +3 -5
  92. package/sdk-core/fsm/rustfsm_trait/src/lib.rs +7 -1
  93. package/sdk-core/histories/fail_wf_task.bin +0 -0
  94. package/sdk-core/histories/timer_workflow_history.bin +0 -0
  95. package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +44 -13
  96. package/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +19 -1
  97. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/common.proto +1 -1
  98. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +9 -0
  99. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +1 -0
  100. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/reset.proto +1 -0
  101. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +13 -0
  102. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +14 -7
  103. package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +176 -18
  104. package/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +6 -0
  105. package/sdk-core/protos/api_upstream/temporal/api/query/v1/message.proto +11 -0
  106. package/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +3 -0
  107. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +156 -7
  108. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +135 -104
  109. package/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +78 -0
  110. package/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +78 -0
  111. package/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +205 -0
  112. package/sdk-core/protos/local/temporal/sdk/core/bridge/service.proto +61 -0
  113. package/sdk-core/protos/local/{child_workflow.proto → temporal/sdk/core/child_workflow/child_workflow.proto} +1 -1
  114. package/sdk-core/protos/local/{common.proto → temporal/sdk/core/common/common.proto} +5 -3
  115. package/sdk-core/protos/local/{core_interface.proto → temporal/sdk/core/core_interface.proto} +10 -10
  116. package/sdk-core/protos/local/temporal/sdk/core/external_data/external_data.proto +30 -0
  117. package/sdk-core/protos/local/{workflow_activation.proto → temporal/sdk/core/workflow_activation/workflow_activation.proto} +35 -11
  118. package/sdk-core/protos/local/{workflow_commands.proto → temporal/sdk/core/workflow_commands/workflow_commands.proto} +55 -4
  119. package/sdk-core/protos/local/{workflow_completion.proto → temporal/sdk/core/workflow_completion/workflow_completion.proto} +3 -3
  120. package/sdk-core/sdk/Cargo.toml +32 -0
  121. package/sdk-core/{src/prototype_rust_sdk → sdk/src}/conversions.rs +0 -0
  122. package/sdk-core/sdk/src/lib.rs +699 -0
  123. package/sdk-core/sdk/src/payload_converter.rs +11 -0
  124. package/sdk-core/sdk/src/workflow_context/options.rs +180 -0
  125. package/sdk-core/{src/prototype_rust_sdk → sdk/src}/workflow_context.rs +201 -124
  126. package/sdk-core/{src/prototype_rust_sdk → sdk/src}/workflow_future.rs +63 -30
  127. package/sdk-core/sdk-core-protos/Cargo.toml +10 -0
  128. package/sdk-core/sdk-core-protos/build.rs +28 -6
  129. package/sdk-core/sdk-core-protos/src/constants.rs +7 -0
  130. package/sdk-core/{src/test_help → sdk-core-protos/src}/history_builder.rs +134 -49
  131. package/sdk-core/sdk-core-protos/src/history_info.rs +216 -0
  132. package/sdk-core/sdk-core-protos/src/lib.rs +594 -168
  133. package/sdk-core/sdk-core-protos/src/task_token.rs +38 -0
  134. package/sdk-core/sdk-core-protos/src/utilities.rs +14 -0
  135. package/sdk-core/test-utils/Cargo.toml +32 -0
  136. package/sdk-core/{src/test_help → test-utils/src}/canned_histories.rs +59 -78
  137. package/sdk-core/test-utils/src/histfetch.rs +28 -0
  138. package/sdk-core/{test_utils → test-utils}/src/lib.rs +131 -68
  139. package/sdk-core/tests/integ_tests/client_tests.rs +1 -1
  140. package/sdk-core/tests/integ_tests/heartbeat_tests.rs +11 -7
  141. package/sdk-core/tests/integ_tests/polling_tests.rs +12 -11
  142. package/sdk-core/tests/integ_tests/queries_tests.rs +82 -78
  143. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +91 -71
  144. package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +3 -4
  145. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +2 -4
  146. package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +4 -6
  147. package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +4 -6
  148. package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +3 -4
  149. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +496 -0
  150. package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +5 -8
  151. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +125 -0
  152. package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +7 -13
  153. package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +33 -5
  154. package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +12 -16
  155. package/sdk-core/tests/integ_tests/workflow_tests.rs +85 -82
  156. package/sdk-core/tests/load_tests.rs +6 -6
  157. package/sdk-core/tests/main.rs +2 -2
  158. package/src/conversions.rs +24 -21
  159. package/src/errors.rs +8 -0
  160. package/src/lib.rs +323 -211
  161. package/sdk-core/protos/local/activity_result.proto +0 -46
  162. package/sdk-core/protos/local/activity_task.proto +0 -66
  163. package/sdk-core/src/core_tests/retry.rs +0 -147
  164. package/sdk-core/src/lib.rs +0 -403
  165. package/sdk-core/src/machines/local_activity_state_machine.rs +0 -117
  166. package/sdk-core/src/pending_activations.rs +0 -249
  167. package/sdk-core/src/protosext/mod.rs +0 -160
  168. package/sdk-core/src/prototype_rust_sdk.rs +0 -412
  169. package/sdk-core/src/task_token.rs +0 -20
  170. package/sdk-core/src/test_help/history_info.rs +0 -158
@@ -1,20 +1,23 @@
1
1
  [package]
2
- name = "test_utils"
2
+ name = "temporal-sdk-core-api"
3
3
  version = "0.1.0"
4
- authors = ["Spencer Judge <spencer@temporal.io>"]
5
4
  edition = "2021"
6
5
 
7
6
  # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8
7
 
9
8
  [dependencies]
9
+ anyhow = "1.0"
10
10
  async-trait = "0.1"
11
- base64 = "0.13"
12
- futures = "0.3"
11
+ derive_builder = "0.10"
13
12
  log = "0.4"
14
- rand = "0.8"
15
- temporal-sdk-core = { path = ".." }
16
- url = "2.2"
13
+ prost-types = "0.9"
14
+ thiserror = "1.0"
15
+ tonic = "0.6"
17
16
 
18
17
  [dependencies.temporal-sdk-core-protos]
19
18
  path = "../sdk-core-protos"
20
19
  version = "0.1"
20
+
21
+ [dependencies.temporal-client]
22
+ path = "../client"
23
+ version = "0.1"
@@ -1,45 +1,19 @@
1
1
  //! Error types exposed by public APIs
2
2
 
3
- use crate::{machines::WFMachinesError, WorkerLookupErr};
3
+ use prost_types::TimestampOutOfSystemRangeError;
4
+ use temporal_client::GatewayInitError;
4
5
  use temporal_sdk_core_protos::coresdk::{
5
- activity_result::ActivityResult, workflow_completion::WfActivationCompletion,
6
+ activity_result::ActivityExecutionResult,
7
+ workflow_activation::remove_from_cache::EvictionReason,
8
+ workflow_completion::WorkflowActivationCompletion,
6
9
  };
7
- use tonic::codegen::http::uri::InvalidUri;
8
-
9
- #[derive(Debug)]
10
- pub(crate) struct WorkflowUpdateError {
11
- /// Underlying workflow error
12
- pub source: WFMachinesError,
13
- /// The run id of the erring workflow
14
- #[allow(dead_code)] // Useful in debug output
15
- pub run_id: String,
16
- }
17
-
18
- impl From<WorkflowMissingError> for WorkflowUpdateError {
19
- fn from(wme: WorkflowMissingError) -> Self {
20
- Self {
21
- source: WFMachinesError::Fatal("Workflow machines missing".to_string()),
22
- run_id: wme.run_id,
23
- }
24
- }
25
- }
26
-
27
- /// The workflow machines were expected to be in the cache but were not
28
- #[derive(Debug)]
29
- pub(crate) struct WorkflowMissingError {
30
- /// The run id of the erring workflow
31
- pub run_id: String,
32
- }
33
10
 
34
11
  /// Errors thrown during initialization of [crate::Core]
35
12
  #[derive(thiserror::Error, Debug)]
36
13
  pub enum CoreInitError {
37
- /// Invalid URI. Configuration error, fatal.
38
- #[error("Invalid URI: {0:?}")]
39
- InvalidUri(#[from] InvalidUri),
40
14
  /// Server connection error. Crashing and restarting the worker is likely best.
41
15
  #[error("Server connection error: {0:?}")]
42
- TonicTransportError(#[from] tonic::transport::Error),
16
+ GatewayInitError(#[from] GatewayInitError),
43
17
  /// There was a problem initializing telemetry
44
18
  #[error("Telemetry initialization error: {0:?}")]
45
19
  TelemetryInitError(anyhow::Error),
@@ -67,15 +41,6 @@ pub enum PollWfError {
67
41
  NoWorkerForQueue(String),
68
42
  }
69
43
 
70
- impl From<WorkerLookupErr> for PollWfError {
71
- fn from(e: WorkerLookupErr) -> Self {
72
- match e {
73
- WorkerLookupErr::Shutdown(_) => Self::ShutDown,
74
- WorkerLookupErr::NoWorker(s) => Self::NoWorkerForQueue(s),
75
- }
76
- }
77
- }
78
-
79
44
  /// Errors thrown by [crate::Core::poll_activity_task]
80
45
  #[derive(thiserror::Error, Debug)]
81
46
  pub enum PollActivityError {
@@ -92,15 +57,6 @@ pub enum PollActivityError {
92
57
  NoWorkerForQueue(String),
93
58
  }
94
59
 
95
- impl From<WorkerLookupErr> for PollActivityError {
96
- fn from(e: WorkerLookupErr) -> Self {
97
- match e {
98
- WorkerLookupErr::Shutdown(_) => Self::ShutDown,
99
- WorkerLookupErr::NoWorker(s) => Self::NoWorkerForQueue(s),
100
- }
101
- }
102
- }
103
-
104
60
  /// Errors thrown by [crate::Core::complete_workflow_activation]
105
61
  #[derive(thiserror::Error, Debug)]
106
62
  #[allow(clippy::large_enum_variant)]
@@ -111,7 +67,7 @@ pub enum CompleteWfError {
111
67
  /// Reason the completion was malformed
112
68
  reason: String,
113
69
  /// The completion, which may not be included to avoid unnecessary copies.
114
- completion: Option<WfActivationCompletion>,
70
+ completion: Option<WorkflowActivationCompletion>,
115
71
  },
116
72
  /// There is no worker registered for the queue being polled
117
73
  #[error("No worker registered for queue: {0}")]
@@ -122,16 +78,6 @@ pub enum CompleteWfError {
122
78
  TonicError(#[from] tonic::Status),
123
79
  }
124
80
 
125
- impl From<WorkerLookupErr> for CompleteWfError {
126
- fn from(e: WorkerLookupErr) -> Self {
127
- match e {
128
- WorkerLookupErr::Shutdown(s) | WorkerLookupErr::NoWorker(s) => {
129
- Self::NoWorkerForQueue(s)
130
- }
131
- }
132
- }
133
- }
134
-
135
81
  /// Errors thrown by [crate::Core::complete_activity_task]
136
82
  #[derive(thiserror::Error, Debug)]
137
83
  pub enum CompleteActivityError {
@@ -141,7 +87,7 @@ pub enum CompleteActivityError {
141
87
  /// Reason the completion was malformed
142
88
  reason: String,
143
89
  /// The completion, which may not be included to avoid unnecessary copies.
144
- completion: Option<ActivityResult>,
90
+ completion: Option<ActivityExecutionResult>,
145
91
  },
146
92
  /// Unhandled error when calling the temporal server. Core will attempt to retry any non-fatal
147
93
  /// errors, so lang should consider this fatal.
@@ -152,34 +98,6 @@ pub enum CompleteActivityError {
152
98
  NoWorkerForQueue(String),
153
99
  }
154
100
 
155
- impl From<WorkerLookupErr> for CompleteActivityError {
156
- fn from(e: WorkerLookupErr) -> Self {
157
- match e {
158
- WorkerLookupErr::Shutdown(s) | WorkerLookupErr::NoWorker(s) => {
159
- Self::NoWorkerForQueue(s)
160
- }
161
- }
162
- }
163
- }
164
-
165
- /// Errors thrown by [crate::Core::record_activity_heartbeat]
166
- #[derive(thiserror::Error, Debug)]
167
- pub enum ActivityHeartbeatError {
168
- /// Heartbeat referenced an activity that we don't think exists. It may have completed already.
169
- #[error("Heartbeat has been sent for activity that either completed or never started on this worker.")]
170
- UnknownActivity,
171
- /// There was no heartbeat timeout set for the activity, but one is required to heartbeat.
172
- #[error("Heartbeat is only allowed on activities with heartbeat timeout.")]
173
- HeartbeatTimeoutNotSet,
174
- /// There was a set heartbeat timeout, but it was not parseable. A valid timeout is requried
175
- /// to heartbeat.
176
- #[error("Unable to parse activity heartbeat timeout.")]
177
- InvalidHeartbeatTimeout,
178
- /// Core is shutting down and thus new heartbeats are not accepted
179
- #[error("New heartbeat requests are not accepted while shutting down")]
180
- ShuttingDown,
181
- }
182
-
183
101
  /// Errors thrown by [crate::Core::register_worker]
184
102
  #[derive(thiserror::Error, Debug)]
185
103
  pub enum WorkerRegistrationError {
@@ -187,3 +105,37 @@ pub enum WorkerRegistrationError {
187
105
  #[error("Worker already registered for queue: {0}")]
188
106
  WorkerAlreadyRegisteredForQueue(String),
189
107
  }
108
+
109
+ /// Errors thrown inside of workflow machines
110
+ #[derive(thiserror::Error, Debug)]
111
+ pub enum WFMachinesError {
112
+ #[error("Nondeterminism error: {0}")]
113
+ Nondeterminism(String),
114
+ #[error("Fatal error in workflow machines: {0}")]
115
+ Fatal(String),
116
+
117
+ #[error("Unrecoverable network error while fetching history: {0}")]
118
+ HistoryFetchingError(tonic::Status),
119
+
120
+ /// Should always be caught internally and turned into a workflow task failure
121
+ #[error("Unable to process partial event history because workflow is no longer cached.")]
122
+ CacheMiss,
123
+ }
124
+
125
+ impl WFMachinesError {
126
+ pub fn evict_reason(&self) -> EvictionReason {
127
+ match self {
128
+ WFMachinesError::Nondeterminism(_) => EvictionReason::Nondeterminism,
129
+ WFMachinesError::Fatal(_) | WFMachinesError::HistoryFetchingError(_) => {
130
+ EvictionReason::Fatal
131
+ }
132
+ WFMachinesError::CacheMiss => EvictionReason::CacheMiss,
133
+ }
134
+ }
135
+ }
136
+
137
+ impl From<TimestampOutOfSystemRangeError> for WFMachinesError {
138
+ fn from(_: TimestampOutOfSystemRangeError) -> Self {
139
+ Self::Fatal("Could not decode timestamp".to_string())
140
+ }
141
+ }
@@ -0,0 +1,158 @@
1
+ pub mod errors;
2
+ pub mod worker;
3
+
4
+ use crate::{
5
+ errors::{
6
+ CompleteActivityError, CompleteWfError, PollActivityError, PollWfError,
7
+ WorkerRegistrationError,
8
+ },
9
+ worker::WorkerConfig,
10
+ };
11
+ use log::Level;
12
+ use std::{
13
+ sync::Arc,
14
+ time::{Duration, SystemTime, UNIX_EPOCH},
15
+ };
16
+ use temporal_client::ServerGatewayApis;
17
+ use temporal_sdk_core_protos::coresdk::{
18
+ activity_task::ActivityTask, workflow_activation::WorkflowActivation,
19
+ workflow_completion::WorkflowActivationCompletion, ActivityHeartbeat, ActivityTaskCompletion,
20
+ };
21
+
22
+ /// This trait is the primary way by which language specific SDKs interact with the core SDK. It is
23
+ /// expected that only one instance of an implementation will exist for the lifetime of the
24
+ /// worker(s) using it.
25
+ #[async_trait::async_trait]
26
+ pub trait Core: Send + Sync {
27
+ /// Register a worker with core. Workers poll on a specific task queue, and when calling core's
28
+ /// poll functions, you must provide a task queue name. If there was already a worker registered
29
+ /// with the same task queue name, it will be shut down and a new one will be created.
30
+ fn register_worker(&self, config: WorkerConfig) -> Result<(), WorkerRegistrationError>;
31
+
32
+ /// Ask the core for some work, returning a [WorkflowActivation]. It is then the language SDK's
33
+ /// responsibility to call the appropriate workflow code with the provided inputs. Blocks
34
+ /// indefinitely until such work is available or [Core::shutdown] is called.
35
+ ///
36
+ /// The returned activation is guaranteed to be for the same task queue / worker which was
37
+ /// provided as the `task_queue` argument.
38
+ ///
39
+ /// It is important to understand that all activations must be responded to. There can only
40
+ /// be one outstanding activation for a particular run of a workflow at any time. If an
41
+ /// activation is not responded to, it will cause that workflow to become stuck forever.
42
+ ///
43
+ /// Activations that contain only a `remove_from_cache` job should not cause the workflow code
44
+ /// to be invoked and may be responded to with an empty command list. Eviction jobs may also
45
+ /// appear with other jobs, but will always appear last in the job list. In this case it is
46
+ /// expected that the workflow code will be invoked, and the response produced as normal, but
47
+ /// the caller should evict the run after doing so.
48
+ ///
49
+ /// It is rarely a good idea to call poll concurrently. It handles polling the server
50
+ /// concurrently internally.
51
+ ///
52
+ /// TODO: Examples
53
+ async fn poll_workflow_activation(
54
+ &self,
55
+ task_queue: &str,
56
+ ) -> Result<WorkflowActivation, PollWfError>;
57
+
58
+ /// Ask the core for some work, returning an [ActivityTask]. It is then the language SDK's
59
+ /// responsibility to call the appropriate activity code with the provided inputs. Blocks
60
+ /// indefinitely until such work is available or [Core::shutdown] is called.
61
+ ///
62
+ /// The returned activation is guaranteed to be for the same task queue / worker which was
63
+ /// provided as the `task_queue` argument.
64
+ ///
65
+ /// It is rarely a good idea to call poll concurrently. It handles polling the server
66
+ /// concurrently internally.
67
+ ///
68
+ /// TODO: Examples
69
+ async fn poll_activity_task(&self, task_queue: &str)
70
+ -> Result<ActivityTask, PollActivityError>;
71
+
72
+ /// Tell the core that a workflow activation has completed. May be freely called concurrently.
73
+ async fn complete_workflow_activation(
74
+ &self,
75
+ completion: WorkflowActivationCompletion,
76
+ ) -> Result<(), CompleteWfError>;
77
+
78
+ /// Tell the core that an activity has finished executing. May be freely called concurrently.
79
+ async fn complete_activity_task(
80
+ &self,
81
+ completion: ActivityTaskCompletion,
82
+ ) -> Result<(), CompleteActivityError>;
83
+
84
+ /// Notify workflow that an activity is still alive. Long running activities that take longer
85
+ /// than `activity_heartbeat_timeout` to finish must call this function in order to report
86
+ /// progress, otherwise the activity will timeout and a new attempt will be scheduled.
87
+ ///
88
+ /// The first heartbeat request will be sent immediately, subsequent rapid calls to this
89
+ /// function will result in heartbeat requests being aggregated and the last one received during
90
+ /// the aggregation period will be sent to the server, where that period is defined as half the
91
+ /// heartbeat timeout.
92
+ ///
93
+ /// Unlike java/go SDKs we do not return cancellation status as part of heartbeat response and
94
+ /// instead send it as a separate activity task to the lang, decoupling heartbeat and
95
+ /// cancellation processing.
96
+ ///
97
+ /// For now activity still need to send heartbeats if they want to receive cancellation
98
+ /// requests. In the future we will change this and will dispatch cancellations more
99
+ /// proactively. Note that this function does not block on the server call and returns
100
+ /// immediately. Underlying validation errors are swallowed and logged, this has been agreed to
101
+ /// be optimal behavior for the user as we don't want to break activity execution due to badly
102
+ /// configured heartbeat options.
103
+ fn record_activity_heartbeat(&self, details: ActivityHeartbeat);
104
+
105
+ /// Request that a workflow be evicted by its run id. This will generate a workflow activation
106
+ /// with the eviction job inside it to be eventually returned by
107
+ /// [Core::poll_workflow_activation]. If the workflow had any existing outstanding activations,
108
+ /// such activations are invalidated and subsequent completions of them will do nothing and log
109
+ /// a warning.
110
+ fn request_workflow_eviction(&self, task_queue: &str, run_id: &str);
111
+
112
+ /// Returns core's instance of the [ServerGatewayApis] implementor it is using.
113
+ fn server_gateway(&self) -> Arc<dyn ServerGatewayApis + Send + Sync>;
114
+
115
+ /// Initiates async shutdown procedure, eventually ceases all polling of the server and shuts
116
+ /// down all registered workers. [Core::poll_workflow_activation] should be called until it
117
+ /// returns [PollWfError::ShutDown] to ensure that any workflows which are still undergoing
118
+ /// replay have an opportunity to finish. This means that the lang sdk will need to call
119
+ /// [Core::complete_workflow_activation] for those workflows until they are done. At that point,
120
+ /// the lang SDK can end the process, or drop the [Core] instance, which will close the
121
+ /// connection.
122
+ async fn shutdown(&self);
123
+
124
+ /// Shut down a specific worker. Will cease all polling on the task queue and future attempts
125
+ /// to poll that queue will return [PollWfError::NoWorkerForQueue].
126
+ async fn shutdown_worker(&self, task_queue: &str);
127
+
128
+ /// Core buffers logs that should be shuttled over to lang so that they may be rendered with
129
+ /// the user's desired logging library. Use this function to grab the most recent buffered logs
130
+ /// since the last time it was called. A fixed number of such logs are retained at maximum, with
131
+ /// the oldest being dropped when full.
132
+ ///
133
+ /// Returns the list of logs from oldest to newest. Returns an empty vec if the feature is not
134
+ /// configured.
135
+ fn fetch_buffered_logs(&self) -> Vec<CoreLog>;
136
+ }
137
+
138
+ /// A log line (which ultimately came from a tracing event) exported from Core->Lang
139
+ #[derive(Debug)]
140
+ pub struct CoreLog {
141
+ /// Log message
142
+ pub message: String,
143
+ /// Time log was generated (not when it was exported to lang)
144
+ pub timestamp: SystemTime,
145
+ /// Message level
146
+ pub level: Level,
147
+ // KV pairs aren't meaningfully exposed yet to the log interface by tracing
148
+ }
149
+
150
+ impl CoreLog {
151
+ /// Return timestamp as ms since epoch
152
+ pub fn millis_since_epoch(&self) -> u128 {
153
+ self.timestamp
154
+ .duration_since(UNIX_EPOCH)
155
+ .unwrap_or(Duration::ZERO)
156
+ .as_millis()
157
+ }
158
+ }
@@ -1,11 +1,9 @@
1
1
  use std::time::Duration;
2
2
 
3
- #[cfg(test)]
4
- use crate::test_help::TEST_Q;
5
-
6
3
  /// Defines per-worker configuration options
7
4
  #[derive(Debug, Clone, derive_builder::Builder)]
8
5
  #[builder(setter(into), build_fn(validate = "Self::validate"))]
6
+ #[non_exhaustive]
9
7
  // TODO: per-second queue limits
10
8
  pub struct WorkerConfig {
11
9
  /// What task queue will this worker poll from? This task queue name will be used for both
@@ -23,10 +21,13 @@ pub struct WorkerConfig {
23
21
  /// "outstanding" until all activations it requires have been completed.
24
22
  #[builder(default = "100")]
25
23
  pub max_outstanding_workflow_tasks: usize,
26
- /// The maximum allowed number of activity tasks that will ever be given to this worker at one
27
- /// time.
24
+ /// The maximum number of activity tasks that will ever be given to this worker concurrently
28
25
  #[builder(default = "100")]
29
26
  pub max_outstanding_activities: usize,
27
+ /// The maximum number of local activity tasks that will ever be given to this worker
28
+ /// concurrently
29
+ #[builder(default = "100")]
30
+ pub max_outstanding_local_activities: usize,
30
31
  /// Maximum number of concurrent poll workflow task requests we will perform at a time on this
31
32
  /// worker's task queue. See also [WorkerConfig::nonsticky_to_sticky_poll_ratio]. Must be at
32
33
  /// least 1.
@@ -64,6 +65,18 @@ pub struct WorkerConfig {
64
65
  pub default_heartbeat_throttle_interval: Duration,
65
66
  }
66
67
 
68
+ impl WorkerConfig {
69
+ pub fn max_nonsticky_polls(&self) -> usize {
70
+ ((self.max_concurrent_wft_polls as f32 * self.nonsticky_to_sticky_poll_ratio) as usize)
71
+ .max(1)
72
+ }
73
+ pub fn max_sticky_polls(&self) -> usize {
74
+ self.max_concurrent_wft_polls
75
+ .saturating_sub(self.max_nonsticky_polls())
76
+ .max(1)
77
+ }
78
+ }
79
+
67
80
  impl WorkerConfigBuilder {
68
81
  fn validate(&self) -> Result<(), String> {
69
82
  if self.max_concurrent_wft_polls == Some(0) {
@@ -72,21 +85,3 @@ impl WorkerConfigBuilder {
72
85
  Ok(())
73
86
  }
74
87
  }
75
-
76
- impl WorkerConfig {
77
- #[cfg(test)]
78
- pub fn default_test_q() -> Self {
79
- WorkerConfigBuilder::default()
80
- .task_queue(TEST_Q)
81
- .build()
82
- .unwrap()
83
- }
84
-
85
- #[cfg(test)]
86
- pub fn default(queue: &str) -> Self {
87
- WorkerConfigBuilder::default()
88
- .task_queue(queue)
89
- .build()
90
- .unwrap()
91
- }
92
- }
@@ -0,0 +1,156 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
3
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4
+ <!-- Generated by graphviz version 2.50.0 (0)
5
+ -->
6
+ <!-- Pages: 1 -->
7
+ <svg width="421pt" height="404pt"
8
+ viewBox="0.00 0.00 420.50 404.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
9
+ <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 400)">
10
+ <polygon fill="white" stroke="transparent" points="-4,4 -4,-400 416.5,-400 416.5,4 -4,4"/>
11
+ <!-- 0 -->
12
+ <g id="node1" class="node">
13
+ <title>0</title>
14
+ <polygon fill="none" stroke="black" points="248,-396 132,-396 132,-360 248,-360 248,-396"/>
15
+ <text text-anchor="middle" x="190" y="-374.3" font-family="Times,serif" font-size="14.00">temporal&#45;sdk&#45;core</text>
16
+ </g>
17
+ <!-- 1 -->
18
+ <g id="node2" class="node">
19
+ <title>1</title>
20
+ <polygon fill="none" stroke="black" points="58,-324 0,-324 0,-288 58,-288 58,-324"/>
21
+ <text text-anchor="middle" x="29" y="-302.3" font-family="Times,serif" font-size="14.00">rustfsm</text>
22
+ </g>
23
+ <!-- 0&#45;&gt;1 -->
24
+ <g id="edge1" class="edge">
25
+ <title>0&#45;&gt;1</title>
26
+ <path fill="none" stroke="black" d="M150.61,-359.88C125.27,-348.86 92.5,-334.61 67.36,-323.68"/>
27
+ <polygon fill="black" stroke="black" points="68.7,-320.44 58.13,-319.67 65.91,-326.86 68.7,-320.44"/>
28
+ </g>
29
+ <!-- 4 -->
30
+ <g id="node3" class="node">
31
+ <title>4</title>
32
+ <polygon fill="none" stroke="black" points="214,-108 114,-108 114,-72 214,-72 214,-108"/>
33
+ <text text-anchor="middle" x="164" y="-86.3" font-family="Times,serif" font-size="14.00">temporal&#45;client</text>
34
+ </g>
35
+ <!-- 0&#45;&gt;4 -->
36
+ <g id="edge2" class="edge">
37
+ <title>0&#45;&gt;4</title>
38
+ <path fill="none" stroke="black" d="M181.7,-359.96C171.44,-325.92 157.74,-247.02 153,-180 151.87,-164.04 152.7,-160 153,-144 153.16,-135.58 153.46,-126.42 154.19,-118.12"/>
39
+ <polygon fill="black" stroke="black" points="157.67,-118.52 155.37,-108.18 150.71,-117.7 157.67,-118.52"/>
40
+ </g>
41
+ <!-- 0&#45;&gt;4 -->
42
+ <g id="edge3" class="edge">
43
+ <title>0&#45;&gt;4</title>
44
+ <path fill="none" stroke="blue" d="M191.8,-359.96C189.44,-325.92 175.74,-247.02 171,-180 169.87,-164.04 170.7,-160 171,-144 171.16,-135.68 171.45,-126.63 171.37,-118.4"/>
45
+ <polygon fill="blue" stroke="blue" points="174.86,-118.05 171.01,-108.18 167.87,-118.3 174.86,-118.05"/>
46
+ </g>
47
+ <!-- 5 -->
48
+ <g id="node4" class="node">
49
+ <title>5</title>
50
+ <polygon fill="none" stroke="black" points="319.5,-36 164.5,-36 164.5,0 319.5,0 319.5,-36"/>
51
+ <text text-anchor="middle" x="242" y="-14.3" font-family="Times,serif" font-size="14.00">temporal&#45;sdk&#45;core&#45;protos</text>
52
+ </g>
53
+ <!-- 0&#45;&gt;5 -->
54
+ <g id="edge6" class="edge">
55
+ <title>0&#45;&gt;5</title>
56
+ <path fill="none" stroke="black" d="M165.88,-359.82C135.16,-335.73 86,-288.78 86,-235 86,-235 86,-235 86,-161 86,-120.55 78.76,-102.78 105,-72 118.09,-56.64 136.18,-45.72 154.93,-37.95"/>
57
+ <polygon fill="black" stroke="black" points="156.39,-41.14 164.46,-34.27 153.87,-34.6 156.39,-41.14"/>
58
+ </g>
59
+ <!-- 6 -->
60
+ <g id="node5" class="node">
61
+ <title>6</title>
62
+ <polygon fill="none" stroke="black" points="307.5,-180 170.5,-180 170.5,-144 307.5,-144 307.5,-180"/>
63
+ <text text-anchor="middle" x="239" y="-158.3" font-family="Times,serif" font-size="14.00">temporal&#45;sdk&#45;core&#45;api</text>
64
+ </g>
65
+ <!-- 0&#45;&gt;6 -->
66
+ <g id="edge5" class="edge">
67
+ <title>0&#45;&gt;6</title>
68
+ <path fill="none" stroke="black" d="M193.8,-359.93C197.8,-342.01 204.29,-313.01 210,-288 217.68,-254.36 226.68,-215.68 232.6,-190.36"/>
69
+ <polygon fill="black" stroke="black" points="236.06,-190.92 234.93,-180.38 229.24,-189.32 236.06,-190.92"/>
70
+ </g>
71
+ <!-- 7 -->
72
+ <g id="node6" class="node">
73
+ <title>7</title>
74
+ <polygon fill="none" stroke="black" points="412.5,-252 323.5,-252 323.5,-216 412.5,-216 412.5,-252"/>
75
+ <text text-anchor="middle" x="368" y="-230.3" font-family="Times,serif" font-size="14.00">temporal&#45;sdk</text>
76
+ </g>
77
+ <!-- 0&#45;&gt;7 -->
78
+ <g id="edge4" class="edge">
79
+ <title>0&#45;&gt;7</title>
80
+ <path fill="none" stroke="blue" d="M224.19,-359.83C242.9,-350.78 265.76,-338.54 284,-324 307.09,-305.6 328.26,-279.21 343.85,-259.94"/>
81
+ <polygon fill="blue" stroke="blue" points="346.58,-262.13 350.18,-252.17 341.15,-257.71 346.58,-262.13"/>
82
+ </g>
83
+ <!-- 8 -->
84
+ <g id="node7" class="node">
85
+ <title>8</title>
86
+ <polygon fill="none" stroke="black" points="283.5,-324 218.5,-324 218.5,-288 283.5,-288 283.5,-324"/>
87
+ <text text-anchor="middle" x="251" y="-302.3" font-family="Times,serif" font-size="14.00">test_utils</text>
88
+ </g>
89
+ <!-- 0&#45;&gt;8 -->
90
+ <g id="edge7" class="edge">
91
+ <title>0&#45;&gt;8</title>
92
+ <path fill="none" stroke="blue" d="M199.16,-359.7C205.68,-351.22 214.51,-340.86 223.1,-331.58"/>
93
+ <polygon fill="blue" stroke="blue" points="225.85,-333.77 230.2,-324.1 220.78,-328.95 225.85,-333.77"/>
94
+ </g>
95
+ <!-- 4&#45;&gt;5 -->
96
+ <g id="edge8" class="edge">
97
+ <title>4&#45;&gt;5</title>
98
+ <path fill="none" stroke="black" d="M183.28,-71.7C192.92,-63.05 204.73,-52.45 215.23,-43.03"/>
99
+ <polygon fill="black" stroke="black" points="217.84,-45.39 222.94,-36.1 213.16,-40.18 217.84,-45.39"/>
100
+ </g>
101
+ <!-- 6&#45;&gt;4 -->
102
+ <g id="edge9" class="edge">
103
+ <title>6&#45;&gt;4</title>
104
+ <path fill="none" stroke="black" d="M220.46,-143.7C211.2,-135.05 199.84,-124.45 189.74,-115.03"/>
105
+ <polygon fill="black" stroke="black" points="192.02,-112.37 182.33,-108.1 187.25,-117.49 192.02,-112.37"/>
106
+ </g>
107
+ <!-- 6&#45;&gt;5 -->
108
+ <g id="edge10" class="edge">
109
+ <title>6&#45;&gt;5</title>
110
+ <path fill="none" stroke="black" d="M239.36,-143.87C239.87,-119.67 240.81,-75.21 241.42,-46.39"/>
111
+ <polygon fill="black" stroke="black" points="244.92,-46.26 241.64,-36.19 237.93,-46.11 244.92,-46.26"/>
112
+ </g>
113
+ <!-- 7&#45;&gt;0 -->
114
+ <g id="edge11" class="edge">
115
+ <title>7&#45;&gt;0</title>
116
+ <path fill="none" stroke="black" d="M363.18,-252.17C352.26,-271.5 328.39,-302.97 302,-324 286.4,-336.43 267.42,-347.19 249.5,-355.7"/>
117
+ <polygon fill="black" stroke="black" points="247.88,-352.6 240.25,-359.95 250.8,-358.96 247.88,-352.6"/>
118
+ </g>
119
+ <!-- 7&#45;&gt;5 -->
120
+ <g id="edge13" class="edge">
121
+ <title>7&#45;&gt;5</title>
122
+ <path fill="none" stroke="black" d="M371.05,-215.88C375.69,-184.29 380.99,-116.06 350,-72 340.45,-58.42 326.41,-48.16 311.6,-40.47"/>
123
+ <polygon fill="black" stroke="black" points="312.84,-37.19 302.31,-36.01 309.81,-43.5 312.84,-37.19"/>
124
+ </g>
125
+ <!-- 7&#45;&gt;6 -->
126
+ <g id="edge12" class="edge">
127
+ <title>7&#45;&gt;6</title>
128
+ <path fill="none" stroke="black" d="M336.44,-215.88C319.34,-206.6 298.02,-195.03 279.68,-185.08"/>
129
+ <polygon fill="black" stroke="black" points="281.14,-181.88 270.68,-180.19 277.8,-188.04 281.14,-181.88"/>
130
+ </g>
131
+ <!-- 8&#45;&gt;0 -->
132
+ <g id="edge15" class="edge">
133
+ <title>8&#45;&gt;0</title>
134
+ <path fill="none" stroke="black" d="M241.99,-324.1C235.51,-332.55 226.69,-342.9 218.1,-352.2"/>
135
+ <polygon fill="black" stroke="black" points="215.33,-350.03 210.99,-359.7 220.41,-354.85 215.33,-350.03"/>
136
+ </g>
137
+ <!-- 8&#45;&gt;5 -->
138
+ <g id="edge17" class="edge">
139
+ <title>8&#45;&gt;5</title>
140
+ <path fill="none" stroke="black" d="M266.47,-287.62C290.36,-258.6 332,-198.15 317,-144 306.53,-106.2 281.25,-68.36 262.93,-44.38"/>
141
+ <polygon fill="black" stroke="black" points="265.45,-41.92 256.54,-36.2 259.94,-46.23 265.45,-41.92"/>
142
+ </g>
143
+ <!-- 8&#45;&gt;6 -->
144
+ <g id="edge16" class="edge">
145
+ <title>8&#45;&gt;6</title>
146
+ <path fill="none" stroke="black" d="M249.55,-287.87C247.51,-263.67 243.75,-219.21 241.31,-190.39"/>
147
+ <polygon fill="black" stroke="black" points="244.78,-189.86 240.45,-180.19 237.81,-190.45 244.78,-189.86"/>
148
+ </g>
149
+ <!-- 8&#45;&gt;7 -->
150
+ <g id="edge14" class="edge">
151
+ <title>8&#45;&gt;7</title>
152
+ <path fill="none" stroke="black" d="M279.62,-287.88C294.92,-278.72 313.94,-267.34 330.42,-257.48"/>
153
+ <polygon fill="black" stroke="black" points="332.48,-260.33 339.27,-252.19 328.89,-254.32 332.48,-260.33"/>
154
+ </g>
155
+ </g>
156
+ </svg>
@@ -126,19 +126,19 @@ use syn::{
126
126
  /// either case the function is expected to return a `TransitionResult` to the appropriate state.
127
127
  ///
128
128
  /// The first transition can be interpreted as "If the machine is in the locked state, when a
129
- /// `CardReadable` event is seen, call `on_card_readable` (pasing in `CardData`) and transition to
129
+ /// `CardReadable` event is seen, call `on_card_readable` (passing in `CardData`) and transition to
130
130
  /// the `ReadingCard` state.
131
131
  ///
132
132
  /// The macro will generate a few things:
133
133
  /// * A struct for the overall state machine, named with the provided name. Here:
134
- /// ```ignore
134
+ /// ```text
135
135
  /// struct CardMachine {
136
136
  /// state: CardMachineState,
137
137
  /// shared_state: CardId,
138
138
  /// }
139
139
  /// ```
140
140
  /// * An enum with a variant for each state, named with the provided name + "State".
141
- /// ```ignore
141
+ /// ```text
142
142
  /// enum CardMachineState {
143
143
  /// Locked(Locked),
144
144
  /// ReadingCard(ReadingCard),
@@ -153,7 +153,7 @@ use syn::{
153
153
  /// generated. This enum must be used as the destination "state" from those handlers.
154
154
  /// * An enum with a variant for each event. You are expected to define the type (if any) contained
155
155
  /// in the event variant.
156
- /// ```ignore
156
+ /// ```text
157
157
  /// enum CardMachineEvents {
158
158
  /// CardReadable(CardData)
159
159
  /// }
@@ -565,7 +565,7 @@ impl StateMachineDefinition {
565
565
  &self.shared_state
566
566
  }
567
567
 
568
- fn on_final_state(&self) -> bool {
568
+ fn has_reached_final_state(&self) -> bool {
569
569
  self.state.is_final()
570
570
  }
571
571
 
@@ -5,10 +5,8 @@ error[E0277]: the trait bound `One: From<Two>` is not satisfied
5
5
  | ^^^ the trait `From<Two>` is not implemented for `One`
6
6
  |
7
7
  = note: required because of the requirements on the impl of `Into<One>` for `Two`
8
- note: required by `TransitionResult::<Sm, Ds>::from`
8
+ note: required by a bound in `TransitionResult::<Sm, Ds>::from`
9
9
  --> $WORKSPACE/fsm/rustfsm_trait/src/lib.rs
10
10
  |
11
- | / pub fn from<CurrentState>(current_state: CurrentState) -> Self
12
- | | where
13
- | | CurrentState: Into<Ds>,
14
- | |_______________________________^
11
+ | CurrentState: Into<Ds>,
12
+ | ^^^^^^^^ required by this bound in `TransitionResult::<Sm, Ds>::from`