@temporalio/core-bridge 1.12.2 → 1.12.3

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 (57) hide show
  1. package/package.json +3 -3
  2. package/releases/aarch64-apple-darwin/index.node +0 -0
  3. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  4. package/releases/x86_64-apple-darwin/index.node +0 -0
  5. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  6. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  7. package/sdk-core/.cargo/config.toml +1 -1
  8. package/sdk-core/client/src/callback_based.rs +123 -0
  9. package/sdk-core/client/src/lib.rs +96 -28
  10. package/sdk-core/client/src/metrics.rs +33 -5
  11. package/sdk-core/client/src/raw.rs +40 -1
  12. package/sdk-core/client/src/retry.rs +12 -3
  13. package/sdk-core/core/src/lib.rs +4 -2
  14. package/sdk-core/core/src/pollers/poll_buffer.rs +62 -14
  15. package/sdk-core/core/src/worker/client.rs +9 -5
  16. package/sdk-core/core/src/worker/heartbeat.rs +3 -1
  17. package/sdk-core/core-api/src/worker.rs +2 -2
  18. package/sdk-core/core-c-bridge/Cargo.toml +2 -0
  19. package/sdk-core/core-c-bridge/include/temporal-sdk-core-c-bridge.h +105 -0
  20. package/sdk-core/core-c-bridge/src/client.rs +265 -8
  21. package/sdk-core/core-c-bridge/src/tests/context.rs +11 -0
  22. package/sdk-core/core-c-bridge/src/tests/mod.rs +179 -3
  23. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/CODEOWNERS +1 -1
  24. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/README.md +1 -1
  25. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/VERSION +1 -1
  26. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/buf.yaml +1 -0
  27. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/request_response.proto +83 -0
  28. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/service.proto +37 -0
  29. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/connectivityrule/v1/message.proto +64 -0
  30. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/identity/v1/message.proto +3 -1
  31. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/namespace/v1/message.proto +10 -0
  32. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/operation/v1/message.proto +1 -0
  33. package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv2.json +644 -9
  34. package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv3.yaml +635 -21
  35. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/batch/v1/message.proto +60 -2
  36. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/common/v1/message.proto +84 -15
  37. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +3 -0
  38. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +11 -0
  39. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/history/v1/message.proto +5 -0
  40. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +1 -1
  41. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/sdk/v1/worker_config.proto +36 -0
  42. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +29 -0
  43. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/worker/v1/message.proto +11 -1
  44. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +122 -4
  45. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +41 -0
  46. package/sdk-core/sdk-core-protos/src/lib.rs +5 -1
  47. package/sdk-core/test-utils/Cargo.toml +1 -0
  48. package/sdk-core/test-utils/src/lib.rs +90 -3
  49. package/sdk-core/tests/cloud_tests.rs +11 -74
  50. package/sdk-core/tests/integ_tests/client_tests.rs +14 -10
  51. package/sdk-core/tests/integ_tests/worker_tests.rs +8 -2
  52. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +13 -0
  53. package/sdk-core/tests/integ_tests/workflow_tests/priority.rs +2 -108
  54. package/sdk-core/tests/main.rs +3 -0
  55. package/sdk-core/tests/shared_tests/mod.rs +43 -0
  56. package/sdk-core/tests/shared_tests/priority.rs +155 -0
  57. package/src/client.rs +5 -0
@@ -24,6 +24,7 @@ use std::{
24
24
  future::Future,
25
25
  net::SocketAddr,
26
26
  path::PathBuf,
27
+ str::FromStr,
27
28
  sync::Arc,
28
29
  time::{Duration, Instant},
29
30
  };
@@ -69,8 +70,9 @@ use temporal_sdk_core_protos::{
69
70
  workflow_completion::WorkflowActivationCompletion,
70
71
  },
71
72
  temporal::api::{
72
- common::v1::Payload, history::v1::History,
73
- workflowservice::v1::StartWorkflowExecutionResponse,
73
+ common::v1::Payload,
74
+ history::v1::History,
75
+ workflowservice::v1::{GetClusterInfoRequest, StartWorkflowExecutionResponse},
74
76
  },
75
77
  };
76
78
  use tokio::{sync::OnceCell, task::AbortHandle};
