@temporalio/core-bridge 1.5.2 → 1.6.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 (153) hide show
  1. package/Cargo.lock +255 -48
  2. package/package.json +4 -4
  3. package/releases/aarch64-apple-darwin/index.node +0 -0
  4. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  5. package/releases/x86_64-apple-darwin/index.node +0 -0
  6. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  7. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  8. package/sdk-core/.buildkite/pipeline.yml +1 -3
  9. package/sdk-core/.cargo/config.toml +5 -2
  10. package/sdk-core/.github/workflows/heavy.yml +28 -0
  11. package/sdk-core/Cargo.toml +1 -1
  12. package/sdk-core/README.md +9 -5
  13. package/sdk-core/client/src/lib.rs +211 -36
  14. package/sdk-core/client/src/raw.rs +1 -1
  15. package/sdk-core/client/src/retry.rs +32 -20
  16. package/sdk-core/core/Cargo.toml +23 -9
  17. package/sdk-core/core/src/abstractions.rs +11 -0
  18. package/sdk-core/core/src/core_tests/activity_tasks.rs +6 -5
  19. package/sdk-core/core/src/core_tests/local_activities.rs +263 -22
  20. package/sdk-core/core/src/core_tests/queries.rs +2 -2
  21. package/sdk-core/core/src/core_tests/workflow_tasks.rs +249 -5
  22. package/sdk-core/core/src/ephemeral_server/mod.rs +5 -6
  23. package/sdk-core/core/src/lib.rs +2 -0
  24. package/sdk-core/core/src/protosext/mod.rs +1 -1
  25. package/sdk-core/core/src/telemetry/log_export.rs +1 -1
  26. package/sdk-core/core/src/telemetry/mod.rs +23 -8
  27. package/sdk-core/core/src/test_help/mod.rs +8 -1
  28. package/sdk-core/core/src/worker/activities/local_activities.rs +259 -125
  29. package/sdk-core/core/src/worker/activities.rs +3 -2
  30. package/sdk-core/core/src/worker/mod.rs +53 -26
  31. package/sdk-core/core/src/worker/workflow/bridge.rs +1 -3
  32. package/sdk-core/core/src/worker/workflow/driven_workflow.rs +3 -5
  33. package/sdk-core/core/src/worker/workflow/history_update.rs +835 -277
  34. package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +9 -17
  35. package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +3 -5
  36. package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +1 -2
  37. package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +3 -5
  38. package/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +1 -2
  39. package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +1 -2
  40. package/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +1 -2
  41. package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +73 -51
  42. package/sdk-core/core/src/worker/workflow/machines/mod.rs +3 -3
  43. package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +4 -4
  44. package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +1 -2
  45. package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +3 -5
  46. package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +6 -7
  47. package/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +2 -2
  48. package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +4 -4
  49. package/sdk-core/core/src/worker/workflow/machines/workflow_machines/local_acts.rs +6 -17
  50. package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +89 -58
  51. package/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +4 -7
  52. package/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +21 -9
  53. package/sdk-core/core/src/worker/workflow/managed_run.rs +1021 -360
  54. package/sdk-core/core/src/worker/workflow/mod.rs +306 -346
  55. package/sdk-core/core/src/worker/workflow/run_cache.rs +29 -53
  56. package/sdk-core/core/src/worker/workflow/wft_extraction.rs +125 -0
  57. package/sdk-core/core/src/worker/workflow/wft_poller.rs +1 -4
  58. package/sdk-core/core/src/worker/workflow/workflow_stream/saved_wf_inputs.rs +115 -0
  59. package/sdk-core/core/src/worker/workflow/workflow_stream/tonic_status_serde.rs +24 -0
  60. package/sdk-core/core/src/worker/workflow/workflow_stream.rs +444 -714
  61. package/sdk-core/core-api/Cargo.toml +2 -0
  62. package/sdk-core/core-api/src/errors.rs +1 -34
  63. package/sdk-core/core-api/src/lib.rs +6 -2
  64. package/sdk-core/core-api/src/worker.rs +14 -1
  65. package/sdk-core/etc/deps.svg +115 -140
  66. package/sdk-core/etc/regen-depgraph.sh +5 -0
  67. package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +6 -6
  68. package/sdk-core/fsm/rustfsm_trait/src/lib.rs +7 -3
  69. package/sdk-core/histories/evict_while_la_running_no_interference-16_history.bin +0 -0
  70. package/sdk-core/protos/api_upstream/Makefile +5 -5
  71. package/sdk-core/protos/api_upstream/build/go.mod +7 -0
  72. package/sdk-core/protos/api_upstream/build/go.sum +5 -0
  73. package/sdk-core/protos/api_upstream/build/tools.go +29 -0
  74. package/sdk-core/protos/api_upstream/go.mod +6 -0
  75. package/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +9 -2
  76. package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +12 -19
  77. package/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +2 -2
  78. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +3 -2
  79. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +3 -2
  80. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/common.proto +3 -2
  81. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +3 -3
  82. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +20 -2
  83. package/sdk-core/protos/api_upstream/temporal/api/{update/v1/message.proto → enums/v1/interaction_type.proto} +11 -18
  84. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +2 -2
  85. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/query.proto +2 -2
  86. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/reset.proto +2 -2
  87. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/schedule.proto +2 -2
  88. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +2 -2
  89. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +2 -13
  90. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +2 -2
  91. package/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +2 -2
  92. package/sdk-core/protos/api_upstream/temporal/api/failure/v1/message.proto +2 -2
  93. package/sdk-core/protos/api_upstream/temporal/api/filter/v1/message.proto +2 -2
  94. package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +13 -19
  95. package/sdk-core/protos/api_upstream/temporal/api/interaction/v1/message.proto +87 -0
  96. package/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +2 -2
  97. package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +2 -2
  98. package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +2 -2
  99. package/sdk-core/protos/api_upstream/temporal/api/query/v1/message.proto +2 -2
  100. package/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +2 -2
  101. package/sdk-core/protos/api_upstream/temporal/api/schedule/v1/message.proto +2 -2
  102. package/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +2 -2
  103. package/sdk-core/protos/api_upstream/temporal/api/version/v1/message.proto +2 -2
  104. package/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +2 -2
  105. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +13 -8
  106. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +2 -2
  107. package/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +2 -0
  108. package/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +2 -2
  109. package/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +2 -2
  110. package/sdk-core/sdk/Cargo.toml +4 -3
  111. package/sdk-core/sdk/src/lib.rs +87 -21
  112. package/sdk-core/sdk/src/workflow_future.rs +7 -12
  113. package/sdk-core/sdk-core-protos/Cargo.toml +5 -2
  114. package/sdk-core/sdk-core-protos/build.rs +36 -2
  115. package/sdk-core/sdk-core-protos/src/history_builder.rs +26 -19
  116. package/sdk-core/sdk-core-protos/src/history_info.rs +4 -0
  117. package/sdk-core/sdk-core-protos/src/lib.rs +78 -34
  118. package/sdk-core/sdk-core-protos/src/task_token.rs +12 -2
  119. package/sdk-core/test-utils/Cargo.toml +3 -1
  120. package/sdk-core/test-utils/src/histfetch.rs +1 -1
  121. package/sdk-core/test-utils/src/lib.rs +50 -18
  122. package/sdk-core/test-utils/src/wf_input_saver.rs +50 -0
  123. package/sdk-core/test-utils/src/workflows.rs +29 -0
  124. package/sdk-core/tests/fuzzy_workflow.rs +130 -0
  125. package/sdk-core/tests/{load_tests.rs → heavy_tests.rs} +114 -7
  126. package/sdk-core/tests/integ_tests/heartbeat_tests.rs +5 -2
  127. package/sdk-core/tests/integ_tests/metrics_tests.rs +1 -1
  128. package/sdk-core/tests/integ_tests/polling_tests.rs +1 -39
  129. package/sdk-core/tests/integ_tests/queries_tests.rs +2 -127
  130. package/sdk-core/tests/integ_tests/visibility_tests.rs +52 -5
  131. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +74 -1
  132. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +5 -13
  133. package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +1 -1
  134. package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +2 -10
  135. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +69 -197
  136. package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +4 -28
  137. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +12 -7
  138. package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +14 -14
  139. package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +3 -19
  140. package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +3 -19
  141. package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +1 -1
  142. package/sdk-core/tests/integ_tests/workflow_tests.rs +5 -6
  143. package/sdk-core/tests/main.rs +2 -12
  144. package/sdk-core/tests/runner.rs +71 -34
  145. package/sdk-core/tests/wf_input_replay.rs +32 -0
  146. package/sdk-core/bridge-ffi/Cargo.toml +0 -24
  147. package/sdk-core/bridge-ffi/LICENSE.txt +0 -23
  148. package/sdk-core/bridge-ffi/build.rs +0 -25
  149. package/sdk-core/bridge-ffi/include/sdk-core-bridge.h +0 -224
  150. package/sdk-core/bridge-ffi/src/lib.rs +0 -746
  151. package/sdk-core/bridge-ffi/src/wrappers.rs +0 -221
  152. package/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +0 -210
  153. package/sdk-core/sdk/src/conversions.rs +0 -8