@@ -95,6 +97,7 @@ pub const OTEL_URL_ENV_VAR: &str = "TEMPORAL_INTEG_OTEL_URL";
95
97
  pub const PROM_ENABLE_ENV_VAR: &str = "TEMPORAL_INTEG_PROM_PORT";
96
98
  /// This should match the prometheus port exposed in docker-compose-ci.yaml
97
99
  pub const PROMETHEUS_QUERY_API: &str = "http://localhost:9090/api/v1/query";
100
+
98
101
  #[macro_export]
99
102
  macro_rules! prost_dur {
100
103
  ($dur_call:ident $args:tt) => {
@@ -192,6 +195,37 @@ pub fn init_integ_telem() -> Option<&'static CoreRuntime> {
192
195
  }))
193
196
  }
194
197
 
198
+ pub async fn get_cloud_client() -> RetryClient<Client> {
199
+ let cloud_addr = env::var("TEMPORAL_CLOUD_ADDRESS").unwrap();
200
+ let cloud_key = env::var("TEMPORAL_CLIENT_KEY").unwrap();
201
+
202
+ let client_cert = env::var("TEMPORAL_CLIENT_CERT")
203
+ .expect("TEMPORAL_CLIENT_CERT must be set")
204
+ .replace("\\n", "\n")
205
+ .into_bytes();
206
+ let client_private_key = cloud_key.replace("\\n", "\n").into_bytes();
207
+ let sgo = ClientOptionsBuilder::default()
208
+ .target_url(Url::from_str(&cloud_addr).unwrap())
209
+ .client_name("sdk-core-integ-tests")
210
+ .client_version("clientver")
211
+ .identity("sdk-test-client")
212
+ .tls_cfg(TlsConfig {
213
+ client_tls_config: Some(ClientTlsConfig {
214
+ client_cert,
215
+ client_private_key,
216
+ }),
217
+ ..Default::default()
218
+ })
219
+ .build()
220
+ .unwrap();
221
+ sgo.connect(
222
+ env::var("TEMPORAL_NAMESPACE").expect("TEMPORAL_NAMESPACE must be set"),
223
+ None,
224
+ )
225
+ .await
226
+ .unwrap()
227
+ }
228
+
195
229
  /// Implements a builder pattern to help integ tests initialize core and create workflows
196
230
  pub struct CoreWfStarter {
197
231
  /// Used for both the task queue and workflow id
@@ -202,6 +236,7 @@ pub struct CoreWfStarter {
202
236
  initted_worker: OnceCell<InitializedWorker>,
203
237
  runtime_override: Option<Arc<CoreRuntime>>,
204
238
  client_override: Option<Arc<RetryClient<Client>>>,
239
+ min_local_server_version: Option<String>,
205
240
  }
206
241
  struct InitializedWorker {
207
242
  worker: Arc<dyn CoreWorker>,
@@ -223,6 +258,51 @@ impl CoreWfStarter {
223
258
  Self::_new(test_name, None, Some(client))
224
259
  }
225
260
 
261
+ /// Targets cloud if the required env vars are present. Otherwise, local server (but only if
262
+ /// the minimum version requirement is met). Returns None if the local server is not new enough.
263
+ ///
264
+ /// An empty string means to skip the version check.
265
+ pub async fn new_cloud_or_local(test_name: &str, version_req: &str) -> Option<Self> {
266
+ init_integ_telem();
267
+ let mut check_mlsv = false;
268
+ let client = if env::var("TEMPORAL_CLOUD_ADDRESS").is_ok() {
269
+ Some(get_cloud_client().await)
270
+ } else {
271
+ check_mlsv = true;
272
+ None
273
+ };
274
+ let mut s = Self::_new(test_name, None, client);
275
+
276
+ if check_mlsv && !version_req.is_empty() {
277
+ let clustinfo = (*s.get_client().await)
278
+ .get_client()
279
+ .inner()
280
+ .workflow_svc()
281
+ .clone()
282
+ .get_cluster_info(GetClusterInfoRequest::default())
283
+ .await;
284
+ let srv_ver = semver::Version::parse(
285
+ &clustinfo
286
+ .expect("must be able to get cluster info")
287
+ .into_inner()
288
+ .server_version,
289
+ )
290
+ .expect("must be able to parse server version");
291
+ let req = semver::VersionReq::parse(version_req)
292
+ .expect("must be able to parse server version requirement");
293
+
294
+ if !req.matches(&srv_ver) {
295
+ warn!(
296
+ "Server version {} does not meet requirement {} for test {}",
297
+ srv_ver, req, test_name
298
+ );
299
+ return None;
300
+ }
301
+ }
302
+
303
+ Some(s)
304
+ }
305
+
226
306
  fn _new(
227
307
  test_name: &str,
228
308
  runtime_override: Option<CoreRuntime>,
@@ -241,6 +321,7 @@ impl CoreWfStarter {
241
321
  workflow_options: Default::default(),
242
322
  runtime_override: runtime_override.map(Arc::new),
243
323
  client_override: client_override.map(Arc::new),
324
+ min_local_server_version: None,
244
325
  }
245
326
  }
246
327
 
@@ -253,6 +334,7 @@ impl CoreWfStarter {
253
334
  workflow_options: self.workflow_options.clone(),
254
335
  runtime_override: self.runtime_override.clone(),
255
336
  client_override: self.client_override.clone(),
337
+ min_local_server_version: self.min_local_server_version.clone(),
256
338
  initted_worker: Default::default(),
257
339
  }
258
340
  }
@@ -475,11 +557,16 @@ impl TestWorker {
475
557
  workflow_id: impl Into<String>,
476
558
  workflow_type: impl Into<String>,
477
559
  input: Vec<Payload>,
478
- options: WorkflowOptions,
560
+ mut options: WorkflowOptions,
479
561
  ) -> Result<String, anyhow::Error> {
480
562
  if self.client.is_none() {
481
563
  return Ok("fake_run_id".to_string());
482
564
  }
565
+ // Fallback overall execution timeout to avoid leaving open workflows when testing against
566
+ // cloud
567
+ if options.execution_timeout.is_none() {
568
+ options.execution_timeout = Some(Duration::from_secs(60 * 5));
569
+ }
483
570
  self.get_submitter_handle()
484
571
  .submit_wf(workflow_id, workflow_type, input, options)
485
572
  .await
@@ -1,53 +1,11 @@
1
- use std::{
2
- env,
3
- str::FromStr,
4
- sync::atomic::{AtomicBool, Ordering::Relaxed},
5
- };
6
- use temporal_client::{
7
- Client, ClientOptionsBuilder, ClientTlsConfig, RetryClient, TlsConfig, WorkflowClientTrait,
8
- };
9
- use temporal_sdk::WfContext;
10
- use temporal_sdk_core_protos::temporal::api::{
11
- enums::v1::{EventType, WorkflowTaskFailedCause::GrpcMessageTooLarge},
12
- history::v1::history_event::Attributes::WorkflowTaskFailedEventAttributes,
13
- };
14
- use temporal_sdk_core_test_utils::CoreWfStarter;
15
- use url::Url;
1
+ use temporal_client::WorkflowClientTrait;
2
+ use temporal_sdk_core_test_utils::get_cloud_client;
16
3
 
17
- async fn get_client(client_name: &str) -> RetryClient<Client> {
18
- let cloud_addr = env::var("TEMPORAL_CLOUD_ADDRESS").unwrap();
19
- let cloud_key = env::var("TEMPORAL_CLIENT_KEY").unwrap();
20
-
21
- let client_cert = env::var("TEMPORAL_CLIENT_CERT")
22
- .expect("TEMPORAL_CLIENT_CERT must be set")
23
- .replace("\\n", "\n")
24
- .into_bytes();
25
- let client_private_key = cloud_key.replace("\\n", "\n").into_bytes();
26
- let sgo = ClientOptionsBuilder::default()
27
- .target_url(Url::from_str(&cloud_addr).unwrap())
28
- .client_name(client_name)
29
- .client_version("clientver")
30
- .identity("sdk-test-client")
31
- .tls_cfg(TlsConfig {
32
- client_tls_config: Some(ClientTlsConfig {
33
- client_cert,
34
- client_private_key,
35
- }),
36
- ..Default::default()
37
- })
38
- .build()
39
- .unwrap();
40
- sgo.connect(
41
- env::var("TEMPORAL_NAMESPACE").expect("TEMPORAL_NAMESPACE must be set"),
42
- None,
43
- )
44
- .await
45
- .unwrap()
46
- }
4
+ mod shared_tests;
47
5
 
48
6
  #[tokio::test]
49
7
  async fn tls_test() {
50
- let con = get_client("tls_tester").await;
8
+ let con = get_cloud_client().await;
51
9
  con.list_workflow_executions(100, vec![], "".to_string())
52
10
  .await
53
11
  .unwrap();
@@ -55,32 +13,11 @@ async fn tls_test() {
55
13
 
56
14
  #[tokio::test]
57
15
  async fn grpc_message_too_large_test() {
58
- let wf_name = "oversize_grpc_message";
59
- let mut starter =
60
- CoreWfStarter::new_with_client(wf_name, get_client("grpc_message_too_large").await);
61
- starter.worker_config.no_remote_activities(true);
62
- let mut core = starter.worker().await;
63
-
64
- static OVERSIZE_GRPC_MESSAGE_RUN: AtomicBool = AtomicBool::new(false);
65
- core.register_wf(wf_name.to_owned(), |_ctx: WfContext| async move {
66
- if OVERSIZE_GRPC_MESSAGE_RUN.load(Relaxed) {
67
- Ok(vec![].into())
68
- } else {
69
- OVERSIZE_GRPC_MESSAGE_RUN.store(true, Relaxed);
70
- let result: Vec<u8> = vec![0; 5000000];
71
- Ok(result.into())
72
- }
73
- });
74
- starter.start_with_worker(wf_name, &mut core).await;
75
- core.run_until_done().await.unwrap();
76
-
77
- assert!(starter.get_history().await.events.iter().any(|e| {
78
- e.event_type == EventType::WorkflowTaskFailed as i32
79
- && if let WorkflowTaskFailedEventAttributes(attr) = e.attributes.as_ref().unwrap() {
80
- attr.cause == GrpcMessageTooLarge as i32
81
- && attr.failure.as_ref().unwrap().message == "GRPC Message too large"
82
- } else {
83
- false
84
- }
85
- }))
16
+ shared_tests::grpc_message_too_large().await
86
17
  }
18
+
19
+ // Needs https://github.com/temporalio/temporal/pull/8143 to be rolled out in cloud to pass
20
+ // #[tokio::test]
21
+ // async fn priority_values_sent_to_server() {
22
+ // shared_tests::priority::priority_values_sent_to_server().await
23
+ // }
@@ -110,7 +110,7 @@ struct GenericService<F> {
110
110
  }
111
111
  impl<F> Service<tonic::codegen::http::Request<Body>> for GenericService<F>
112
112
  where
113
- F: FnMut() -> Response<Body>,
113
+ F: FnMut() -> BoxFuture<'static, Response<Body>>,
114
114
  {
115
115
  type Response = Response<Body>;
116
116
  type Error = Infallible;
@@ -133,7 +133,7 @@ where
133
133
  )
134
134
  .unwrap();
135
135
  let r = (self.response_maker)();
136
- async move { Ok(r) }.boxed()
136
+ async move { Ok(r.await) }.boxed()
137
137
  }
138
138
  }
139
139
  impl<F> NamedService for GenericService<F> {
@@ -144,12 +144,12 @@ struct FakeServer {
144
144
  addr: std::net::SocketAddr,
145
145
  shutdown_tx: oneshot::Sender<()>,
146
146
  header_rx: tokio::sync::mpsc::UnboundedReceiver<String>,
147
- server_handle: tokio::task::JoinHandle<()>,
147
+ pub server_handle: tokio::task::JoinHandle<()>,
148
148
  }
149
149
 
150
150
  async fn fake_server<F>(response_maker: F) -> FakeServer
151
151
  where
152
- F: FnMut() -> Response<Body> + Clone + Send + Sync + 'static,
152
+ F: FnMut() -> BoxFuture<'static, Response<Body>> + Clone + Send + Sync + 'static,
153
153
  {
154
154
  let (shutdown_tx, shutdown_rx) = oneshot::channel::<()>();
155
155
  let (header_tx, header_rx) = tokio::sync::mpsc::unbounded_channel();
@@ -191,7 +191,7 @@ impl FakeServer {
191
191
 
192
192
  #[tokio::test]
193
193
  async fn timeouts_respected_one_call_fake_server() {
194
- let mut fs = fake_server(|| Response::new(Body::empty())).await;
194
+ let mut fs = fake_server(|| async { Response::new(Body::empty()) }.boxed()).await;
195
195
  let header_rx = &mut fs.header_rx;
196
196
 
197
197
  let mut opts = get_integ_server_options();
@@ -260,7 +260,11 @@ async fn non_retryable_errors() {
260
260
  Code::Unauthenticated,
261
261
  Code::Unimplemented,
262
262
  ] {
263
- let mut fs = fake_server(move || Status::new(code, "bla").into_http()).await;
263
+ let mut fs = fake_server(move || {
264
+ let s = Status::new(code, "bla").into_http();
265
+ async { s }.boxed()
266
+ })
267
+ .await;
264
268
 
265
269
  let mut opts = get_integ_server_options();
266
270
  let uri = format!("http://localhost:{}", fs.addr.port())
@@ -292,13 +296,13 @@ async fn retryable_errors() {
292
296
  {
293
297
  let count = Arc::new(AtomicUsize::new(0));
294
298
  let mut fs = fake_server(move || {
295
- dbg!("Making resp");
296
299
  let prev = count.fetch_add(1, Ordering::Relaxed);
297
- if prev < 3 {
300
+ let r = if prev < 3 {
298
301
  Status::new(code, "bla").into_http()
299
302
  } else {
300
303
  make_ok_response(RespondActivityTaskCanceledResponse::default())
301
- }
304
+ };
305
+ async { r }.boxed()
302
306
  })
303
307
  .await;
304
308
 
@@ -335,7 +339,7 @@ async fn namespace_header_attached_to_relevant_calls() {
335
339
  .add_service(GenericService {
336
340
  header_to_parse: "Temporal-Namespace",
337
341
  header_tx,
338
- response_maker: || Response::new(Body::empty()),
342
+ response_maker: || async { Response::new(Body::empty()) }.boxed(),
339
343
  })
340
344
  .serve_with_incoming_shutdown(
341
345
  tokio_stream::wrappers::TcpListenerStream::new(listener),
@@ -1,3 +1,4 @@
1
+ use crate::shared_tests;
1
2
  use assert_matches::assert_matches;
2
3
  use std::{
3
4
  cell::Cell,
@@ -15,13 +16,13 @@ use temporal_sdk_core_api::{
15
16
  errors::WorkerValidationError,
16
17
  worker::{PollerBehavior, WorkerConfigBuilder, WorkerVersioningStrategy},
17
18
  };
18
- use temporal_sdk_core_protos::temporal::api::enums::v1::WorkflowTaskFailedCause::GrpcMessageTooLarge;
19
19
  use temporal_sdk_core_protos::{
20
20
  coresdk::workflow_completion::{
21
21
  Failure, WorkflowActivationCompletion, workflow_activation_completion::Status,
22
22
  },
23
23
  temporal::api::{
24
- enums::v1::EventType, failure::v1::Failure as InnerFailure,
24
+ enums::v1::{EventType, WorkflowTaskFailedCause::GrpcMessageTooLarge},
25
+ failure::v1::Failure as InnerFailure,
25
26
  history::v1::history_event::Attributes::WorkflowTaskFailedEventAttributes,
26
27
  },
27
28
  };
@@ -195,3 +196,8 @@ async fn oversize_grpc_message() {
195
196
  }
196
197
  }))
197
198
  }
199
+
200
+ #[tokio::test]
201
+ async fn grpc_message_too_large_test() {
202
+ shared_tests::grpc_message_too_large().await
203
+ }
@@ -11,6 +11,7 @@ use temporal_sdk::{
11
11
  ActContext, ActExitValue, ActivityError, ActivityOptions, CancellableFuture, WfContext,
12
12
  WfExitValue, WorkflowResult,
13
13
  };
14
+ use temporal_sdk_core_api::worker::PollerBehavior;
14
15
  use temporal_sdk_core_protos::{
15
16
  DEFAULT_ACTIVITY_TYPE, TaskToken,
16
17
  coresdk::{
@@ -1066,11 +1067,23 @@ async fn activity_can_be_cancelled_by_local_timeout() {
1066
1067
 
1067
1068
  #[tokio::test]
1068
1069
  #[ignore] // Runs forever, used to manually attempt to repro spurious activity completion rpc errs
1070
+ // Unfortunately there is no way to unit test this as tonic doesn't publicly expose the necessary
1071
+ // machinery to construct the right kind of error.
1069
1072
  async fn long_activity_timeout_repro() {
1070
1073
  let wf_name = "long_activity_timeout_repro";
1071
1074
  let mut starter = CoreWfStarter::new(wf_name);
1072
1075
  starter
1073
1076
  .worker_config
1077
+ .workflow_task_poller_behavior(PollerBehavior::Autoscaling {
1078
+ minimum: 1,
1079
+ maximum: 10,
1080
+ initial: 5,
1081
+ })
1082
+ .activity_task_poller_behavior(PollerBehavior::Autoscaling {
1083
+ minimum: 1,
1084
+ maximum: 10,
1085
+ initial: 5,
1086
+ })
1074
1087
  .local_timeout_buffer_for_activities(Duration::from_secs(0));
1075
1088
  let mut worker = starter.worker().await;
1076
1089
  worker.register_wf(wf_name.to_owned(), |ctx: WfContext| async move {
@@ -1,112 +1,6 @@
1
- use std::time::Duration;
2
- use temporal_client::{Priority, WorkflowClientTrait, WorkflowOptions};
3
- use temporal_sdk::{ActContext, ActivityOptions, ChildWorkflowOptions, WfContext};
4
- use temporal_sdk_core_protos::{
5
- coresdk::AsJsonPayloadExt,
6
- temporal::api::{common, history::v1::history_event::Attributes},
7
- };
8
- use temporal_sdk_core_test_utils::CoreWfStarter;
1
+ use crate::shared_tests;
9
2
 
10
3
  #[tokio::test]
11
4
  async fn priority_values_sent_to_server() {
12
- let mut starter = CoreWfStarter::new("priority-values-sent-to-server");
13
- starter.workflow_options.priority = Some(Priority { priority_key: 1 });
14
- let mut worker = starter.worker().await;
15
- let child_type = "child-wf";
16
-
17
- worker.register_wf(starter.get_task_queue(), move |ctx: WfContext| async move {
18
- let child = ctx.child_workflow(ChildWorkflowOptions {
19
- workflow_id: format!("{}-child", ctx.task_queue()),
20
- workflow_type: child_type.to_owned(),
21
- options: WorkflowOptions {
22
- priority: Some(Priority { priority_key: 4 }),
23
- ..Default::default()
24
- },
25
- ..Default::default()
26
- });
27
-
28
- let started = child
29
- .start(&ctx)
30
- .await
31
- .into_started()
32
- .expect("Child should start OK");
33
- let activity = ctx.activity(ActivityOptions {
34
- activity_type: "echo".to_owned(),
35
- input: "hello".as_json_payload().unwrap(),
36
- start_to_close_timeout: Some(Duration::from_secs(5)),
37
- priority: Some(Priority { priority_key: 5 }),
38
- // Currently no priority info attached to eagerly run activities
39
- do_not_eagerly_execute: true,
40
- ..Default::default()
41
- });
42
- started.result().await;
43
- activity.await.unwrap_ok_payload();
44
- Ok(().into())
45
- });
46
- worker.register_wf(child_type.to_owned(), |ctx: WfContext| async move {
47
- assert_eq!(
48
- ctx.workflow_initial_info().priority,
49
- Some(common::v1::Priority { priority_key: 4 })
50
- );
51
- Ok(().into())
52
- });
53
- worker.register_activity("echo", |ctx: ActContext, echo_me: String| async move {
54
- assert_eq!(ctx.get_info().priority, Priority { priority_key: 5 });
55
- Ok(echo_me)
56
- });
57
-
58
- starter
59
- .start_with_worker(starter.get_task_queue(), &mut worker)
60
- .await;
61
- worker.run_until_done().await.unwrap();
62
-
63
- let client = starter.get_client().await;
64
- let history = client
65
- .get_workflow_execution_history(starter.get_task_queue().to_owned(), None, vec![])
66
- .await
67
- .unwrap()
68
- .history
69
- .unwrap();
70
- let workflow_init_event = history
71
- .events
72
- .iter()
73
- .find_map(|e| {
74
- if let Attributes::WorkflowExecutionStartedEventAttributes(e) =
75
- e.attributes.as_ref().unwrap()
76
- {
77
- Some(e)
78
- } else {
79
- None
80
- }
81
- })
82
- .unwrap();
83
- assert_eq!(workflow_init_event.priority.unwrap().priority_key, 1);
84
- let child_init_event = history
85
- .events
86
- .iter()
87
- .find_map(|e| {
88
- if let Attributes::StartChildWorkflowExecutionInitiatedEventAttributes(e) =
89
- e.attributes.as_ref().unwrap()
90
- {
91
- Some(e)
92
- } else {
93
- None
94
- }
95
- })
96
- .unwrap();
97
- assert_eq!(child_init_event.priority.unwrap().priority_key, 4);
98
- let activity_sched_event = history
99
- .events
100
- .iter()
101
- .find_map(|e| {
102
- if let Attributes::ActivityTaskScheduledEventAttributes(e) =
103
- e.attributes.as_ref().unwrap()
104
- {
105
- Some(e)
106
- } else {
107
- None
108
- }
109
- })
110
- .unwrap();
111
- assert_eq!(activity_sched_event.priority.unwrap().priority_key, 5);
5
+ shared_tests::priority::priority_values_sent_to_server().await
112
6
  }
@@ -5,6 +5,9 @@ extern crate rstest;
5
5
  #[macro_use]
6
6
  extern crate temporal_sdk_core_test_utils;
7
7
 
8
+ #[cfg(test)]
9
+ mod shared_tests;
10
+
8
11
  #[cfg(test)]
9
12
  mod integ_tests {
10
13
  mod activity_functions;
@@ -0,0 +1,43 @@
1
+ //! Shared tests that are meant to be run against both local dev server and cloud
2
+
3
+ use std::sync::atomic::{AtomicBool, Ordering::Relaxed};
4
+ use temporal_sdk::WfContext;
5
+ use temporal_sdk_core_protos::temporal::api::{
6
+ enums::v1::{EventType, WorkflowTaskFailedCause::GrpcMessageTooLarge},
7
+ history::v1::history_event::Attributes::WorkflowTaskFailedEventAttributes,
8
+ };
9
+ use temporal_sdk_core_test_utils::CoreWfStarter;
10
+
11
+ pub(crate) mod priority;
12
+
13
+ pub(crate) async fn grpc_message_too_large() {
14
+ let wf_name = "oversize_grpc_message";
15
+ let mut starter = CoreWfStarter::new_cloud_or_local(wf_name, "")
16
+ .await
17
+ .unwrap();
18
+ starter.worker_config.no_remote_activities(true);
19
+ let mut core = starter.worker().await;
20
+
21
+ static OVERSIZE_GRPC_MESSAGE_RUN: AtomicBool = AtomicBool::new(false);
22
+ core.register_wf(wf_name.to_owned(), |_ctx: WfContext| async move {
23
+ if OVERSIZE_GRPC_MESSAGE_RUN.load(Relaxed) {
24
+ Ok(vec![].into())
25
+ } else {
26
+ OVERSIZE_GRPC_MESSAGE_RUN.store(true, Relaxed);
27
+ let result: Vec<u8> = vec![0; 5000000];
28
+ Ok(result.into())
29
+ }
30
+ });
31
+ starter.start_with_worker(wf_name, &mut core).await;
32
+ core.run_until_done().await.unwrap();
33
+
34
+ assert!(starter.get_history().await.events.iter().any(|e| {
35
+ e.event_type == EventType::WorkflowTaskFailed as i32
36
+ && if let WorkflowTaskFailedEventAttributes(attr) = e.attributes.as_ref().unwrap() {
37
+ attr.cause == GrpcMessageTooLarge as i32
38
+ && attr.failure.as_ref().unwrap().message == "GRPC Message too large"
39
+ } else {
40
+ false
41
+ }
42
+ }))
43
+ }