@@ -1,746 +0,0 @@
1
- #![allow(
2
- // Non-camel-case types needed since this is exported as a C header and we
3
- // want C-like underscores in our type names
4
- non_camel_case_types,
5
-
6
- // We choose to have narrow "unsafe" blocks instead of marking entire
7
- // functions as unsafe. Even the example in clippy's docs at
8
- // https://rust-lang.github.io/rust-clippy/master/index.html#not_unsafe_ptr_arg_deref
9
- // cause a rustc warning for unnecessary inner-unsafe when marked on fn.
10
- // This check only applies to "pub" functions which are all exposed via C
11
- // API.
12
- clippy::not_unsafe_ptr_arg_deref,
13
- )]
14
-
15
- mod wrappers;
16
-
17
- use bridge::{init_response, CreateWorkerRequest, InitResponse};
18
- use prost::Message;
19
- use std::sync::Arc;
20
- use temporal_sdk_core::{Client, ClientOptions, CoreRuntime, RetryClient};
21
- use temporal_sdk_core_api::{telemetry::TelemetryOptions, Worker};
22
- use temporal_sdk_core_protos::coresdk::{bridge, bridge::CreateClientRequest};
23
-
24
- /// A set of bytes owned by Core. No fields within nor any bytes references must
25
- /// ever be mutated outside of Core. This must always be passed to
26
- /// tmprl_bytes_free when no longer in use.
27
- #[repr(C)]
28
- pub struct tmprl_bytes_t {
29
- bytes: *const u8,
30
- len: libc::size_t,
31
- /// For internal use only.
32
- cap: libc::size_t,
33
- /// For internal use only.
34
- disable_free: bool,
35
- }
36
-
37
- impl tmprl_bytes_t {
38
- fn from_vec(vec: Vec<u8>) -> tmprl_bytes_t {
39
- // Mimics Vec::into_raw_parts that's only available in nightly
40
- let mut vec = std::mem::ManuallyDrop::new(vec);
41
- tmprl_bytes_t {
42
- bytes: vec.as_mut_ptr(),
43
- len: vec.len(),
44
- cap: vec.capacity(),
45
- disable_free: false,
46
- }
47
- }
48
-
49
- fn from_vec_disable_free(vec: Vec<u8>) -> tmprl_bytes_t {
50
- let mut b = tmprl_bytes_t::from_vec(vec);
51
- b.disable_free = true;
52
- b
53
- }
54
-
55
- fn into_raw(self) -> *mut tmprl_bytes_t {
56
- Box::into_raw(Box::new(self))
57
- }
58
- }
59
-
60
- /// Required because these instances are used by lazy_static and raw pointers
61
- /// are not usually safe for send/sync.
62
- unsafe impl Send for tmprl_bytes_t {}
63
- unsafe impl Sync for tmprl_bytes_t {}
64
-
65
- impl Drop for tmprl_bytes_t {
66
- fn drop(&mut self) {
67
- // In cases where freeing is disabled (or technically some other
68
- // drop-but-not-freed situation though we don't expect any), the bytes
69
- // remain non-null so we re-own them here
70
- if !self.bytes.is_null() {
71
- unsafe { Vec::from_raw_parts(self.bytes as *mut u8, self.len, self.cap) };
72
- }
73
- }
74
- }
75
-
76
- /// Free a set of bytes. The first parameter can be null in cases where a [tmprl_worker_t] instance
77
- /// isn't available. If the second parameter is null, this is a no-op.
78
- #[no_mangle]
79
- pub extern "C" fn tmprl_bytes_free(worker: *mut tmprl_worker_t, bytes: *const tmprl_bytes_t) {
80
- // Bail if freeing is disabled
81
- unsafe {
82
- if bytes.is_null() || (*bytes).disable_free {
83
- return;
84
- }
85
- }
86
- let bytes = bytes as *mut tmprl_bytes_t;
87
- // Return vec back to core before dropping bytes
88
- let vec = unsafe { Vec::from_raw_parts((*bytes).bytes as *mut u8, (*bytes).len, (*bytes).cap) };
89
- // Set to null so the byte dropper doesn't try to free it
90
- unsafe { (*bytes).bytes = std::ptr::null_mut() };
91
- // Return only if worker is non-null
92
- if !worker.is_null() {
93
- let worker = unsafe { &mut *worker };
94
- worker.return_buf(vec);
95
- }
96
- unsafe {
97
- let _ = Box::from_raw(bytes);
98
- }
99
- }
100
-
101
- /// Used for maintaining pointer to user data across threads. See
102
- /// https://doc.rust-lang.org/nomicon/send-and-sync.html.
103
- struct UserDataHandle(*mut libc::c_void);
104
- unsafe impl Send for UserDataHandle {}
105
- unsafe impl Sync for UserDataHandle {}
106
-
107
- impl From<UserDataHandle> for *mut libc::c_void {
108
- fn from(v: UserDataHandle) -> Self {
109
- v.0
110
- }
111
- }
112
-
113
- lazy_static::lazy_static! {
114
- static ref DEFAULT_INIT_RESPONSE_BYTES: tmprl_bytes_t = {
115
- tmprl_bytes_t::from_vec_disable_free(bridge::InitResponse::default().encode_to_vec())
116
- };
117
-
118
- static ref DEFAULT_REGISTER_WORKER_RESPONSE_BYTES: tmprl_bytes_t = {
119
- tmprl_bytes_t::from_vec_disable_free(bridge::RegisterWorkerResponse::default().encode_to_vec())
120
- };
121
-
122
- static ref DEFAULT_SHUTDOWN_WORKER_RESPONSE_BYTES: tmprl_bytes_t = {
123
- tmprl_bytes_t::from_vec_disable_free(bridge::ShutdownWorkerResponse::default().encode_to_vec())
124
- };
125
-
126
- static ref DEFAULT_COMPLETE_WORKFLOW_ACTIVATION_RESPONSE_BYTES: tmprl_bytes_t = {
127
- tmprl_bytes_t::from_vec_disable_free(bridge::CompleteWorkflowActivationResponse::default().encode_to_vec())
128
- };
129
-
130
- static ref DEFAULT_COMPLETE_ACTIVITY_TASK_RESPONSE_BYTES: tmprl_bytes_t = {
131
- tmprl_bytes_t::from_vec_disable_free(bridge::CompleteActivityTaskResponse::default().encode_to_vec())
132
- };
133
-
134
- static ref DEFAULT_RECORD_ACTIVITY_HEARTBEAT_RESPONSE_BYTES: tmprl_bytes_t = {
135
- tmprl_bytes_t::from_vec_disable_free(bridge::RecordActivityHeartbeatResponse::default().encode_to_vec())
136
- };
137
-
138
- static ref DEFAULT_REQUEST_WORKFLOW_EVICTION_RESPONSE_BYTES: tmprl_bytes_t = {
139
- tmprl_bytes_t::from_vec_disable_free(bridge::RequestWorkflowEvictionResponse::default().encode_to_vec())
140
- };
141
- }
142
-
143
- /// A runtime owned by Core. This must be passed to [tmprl_runtime_free] when no longer in use. This
144
- /// should not be freed until every call to every [tmprl_worker_t] instance created with this
145
- /// runtime has been shutdown. In practice, since the actual runtime is behind an [Arc], it's
146
- /// currently OK, but that's an implementation detail.
147
- pub struct tmprl_runtime_t {
148
- // This is the same runtime shared with worker instances
149
- core_runtime: Arc<CoreRuntime>,
150
- }
151
-
152
- /// Create a new runtime. The result is never null and must be freed via
153
- /// tmprl_runtime_free when no longer in use.
154
- #[no_mangle]
155
- pub extern "C" fn tmprl_runtime_new() -> *mut tmprl_runtime_t {
156
- Box::into_raw(Box::new(tmprl_runtime_t {
157
- // TODO(cretz): Options to configure thread pool?
158
- core_runtime: Arc::new(
159
- CoreRuntime::new(
160
- TelemetryOptions::default(),
161
- tokio::runtime::Builder::new_multi_thread(),
162
- )
163
- .expect("Core runtime must initialize"),
164
- ),
165
- }))
166
- }
167
-
168
- /// Free a previously created runtime.
169
- #[no_mangle]
170
- pub extern "C" fn tmprl_runtime_free(runtime: *mut tmprl_runtime_t) {
171
- if !runtime.is_null() {
172
- unsafe {
173
- let _ = Box::from_raw(runtime);
174
- }
175
- }
176
- }
177
-
178
- /// A worker instance owned by Core. This must be passed to [tmprl_worker_shutdown]
179
- /// when no longer in use which will free the resources.
180
- pub struct tmprl_worker_t {
181
- core_runtime: Arc<CoreRuntime>,
182
- // We are not concerned with the overhead of dynamic dispatch at this time
183
- worker: Arc<dyn Worker>,
184
- }
185
-
186
- /// Callback called by [tmprl_worker_init] on completion. The first parameter of the
187
- /// callback is user data passed into the original function. The second
188
- /// parameter is a worker instance if the call is successful or null if not. If
189
- /// present, the worker instance must be freed via [tmprl_worker_shutdown] when no
190
- /// longer in use. The third parameter of the callback is a byte array for a
191
- /// [InitResponse] protobuf message which must be freed via [tmprl_bytes_free].
192
- type tmprl_worker_init_callback = unsafe extern "C" fn(
193
- user_data: *mut libc::c_void,
194
- worker: *mut tmprl_worker_t,
195
- resp: *const tmprl_bytes_t,
196
- );
197
-
198
- /// Callback called on function completion. The first parameter of the callback
199
- /// is user data passed into the original function. The second parameter of the
200
- /// callback is a never-null byte array for a response protobuf message which
201
- /// must be freed via [tmprl_bytes_free].
202
- type tmprl_callback =
203
- unsafe extern "C" fn(user_data: *mut libc::c_void, core: *const tmprl_bytes_t);
204
-
205
- /// Create a new worker instance.
206
- ///
207
- /// `runtime` and `client` are both required and must outlive this instance.
208
- /// `req_proto` and `req_proto_len` represent a byte array for a [CreateWorkerRequest] protobuf
209
- /// message.
210
- /// The callback is invoked on completion.
211
- #[no_mangle]
212
- pub extern "C" fn tmprl_worker_init(
213
- runtime: *mut tmprl_runtime_t,
214
- client: *mut tmprl_client_t,
215
- req_proto: *const u8,
216
- req_proto_len: libc::size_t,
217
- user_data: *mut libc::c_void,
218
- callback: tmprl_worker_init_callback,
219
- ) {
220
- let (runtime, client) = unsafe { (&*runtime, &*client) };
221
- let req = match tmprl_worker_t::decode_proto::<CreateWorkerRequest>(req_proto, req_proto_len) {
222
- Ok(req) => req,
223
- Err(message) => {
224
- let resp = InitResponse {
225
- error: Some(init_response::Error { message }),
226
- };
227
- unsafe {
228
- callback(
229
- user_data,
230
- std::ptr::null_mut(),
231
- tmprl_bytes_t::from_vec(resp.encode_to_vec()).into_raw(),
232
- );
233
- }
234
- return;
235
- }
236
- };
237
- let user_data = UserDataHandle(user_data);
238
- match tmprl_worker_t::new(
239
- runtime.core_runtime.clone(),
240
- client.client.clone(),
241
- wrappers::WorkerConfig(req),
242
- ) {
243
- Ok(worker) => unsafe {
244
- callback(
245
- user_data.into(),
246
- Box::into_raw(Box::new(worker)),
247
- &*DEFAULT_INIT_RESPONSE_BYTES,
248
- );
249
- },
250
- Err(message) => {
251
- let resp = InitResponse {
252
- error: Some(init_response::Error { message }),
253
- };
254
- unsafe {
255
- callback(
256
- user_data.into(),
257
- std::ptr::null_mut(),
258
- tmprl_bytes_t::from_vec(resp.encode_to_vec()).into_raw(),
259
- );
260
- }
261
- }
262
- };
263
- }
264
-
265
- /// Shutdown and free a previously created worker.
266
- ///
267
- /// The req_proto and req_proto_len represent a byte array for a [bridge::ShutdownWorkerRequest]
268
- /// protobuf message, which currently contains nothing and are unused, but the parameters are kept
269
- /// for now.
270
- ///
271
- /// The callback is invoked on completion with a ShutdownWorkerResponse protobuf message.
272
- ///
273
- /// After the callback has been called, the worker struct will be freed and the pointer will no
274
- /// longer be valid.
275
- #[no_mangle]
276
- pub extern "C" fn tmprl_worker_shutdown(
277
- worker: *mut tmprl_worker_t,
278
- #[allow(unused_variables)] // We intentionally ignore the request
279
- req_proto: *const u8,
280
- #[allow(unused_variables)] req_proto_len: libc::size_t,
281
- user_data: *mut libc::c_void,
282
- callback: tmprl_callback,
283
- ) {
284
- let worker = unsafe { Box::from_raw(worker) };
285
- let user_data = UserDataHandle(user_data);
286
- worker.core_runtime.tokio_handle().spawn(async move {
287
- worker.shutdown().await;
288
- unsafe {
289
- callback(user_data.into(), &*DEFAULT_SHUTDOWN_WORKER_RESPONSE_BYTES);
290
- }
291
- drop(worker);
292
- });
293
- }
294
-
295
- /// A client instance owned by Core. This must be passed to [tmprl_client_free]
296
- /// when no longer in use which will free the resources.
297
- pub struct tmprl_client_t {
298
- client: Arc<RetryClient<Client>>,
299
- }
300
-
301
- impl tmprl_client_t {
302
- pub fn new(client: Arc<RetryClient<Client>>) -> Self {
303
- Self { client }
304
- }
305
- }
306
-
307
- /// Callback called by [tmprl_client_init] on completion. The first parameter of the
308
- /// callback is user data passed into the original function. The second
309
- /// parameter is a client instance if the call is successful or null if not. If
310
- /// present, the client instance must be freed via [tmprl_client_free] when no
311
- /// longer in use. The third parameter of the callback is a byte array for a
312
- /// [InitResponse] protobuf message which must be freed via [tmprl_bytes_free].
313
- type tmprl_client_init_callback = unsafe extern "C" fn(
314
- user_data: *mut libc::c_void,
315
- client: *mut tmprl_client_t,
316
- resp: *const tmprl_bytes_t,
317
- );
318
-
319
- /// Initialize a client connection to the Temporal service.
320
- ///
321
- /// The runtime is required and must outlive this instance. The `req_proto` and `req_proto_len`
322
- /// represent a byte array for a [CreateClientRequest] protobuf message. The callback is invoked on
323
- /// completion.
324
- #[no_mangle]
325
- pub extern "C" fn tmprl_client_init(
326
- runtime: *mut tmprl_runtime_t,
327
- req_proto: *const u8,
328
- req_proto_len: libc::size_t,
329
- user_data: *mut libc::c_void,
330
- callback: tmprl_client_init_callback,
331
- ) {
332
- let runtime = unsafe { &*runtime };
333
- let (namespace, req) =
334
- match tmprl_worker_t::decode_proto::<CreateClientRequest>(req_proto, req_proto_len)
335
- .and_then(|cgr| {
336
- let ns = cgr.namespace.clone();
337
- wrappers::ClientOptions(cgr)
338
- .try_into()
339
- .map(|sgo: ClientOptions| (ns, sgo))
340
- }) {
341
- Ok(req) => req,
342
- Err(message) => {
343
- let resp = InitResponse {
344
- error: Some(init_response::Error { message }),
345
- };
346
- unsafe {
347
- callback(
348
- user_data,
349
- std::ptr::null_mut(),
350
- tmprl_bytes_t::from_vec(resp.encode_to_vec()).into_raw(),
351
- );
352
- }
353
- return;
354
- }
355
- };
356
-
357
- let user_data = UserDataHandle(user_data);
358
- runtime.core_runtime.tokio_handle().spawn(async move {
359
- match req.connect(namespace, None, None).await {
360
- Ok(client) => unsafe {
361
- callback(
362
- user_data.into(),
363
- Box::into_raw(Box::new(tmprl_client_t::new(Arc::new(client)))),
364
- &*DEFAULT_INIT_RESPONSE_BYTES,
365
- );
366
- },
367
- Err(e) => {
368
- let resp = InitResponse {
369
- error: Some(init_response::Error {
370
- message: e.to_string(),
371
- }),
372
- };
373
- unsafe {
374
- callback(
375
- user_data.into(),
376
- std::ptr::null_mut(),
377
- tmprl_bytes_t::from_vec(resp.encode_to_vec()).into_raw(),
378
- );
379
- }
380
- }
381
- }
382
- });
383
- }
384
-
385
- /// Free a previously created client
386
- #[no_mangle]
387
- pub extern "C" fn tmprl_client_free(client: *mut tmprl_client_t) {
388
- unsafe { drop(Box::from_raw(client)) };
389
- }
390
-
391
- /// Poll for a workflow activation.
392
- ///
393
- /// The `req_proto` and `req_proto_len` represent a byte array for a
394
- /// [bridge::PollWorkflowActivationRequest] protobuf message, which currently contains nothing and
395
- /// is unused, but the parameters are kept for now.
396
- ///
397
- /// The callback is invoked on completion with a [bridge::PollWorkflowActivationResponse] protobuf
398
- /// message.
399
- #[no_mangle]
400
- pub extern "C" fn tmprl_poll_workflow_activation(
401
- worker: *mut tmprl_worker_t,
402
- #[allow(unused_variables)] // We intentionally ignore the request
403
- req_proto: *const u8,
404
- #[allow(unused_variables)] // We intentionally ignore the request
405
- req_proto_len: libc::size_t,
406
- user_data: *mut libc::c_void,
407
- callback: tmprl_callback,
408
- ) {
409
- let worker = unsafe { &mut *worker };
410
- let user_data = UserDataHandle(user_data);
411
- worker.core_runtime.tokio_handle().spawn(async move {
412
- let resp = bridge::PollWorkflowActivationResponse {
413
- response: Some(match worker.poll_workflow_activation().await {
414
- Ok(act) => bridge::poll_workflow_activation_response::Response::Activation(act),
415
- Err(err) => bridge::poll_workflow_activation_response::Response::Error(err),
416
- }),
417
- };
418
- unsafe { callback(user_data.into(), worker.encode_proto(&resp).into_raw()) };
419
- });
420
- }
421
-
422
- /// Poll for an activity task.
423
- ///
424
- /// The `req_proto` and `req_proto_len` represent a byte array for a
425
- /// [bridge::PollActivityTaskRequest] protobuf message, which currently contains nothing and is
426
- /// unused, but the parameters are kept for now.
427
- ///
428
- /// The callback is invoked on completion with a [bridge::PollActivityTaskResponse] protobuf
429
- /// message.
430
- #[no_mangle]
431
- pub extern "C" fn tmprl_poll_activity_task(
432
- worker: *mut tmprl_worker_t,
433
- #[allow(unused_variables)] // We intentionally ignore the request
434
- req_proto: *const u8,
435
- #[allow(unused_variables)] // We intentionally ignore the request
436
- req_proto_len: libc::size_t,
437
- user_data: *mut libc::c_void,
438
- callback: tmprl_callback,
439
- ) {
440
- let worker = unsafe { &mut *worker };
441
- let user_data = UserDataHandle(user_data);
442
- worker.core_runtime.tokio_handle().spawn(async move {
443
- let resp = bridge::PollActivityTaskResponse {
444
- response: Some(match worker.poll_activity_task().await {
445
- Ok(task) => bridge::poll_activity_task_response::Response::Task(task),
446
- Err(err) => bridge::poll_activity_task_response::Response::Error(err),
447
- }),
448
- };
449
- unsafe { callback(user_data.into(), worker.encode_proto(&resp).into_raw()) };
450
- });
451
- }
452
-
453
- /// Complete a workflow activation.
454
- ///
455
- /// The `req_proto` and `req_proto_len` represent a byte array for a
456
- /// [bridge::CompleteWorkflowActivationRequest] protobuf message. The callback is invoked on
457
- /// completion with a [bridge::CompleteWorkflowActivationResponse] protobuf message.
458
- #[no_mangle]
459
- pub extern "C" fn tmprl_complete_workflow_activation(
460
- worker: *mut tmprl_worker_t,
461
- req_proto: *const u8,
462
- req_proto_len: libc::size_t,
463
- user_data: *mut libc::c_void,
464
- callback: tmprl_callback,
465
- ) {
466
- let worker = unsafe { &mut *worker };
467
- let req = match tmprl_worker_t::decode_proto::<bridge::CompleteWorkflowActivationRequest>(
468
- req_proto,
469
- req_proto_len,
470
- ) {
471
- Ok(req) => req,
472
- Err(message) => {
473
- let resp = bridge::CompleteWorkflowActivationResponse {
474
- error: Some(bridge::complete_workflow_activation_response::Error { message }),
475
- };
476
- unsafe {
477
- callback(user_data, worker.encode_proto(&resp).into_raw());
478
- }
479
- return;
480
- }
481
- };
482
- let user_data = UserDataHandle(user_data);
483
- worker.core_runtime.tokio_handle().spawn(async move {
484
- match worker.complete_workflow_activation(req).await {
485
- Ok(()) => unsafe {
486
- callback(
487
- user_data.into(),
488
- &*DEFAULT_COMPLETE_WORKFLOW_ACTIVATION_RESPONSE_BYTES,
489
- );
490
- },
491
- Err(err) => {
492
- let resp = bridge::CompleteWorkflowActivationResponse { error: Some(err) };
493
- unsafe { callback(user_data.into(), worker.encode_proto(&resp).into_raw()) };
494
- }
495
- }
496
- });
497
- }
498
-
499
- /// Complete an activity task.
500
- ///
501
- /// The `req_proto` and `req_proto_len` represent a byte array for a
502
- /// [bridge::CompleteActivityTaskRequest] protobuf message. The callback is invoked on completion
503
- /// with a [bridge::CompleteActivityTaskResponse] protobuf message.
504
- #[no_mangle]
505
- pub extern "C" fn tmprl_complete_activity_task(
506
- worker: *mut tmprl_worker_t,
507
- req_proto: *const u8,
508
- req_proto_len: libc::size_t,
509
- user_data: *mut libc::c_void,
510
- callback: tmprl_callback,
511
- ) {
512
- let worker = unsafe { &mut *worker };
513
- let req = match tmprl_worker_t::decode_proto::<bridge::CompleteActivityTaskRequest>(
514
- req_proto,
515
- req_proto_len,
516
- ) {
517
- Ok(req) => req,
518
- Err(message) => {
519
- let resp = bridge::CompleteActivityTaskResponse {
520
- error: Some(bridge::complete_activity_task_response::Error { message }),
521
- };
522
- unsafe {
523
- callback(user_data, worker.encode_proto(&resp).into_raw());
524
- }
525
- return;
526
- }
527
- };
528
- let user_data = UserDataHandle(user_data);
529
- worker.core_runtime.tokio_handle().spawn(async move {
530
- match worker.complete_activity_task(req).await {
531
- Ok(()) => unsafe {
532
- callback(
533
- user_data.into(),
534
- &*DEFAULT_COMPLETE_ACTIVITY_TASK_RESPONSE_BYTES,
535
- );
536
- },
537
- Err(err) => {
538
- let resp = bridge::CompleteActivityTaskResponse { error: Some(err) };
539
- unsafe { callback(user_data.into(), worker.encode_proto(&resp).into_raw()) };
540
- }
541
- }
542
- });
543
- }
544
-
545
- /// Record an activity heartbeat.
546
- ///
547
- /// `req_proto` and `req_proto_len` represent a byte array for a
548
- /// [bridge::RecordActivityHeartbeatRequest] protobuf message. The callback is invoked on completion
549
- /// with a RecordActivityHeartbeatResponse protobuf message.
550
- #[no_mangle]
551
- pub extern "C" fn tmprl_record_activity_heartbeat(
552
- worker: *mut tmprl_worker_t,
553
- req_proto: *const u8,
554
- req_proto_len: libc::size_t,
555
- user_data: *mut libc::c_void,
556
- callback: tmprl_callback,
557
- ) {
558
- let worker = unsafe { &mut *worker };
559
- let req = match tmprl_worker_t::decode_proto::<bridge::RecordActivityHeartbeatRequest>(
560
- req_proto,
561
- req_proto_len,
562
- ) {
563
- Ok(req) => req,
564
- Err(message) => {
565
- let resp = bridge::RecordActivityHeartbeatResponse {
566
- error: Some(bridge::record_activity_heartbeat_response::Error { message }),
567
- };
568
- unsafe {
569
- callback(user_data, worker.encode_proto(&resp).into_raw());
570
- }
571
- return;
572
- }
573
- };
574
- let user_data = UserDataHandle(user_data);
575
- // We intentionally spawn even though the core call is not async so the
576
- // callback can be made in the tokio runtime
577
- worker.core_runtime.tokio_handle().spawn(async move {
578
- worker.record_activity_heartbeat(req);
579
- unsafe {
580
- callback(
581
- user_data.into(),
582
- &*DEFAULT_RECORD_ACTIVITY_HEARTBEAT_RESPONSE_BYTES,
583
- );
584
- }
585
- });
586
- }
587
-
588
- /// Request a workflow eviction.
589
- ///
590
- /// The `req_proto` and `req_proto_len` represent a byte array for a
591
- /// [bridge::RequestWorkflowEvictionRequest] protobuf message. The callback is invoked on completion
592
- /// with a [bridge::RequestWorkflowEvictionResponse] protobuf message.
593
- #[no_mangle]
594
- pub extern "C" fn tmprl_request_workflow_eviction(
595
- worker: *mut tmprl_worker_t,
596
- req_proto: *const u8,
597
- req_proto_len: libc::size_t,
598
- user_data: *mut libc::c_void,
599
- callback: tmprl_callback,
600
- ) {
601
- let worker = unsafe { &mut *worker };
602
- let req = match tmprl_worker_t::decode_proto::<bridge::RequestWorkflowEvictionRequest>(
603
- req_proto,
604
- req_proto_len,
605
- ) {
606
- Ok(req) => req,
607
- Err(message) => {
608
- let resp = bridge::RequestWorkflowEvictionResponse {
609
- error: Some(bridge::request_workflow_eviction_response::Error { message }),
610
- };
611
- unsafe {
612
- callback(user_data, worker.encode_proto(&resp).into_raw());
613
- }
614
- return;
615
- }
616
- };
617
- let user_data = UserDataHandle(user_data);
618
- // We intentionally spawn even though the core call is not async so the
619
- // callback can be made in the tokio runtime
620
- worker.core_runtime.tokio_handle().spawn(async move {
621
- worker.request_workflow_eviction(req);
622
- unsafe {
623
- callback(
624
- user_data.into(),
625
- &*DEFAULT_REQUEST_WORKFLOW_EVICTION_RESPONSE_BYTES,
626
- );
627
- }
628
- });
629
- }
630
-
631
- impl tmprl_worker_t {
632
- fn new(
633
- core_runtime: Arc<CoreRuntime>,
634
- client: Arc<RetryClient<Client>>,
635
- opts: wrappers::WorkerConfig,
636
- ) -> Result<tmprl_worker_t, String> {
637
- let worker = Arc::new(
638
- temporal_sdk_core::init_worker(&core_runtime, opts.try_into()?, client)
639
- .map_err(|e| e.to_string())?,
640
- );
641
- Ok(tmprl_worker_t {
642
- core_runtime,
643
- worker,
644
- })
645
- }
646
-
647
- async fn shutdown(&self) {
648
- self.worker.shutdown().await;
649
- }
650
-
651
- async fn poll_workflow_activation(
652
- &self,
653
- ) -> Result<
654
- temporal_sdk_core_protos::coresdk::workflow_activation::WorkflowActivation,
655
- bridge::poll_workflow_activation_response::Error,
656
- > {
657
- self.worker.poll_workflow_activation().await.map_err(|err| {
658
- bridge::poll_workflow_activation_response::Error {
659
- message: format!("{}", err),
660
- shutdown: matches!(err, temporal_sdk_core_api::errors::PollWfError::ShutDown),
661
- }
662
- })
663
- }
664
-
665
- async fn poll_activity_task(
666
- &self,
667
- ) -> Result<
668
- temporal_sdk_core_protos::coresdk::activity_task::ActivityTask,
669
- bridge::poll_activity_task_response::Error,
670
- > {
671
- self.worker.poll_activity_task().await.map_err(|err| {
672
- bridge::poll_activity_task_response::Error {
673
- message: format!("{}", err),
674
- shutdown: matches!(
675
- err,
676
- temporal_sdk_core_api::errors::PollActivityError::ShutDown
677
- ),
678
- }
679
- })
680
- }
681
-
682
- async fn complete_workflow_activation(
683
- &self,
684
- req: bridge::CompleteWorkflowActivationRequest,
685
- ) -> Result<(), bridge::complete_workflow_activation_response::Error> {
686
- self.worker
687
- .complete_workflow_activation(req.completion.unwrap_or_default())
688
- .await
689
- .map_err(|err| bridge::complete_workflow_activation_response::Error {
690
- message: format!("{}", err),
691
- })
692
- }
693
-
694
- async fn complete_activity_task(
695
- &self,
696
- req: bridge::CompleteActivityTaskRequest,
697
- ) -> Result<(), bridge::complete_activity_task_response::Error> {
698
- self.worker
699
- .complete_activity_task(req.completion.unwrap_or_default())
700
- .await
701
- .map_err(|err| bridge::complete_activity_task_response::Error {
702
- message: format!("{}", err),
703
- })
704
- }
705
-
706
- fn record_activity_heartbeat(&self, req: bridge::RecordActivityHeartbeatRequest) {
707
- self.worker
708
- .record_activity_heartbeat(req.heartbeat.unwrap_or_default());
709
- }
710
-
711
- fn request_workflow_eviction(&self, req: bridge::RequestWorkflowEvictionRequest) {
712
- self.worker.request_workflow_eviction(&req.run_id);
713
- }
714
-
715
- // TODO: Fetch logs
716
-
717
- fn borrow_buf(&mut self) -> Vec<u8> {
718
- // We currently do not use a thread-safe byte pool, but if wanted, it
719
- // can be added here
720
- Vec::new()
721
- }
722
-
723
- fn return_buf(&mut self, _vec: Vec<u8>) {
724
- // We currently do not use a thread-safe byte pool, but if wanted, it
725
- // can be added here
726
- }
727
-
728
- fn encode_proto(&mut self, proto: &impl prost::Message) -> tmprl_bytes_t {
729
- let mut buf = self.borrow_buf();
730
- buf.clear();
731
- // Increase buf capacity if needed
732
- buf.reserve(proto.encoded_len());
733
- // Only fails if size not big enough which can't happen in our case
734
- proto.encode(&mut buf).unwrap();
735
- tmprl_bytes_t::from_vec(buf)
736
- }
737
-
738
- fn decode_proto<P>(bytes: *const u8, bytes_len: libc::size_t) -> Result<P, String>
739
- where
740
- P: prost::Message,
741
- P: Default,
742
- {
743
- P::decode(unsafe { std::slice::from_raw_parts(bytes, bytes_len) })
744
- .map_err(|err| format!("failed decoding proto: {}", err))
745
- }
746
- }