@temporalio/core-bridge 1.7.0 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@temporalio/core-bridge",
3
- "version": "1.7.0",
3
+ "version": "1.7.1",
4
4
  "description": "Temporal.io SDK Core<>Node bridge",
5
5
  "main": "index.js",
6
6
  "types": "lib/index.d.ts",
@@ -23,7 +23,7 @@
23
23
  "license": "MIT",
24
24
  "dependencies": {
25
25
  "@opentelemetry/api": "^1.3.0",
26
- "@temporalio/common": "1.7.0",
26
+ "@temporalio/common": "1.7.1",
27
27
  "arg": "^5.0.2",
28
28
  "cargo-cp-artifact": "^0.1.6",
29
29
  "which": "^2.0.2"
@@ -53,5 +53,5 @@
53
53
  "publishConfig": {
54
54
  "access": "public"
55
55
  },
56
- "gitHead": "2b32bac62f879b35238b487d3aaed093a1e449a7"
56
+ "gitHead": "368aa83c631555fc31cff25f4af8817d069878d8"
57
57
  }
@@ -33,7 +33,7 @@ use crate::{
33
33
  workflow_handle::UntypedWorkflowHandle,
34
34
  };
35
35
  use backoff::{exponential, ExponentialBackoff, SystemClock};
36
- use http::uri::InvalidUri;
36
+ use http::{uri::InvalidUri, Uri};
37
37
  use once_cell::sync::OnceCell;
38
38
  use parking_lot::RwLock;
39
39
  use std::{
@@ -114,6 +114,14 @@ pub struct ClientOptions {
114
114
  /// Retry configuration for the server client. Default is [RetryConfig::default]
115
115
  #[builder(default)]
116
116
  pub retry_config: RetryConfig,
117
+
118
+ /// If set, override the origin used when connecting. May be useful in rare situations where tls
119
+ /// verification needs to use a different name from what should be set as the `:authority`
120
+ /// header. If [TlsConfig::domain] is set, and this is not, this will be set to
121
+ /// `https://<domain>`, effectively making the `:authority` header consistent with the domain
122
+ /// override.
123
+ #[builder(default)]
124
+ pub override_origin: Option<Uri>,
117
125
  }
118
126
 
119
127
  /// Configuration options for TLS
@@ -310,6 +318,11 @@ impl ClientOptions {
310
318
  {
311
319
  let channel = Channel::from_shared(self.target_url.to_string())?;
312
320
  let channel = self.add_tls_to_channel(channel).await?;
321
+ let channel = if let Some(origin) = self.override_origin.clone() {
322
+ channel.origin(origin)
323
+ } else {
324
+ channel
325
+ };
313
326
  let channel = channel.connect().await?;
314
327
  let service = ServiceBuilder::new()
315
328
  .layer_fn(|channel| GrpcMetricSvc {
@@ -347,10 +360,7 @@ impl ClientOptions {
347
360
 
348
361
  /// If TLS is configured, set the appropriate options on the provided channel and return it.
349
362
  /// Passes it through if TLS options not set.
350
- async fn add_tls_to_channel(
351
- &self,
352
- channel: Endpoint,
353
- ) -> Result<Endpoint, tonic::transport::Error> {
363
+ async fn add_tls_to_channel(&self, mut channel: Endpoint) -> Result<Endpoint, ClientInitError> {
354
364
  if let Some(tls_cfg) = &self.tls_cfg {
355
365
  let mut tls = tonic::transport::ClientTlsConfig::new();
356
366
 
@@ -361,6 +371,13 @@ impl ClientOptions {
361
371
 
362
372
  if let Some(domain) = &tls_cfg.domain {
363
373
  tls = tls.domain_name(domain);
374
+
375
+ // This song and dance ultimately is just to make sure the `:authority` header ends
376
+ // up correct on requests while we use TLS. Setting the header directly in our
377
+ // interceptor doesn't work since seemingly it is overridden at some point by
378
+ // something lower level.
379
+ let uri: Uri = format!("https://{}", domain).parse()?;
380
+ channel = channel.origin(uri);
364
381
  }
365
382
 
366
383
  if let Some(client_opts) = &tls_cfg.client_tls_config {
@@ -369,7 +386,7 @@ impl ClientOptions {
369
386
  tls = tls.identity(client_identity);
370
387
  }
371
388
 
372
- return channel.tls_config(tls);
389
+ return channel.tls_config(tls).map_err(Into::into);
373
390
  }
374
391
  Ok(channel)
375
392
  }
@@ -13,8 +13,11 @@ use temporal_sdk::{
13
13
  ActivityOptions, ChildWorkflowOptions, LocalActivityOptions, WfContext, WorkflowResult,
14
14
  };
15
15
  use temporal_sdk_core_protos::{
16
- temporal::api::{enums::v1::WorkflowTaskFailedCause, failure::v1::Failure},
17
- DEFAULT_ACTIVITY_TYPE,
16
+ temporal::api::{
17
+ enums::v1::{EventType, WorkflowTaskFailedCause},
18
+ failure::v1::Failure,
19
+ },
20
+ TestHistoryBuilder, DEFAULT_ACTIVITY_TYPE,
18
21
  };
19
22
 
20
23
  static DID_FAIL: AtomicBool = AtomicBool::new(false);
@@ -268,3 +271,47 @@ async fn child_wf_id_or_type_change_is_nondeterministic(
268
271
  .unwrap();
269
272
  worker.run_until_done().await.unwrap();
270
273
  }
274
+
275
+ /// Repros a situation where if, upon completing a task there is some internal error which causes
276
+ /// us to want to auto-fail the workflow task while there is also an outstanding eviction, the wf
277
+ /// would get evicted but then try to send some info down the completion channel afterward, causing
278
+ /// a panic.
279
+ #[tokio::test]
280
+ async fn repro_channel_missing_because_nondeterminism() {
281
+ for _ in 1..50 {
282
+ let wf_id = "fakeid";
283
+ let wf_type = DEFAULT_WORKFLOW_TYPE;
284
+ let mut t = TestHistoryBuilder::default();
285
+ t.add_by_type(EventType::WorkflowExecutionStarted);
286
+ t.add_full_wf_task();
287
+ t.add_has_change_marker("patch-1", false);
288
+ let _ts = t.add_by_type(EventType::TimerStarted);
289
+ t.add_workflow_task_scheduled_and_started();
290
+
291
+ let mock = mock_workflow_client();
292
+ let mut mh =
293
+ MockPollCfg::from_resp_batches(wf_id, t, [1.into(), ResponseType::AllHistory], mock);
294
+ mh.num_expected_fails = 1;
295
+ let mut worker = mock_sdk_cfg(mh, |cfg| {
296
+ cfg.max_cached_workflows = 2;
297
+ cfg.ignore_evicts_on_shutdown = false;
298
+ });
299
+
300
+ worker.register_wf(wf_type.to_owned(), move |ctx: WfContext| async move {
301
+ ctx.patched("wrongid");
302
+ ctx.timer(Duration::from_secs(1)).await;
303
+ Ok(().into())
304
+ });
305
+
306
+ worker
307
+ .submit_wf(
308
+ wf_id.to_owned(),
309
+ wf_type.to_owned(),
310
+ vec![],
311
+ WorkflowOptions::default(),
312
+ )
313
+ .await
314
+ .unwrap();
315
+ worker.run_until_done().await.unwrap();
316
+ }
317
+ }
@@ -47,20 +47,6 @@ impl InternalFlags {
47
47
  }
48
48
  }
49
49
 
50
- #[cfg(test)]
51
- pub fn all_core_enabled() -> Self {
52
- Self {
53
- enabled: true,
54
- core: BTreeSet::from([
55
- CoreInternalFlags::IdAndTypeDeterminismChecks,
56
- CoreInternalFlags::UpsertSearchAttributeOnPatch,
57
- ]),
58
- lang: Default::default(),
59
- core_since_last_complete: Default::default(),
60
- lang_since_last_complete: Default::default(),
61
- }
62
- }
63
-
64
50
  pub fn add_from_complete(&mut self, e: &WorkflowTaskCompletedEventAttributes) {
65
51
  if !self.enabled {
66
52
  return;
@@ -538,6 +538,7 @@ impl Worker {
538
538
  self.workflows
539
539
  .activation_completed(
540
540
  completion,
541
+ false,
541
542
  self.post_activate_hook
542
543
  .as_ref()
543
544
  .map(|h| |data: PostActivateHookData| h(self, data)),
@@ -38,7 +38,7 @@ fsm! {
38
38
  // upon observing a history event indicating that the command has been recorded. Note that this
39
39
  // does not imply that the command has been _executed_, only that it _will be_ executed at some
40
40
  // point in the future.
41
- CommandIssued --(CommandRecorded(CmdRecDat), shared on_command_recorded) --> Done;
41
+ CommandIssued --(CommandRecorded, on_command_recorded) --> Done;
42
42
  }
43
43
 
44
44
  /// Instantiates an UpsertSearchAttributesMachine and packs it together with an initial command
@@ -62,37 +62,21 @@ pub(super) fn upsert_search_attrs(
62
62
  );
63
63
  // We must still create the command to preserve compatability with anyone previously doing
64
64
  // this.
65
- create_new(Default::default(), true, internal_flags)
65
+ create_new(Default::default())
66
66
  } else {
67
- create_new(attribs.search_attributes.into(), false, internal_flags)
67
+ create_new(attribs.search_attributes.into())
68
68
  }
69
69
  }
70
70
 
71
71
  /// May be used by other state machines / internal needs which desire upserting search attributes.
72
72
  pub(super) fn upsert_search_attrs_internal(
73
73
  attribs: UpsertWorkflowSearchAttributesCommandAttributes,
74
- internal_flags: InternalFlagsRef,
75
74
  ) -> NewMachineWithCommand {
76
- create_new(
77
- attribs.search_attributes.unwrap_or_default(),
78
- true,
79
- internal_flags,
80
- )
75
+ create_new(attribs.search_attributes.unwrap_or_default())
81
76
  }
82
77
 
83
- fn create_new(
84
- sa_map: SearchAttributes,
85
- should_skip_determinism: bool,
86
- internal_flags: InternalFlagsRef,
87
- ) -> NewMachineWithCommand {
88
- let sm = UpsertSearchAttributesMachine::from_parts(
89
- Created {}.into(),
90
- SharedState {
91
- sa_map: sa_map.clone(),
92
- should_skip_determinism,
93
- internal_flags,
94
- },
95
- );
78
+ fn create_new(sa_map: SearchAttributes) -> NewMachineWithCommand {
79
+ let sm = UpsertSearchAttributesMachine::from_parts(Created {}.into(), SharedState {});
96
80
  let cmd = Command {
97
81
  command_type: CommandType::UpsertWorkflowSearchAttributes as i32,
98
82
  attributes: Some(
@@ -110,11 +94,7 @@ fn create_new(
110
94
  }
111
95
 
112
96
  #[derive(Clone)]
113
- pub(super) struct SharedState {
114
- should_skip_determinism: bool,
115
- sa_map: SearchAttributes,
116
- internal_flags: InternalFlagsRef,
117
- }
97
+ pub(super) struct SharedState {}
118
98
 
119
99
  /// The state-machine-specific set of commands that are the results of state transition in the
120
100
  /// UpsertSearchAttributesMachine. There are none of these because this state machine emits the
@@ -131,30 +111,9 @@ pub(super) struct Created {}
131
111
  /// higher-level machinery, it transitions into this state.
132
112
  #[derive(Debug, Default, Clone, derive_more::Display)]
133
113
  pub(super) struct CommandIssued {}
134
- pub(super) struct CmdRecDat {
135
- sa_map: Option<SearchAttributes>,
136
- replaying: bool,
137
- }
138
114
 
139
115
  impl CommandIssued {
140
- pub(super) fn on_command_recorded(
141
- self,
142
- shared: &mut SharedState,
143
- dat: CmdRecDat,
144
- ) -> UpsertSearchAttributesMachineTransition<Done> {
145
- if shared.internal_flags.borrow_mut().try_use(
146
- CoreInternalFlags::UpsertSearchAttributeOnPatch,
147
- !dat.replaying,
148
- ) {
149
- let sa = dat.sa_map.unwrap_or_default();
150
- if !shared.should_skip_determinism && shared.sa_map != sa {
151
- return TransitionResult::Err(WFMachinesError::Nondeterminism(format!(
152
- "Search attribute upsert calls must remain deterministic, but {:?} does not \
153
- match the attributes from history: {:?}",
154
- shared.sa_map, sa
155
- )));
156
- }
157
- }
116
+ pub(super) fn on_command_recorded(self) -> UpsertSearchAttributesMachineTransition<Done> {
158
117
  TransitionResult::default()
159
118
  }
160
119
  }
@@ -198,14 +157,9 @@ impl TryFrom<HistEventData> for UpsertSearchAttributesMachineEvents {
198
157
 
199
158
  fn try_from(e: HistEventData) -> Result<Self, Self::Error> {
200
159
  match e.event.attributes {
201
- Some(history_event::Attributes::UpsertWorkflowSearchAttributesEventAttributes(
202
- attrs,
203
- )) => Ok(UpsertSearchAttributesMachineEvents::CommandRecorded(
204
- CmdRecDat {
205
- sa_map: attrs.search_attributes,
206
- replaying: e.replaying,
207
- },
208
- )),
160
+ Some(history_event::Attributes::UpsertWorkflowSearchAttributesEventAttributes(_)) => {
161
+ Ok(UpsertSearchAttributesMachineEvents::CommandRecorded)
162
+ }
209
163
  _ => Err(Self::Error::Nondeterminism(format!(
210
164
  "UpsertWorkflowSearchAttributesMachine does not handle {e}"
211
165
  ))),
@@ -241,7 +195,6 @@ impl From<Created> for CommandIssued {
241
195
  mod tests {
242
196
  use super::{super::OnEventWrapper, *};
243
197
  use crate::{
244
- internal_flags::InternalFlags,
245
198
  replay::TestHistoryBuilder,
246
199
  test_help::{build_mock_pollers, mock_worker, MockPollCfg, ResponseType},
247
200
  worker::{
@@ -249,8 +202,8 @@ mod tests {
249
202
  workflow::{machines::patch_state_machine::VERSION_SEARCH_ATTR_KEY, ManagedWFFunc},
250
203
  },
251
204
  };
252
- use rustfsm::{MachineError, StateMachine};
253
- use std::{cell::RefCell, collections::HashMap, rc::Rc};
205
+ use rustfsm::StateMachine;
206
+ use std::collections::HashMap;
254
207
  use temporal_sdk::{WfContext, WorkflowFunction};
255
208
  use temporal_sdk_core_api::Worker;
256
209
  use temporal_sdk_core_protos::{
@@ -317,25 +270,14 @@ mod tests {
317
270
  }
318
271
 
319
272
  #[rstest::rstest]
320
- fn upsert_search_attrs_sm(#[values(true, false)] nondetermistic: bool) {
321
- let mut sm = UpsertSearchAttributesMachine::from_parts(
322
- Created {}.into(),
323
- SharedState {
324
- sa_map: Default::default(),
325
- should_skip_determinism: false,
326
- internal_flags: Rc::new(RefCell::new(InternalFlags::all_core_enabled())),
327
- },
328
- );
329
-
330
- let sa_attribs = if nondetermistic {
331
- UpsertWorkflowSearchAttributesEventAttributes {
332
- workflow_task_completed_event_id: 0,
333
- search_attributes: Some(SearchAttributes {
334
- indexed_fields: HashMap::from([("Yo".to_string(), Payload::default())]),
335
- }),
336
- }
337
- } else {
338
- Default::default()
273
+ fn upsert_search_attrs_sm() {
274
+ let mut sm = UpsertSearchAttributesMachine::from_parts(Created {}.into(), SharedState {});
275
+
276
+ let sa_attribs = UpsertWorkflowSearchAttributesEventAttributes {
277
+ workflow_task_completed_event_id: 0,
278
+ search_attributes: Some(SearchAttributes {
279
+ indexed_fields: HashMap::from([("Yo".to_string(), Payload::default())]),
280
+ }),
339
281
  };
340
282
  let recorded_history_event = HistoryEvent {
341
283
  event_type: EventType::UpsertWorkflowSearchAttributes as i32,
@@ -365,15 +307,8 @@ mod tests {
365
307
  assert_eq!(CommandIssued {}.to_string(), sm.state().to_string());
366
308
 
367
309
  let recorded_res = OnEventWrapper::on_event_mut(&mut sm, cmd_recorded_sm_event);
368
- if nondetermistic {
369
- assert_matches!(
370
- recorded_res.unwrap_err(),
371
- MachineError::Underlying(WFMachinesError::Nondeterminism(_))
372
- );
373
- } else {
374
- recorded_res.expect("CommandRecorded should transition CommandIssued -> Done");
375
- assert_eq!(Done {}.to_string(), sm.state().to_string());
376
- }
310
+ recorded_res.expect("CommandRecorded should transition CommandIssued -> Done");
311
+ assert_eq!(Done {}.to_string(), sm.state().to_string());
377
312
  }
378
313
 
379
314
  #[rstest::rstest]
@@ -924,10 +924,7 @@ impl WorkflowMachines {
924
924
  }
925
925
  ProtoCmdAttrs::UpsertWorkflowSearchAttributesCommandAttributes(attrs) => {
926
926
  self.add_cmd_to_wf_task(
927
- upsert_search_attrs_internal(
928
- attrs,
929
- self.observed_internal_flags.clone(),
930
- ),
927
+ upsert_search_attrs_internal(attrs),
931
928
  CommandIdKind::NeverResolves,
932
929
  );
933
930
  }
@@ -550,8 +550,15 @@ impl ManagedRun {
550
550
 
551
551
  /// Delete the currently tracked workflow activation and return it, if any. Should be called
552
552
  /// after the processing of the activation completion, and WFT reporting.
553
- pub(super) fn delete_activation(&mut self) -> Option<OutstandingActivation> {
554
- self.activation.take()
553
+ pub(super) fn delete_activation(
554
+ &mut self,
555
+ pred: impl FnOnce(&OutstandingActivation) -> bool,
556
+ ) -> Option<OutstandingActivation> {
557
+ if self.activation().map(pred).unwrap_or_default() {
558
+ self.activation.take()
559
+ } else {
560
+ None
561
+ }
555
562
  }
556
563
 
557
564
  /// Called when local activities resolve
@@ -929,6 +936,7 @@ impl ManagedRun {
929
936
  }
930
937
 
931
938
  fn insert_outstanding_activation(&mut self, act: &ActivationOrAuto) {
939
+ warn!("Inserting {:?}", act);
932
940
  let act_type = match &act {
933
941
  ActivationOrAuto::LangActivation(act) | ActivationOrAuto::ReadyForQueries(act) => {
934
942
  if act.is_legacy_query() {
@@ -23,8 +23,8 @@ pub(crate) use managed_run::ManagedWFFunc;
23
23
 
24
24
  use crate::{
25
25
  abstractions::{
26
- stream_when_allowed, take_cell::TakeCell, MeteredSemaphore, TrackedOwnedMeteredSemPermit,
27
- UsedMeteredSemPermit,
26
+ dbg_panic, stream_when_allowed, take_cell::TakeCell, MeteredSemaphore,
27
+ TrackedOwnedMeteredSemPermit, UsedMeteredSemPermit,
28
28
  },
29
29
  internal_flags::InternalFlags,
30
30
  protosext::{legacy_query_failure, ValidPollWFTQResponse},
@@ -294,6 +294,7 @@ impl Workflows {
294
294
  workflow_completion::Success::from_variants(vec![]).into(),
295
295
  ),
296
296
  },
297
+ true,
297
298
  // We need to say a type, but the type is irrelevant, so imagine some
298
299
  // boxed function we'll never call.
299
300
  Option::<Box<dyn Fn(PostActivateHookData) + Send>>::None,
@@ -309,6 +310,7 @@ impl Workflows {
309
310
  run_id,
310
311
  status: Some(auto_fail_to_complete_status(machines_err)),
311
312
  },
313
+ true,
312
314
  Option::<Box<dyn Fn(PostActivateHookData) + Send>>::None,
313
315
  )
314
316
  .await?;
@@ -324,8 +326,9 @@ impl Workflows {
324
326
  pub(super) async fn activation_completed(
325
327
  &self,
326
328
  completion: WorkflowActivationCompletion,
329
+ is_autocomplete: bool,
327
330
  post_activate_hook: Option<impl Fn(PostActivateHookData)>,
328
- ) -> Result<usize, CompleteWfError> {
331
+ ) -> Result<(), CompleteWfError> {
329
332
  let is_empty_completion = completion.is_empty();
330
333
  let completion = validate_completion(completion)?;
331
334
  let run_id = completion.run_id().to_string();
@@ -337,7 +340,7 @@ impl Workflows {
337
340
  if !was_sent {
338
341
  if is_empty_completion {
339
342
  // Empty complete which is likely an evict reply, we can just ignore.
340
- return Ok(0);
343
+ return Ok(());
341
344
  }
342
345
  panic!(
343
346
  "A non-empty completion was not processed. Workflow processing may have \
@@ -345,9 +348,18 @@ impl Workflows {
345
348
  );
346
349
  }
347
350
 
348
- let completion_outcome = rx
349
- .await
350
- .expect("Send half of activation complete response not dropped");
351
+ let completion_outcome = if let Ok(c) = rx.await {
352
+ c
353
+ } else {
354
+ dbg_panic!("Send half of activation complete response channel went missing");
355
+ self.request_eviction(
356
+ run_id,
357
+ "Send half of activation complete response channel went missing",
358
+ EvictionReason::Fatal,
359
+ );
360
+ return Ok(());
361
+ };
362
+
351
363
  let mut wft_from_complete = None;
352
364
  let wft_report_status = match completion_outcome.outcome {
353
365
  ActivationCompleteOutcome::ReportWFTSuccess(report) => match report {
@@ -460,9 +472,10 @@ impl Workflows {
460
472
  run_id,
461
473
  wft_report_status,
462
474
  wft_from_complete: maybe_pwft,
475
+ is_autocomplete,
463
476
  });
464
477
 
465
- Ok(completion_outcome.most_recently_processed_event)
478
+ Ok(())
466
479
  }
467
480
 
468
481
  /// Tell workflow that a local activity has finished with the provided result
@@ -932,6 +945,7 @@ struct PostActivationMsg {
932
945
  run_id: String,
933
946
  wft_report_status: WFTReportStatus,
934
947
  wft_from_complete: Option<(PreparedWFT, HistoryPaginator)>,
948
+ is_autocomplete: bool,
935
949
  }
936
950
  #[derive(Debug, Clone)]
937
951
  #[cfg_attr(
@@ -338,37 +338,39 @@ impl WFStream {
338
338
 
339
339
  // If we reported to server, we always want to mark it complete.
340
340
  let maybe_t = self.complete_wft(run_id, report.wft_report_status);
341
- // Delete the activation
342
- let activation = self
343
- .runs
344
- .get_mut(run_id)
345
- .and_then(|rh| rh.delete_activation());
346
-
347
- // Evict the run if the activation contained an eviction
348
- let mut applied_buffered_poll_for_this_run = false;
349
- if activation.map(|a| a.has_eviction()).unwrap_or_default() {
350
- debug!(run_id=%run_id, "Evicting run");
351
-
352
- if let Some(mut rh) = self.runs.remove(run_id) {
353
- if let Some(buff) = rh.take_buffered_wft() {
354
- // Don't try to apply a buffered poll for this run if we just got a new WFT
355
- // from completing, because by definition that buffered poll is now an
356
- // out-of-date WFT.
357
- if wft_from_complete.is_none() {
358
- res = self.instantiate_or_update(buff);
359
- applied_buffered_poll_for_this_run = true;
341
+ // Delete the activation, but only if the report came from lang, or we know the outstanding
342
+ // activation is expected to be completed internally.
343
+ if let Some(activation) = self.runs.get_mut(run_id).and_then(|rh| {
344
+ rh.delete_activation(|act| {
345
+ !report.is_autocomplete || matches!(act, OutstandingActivation::Autocomplete)
346
+ })
347
+ }) {
348
+ // Evict the run if the activation contained an eviction
349
+ let mut applied_buffered_poll_for_this_run = false;
350
+ if activation.has_eviction() {
351
+ debug!(run_id=%run_id, "Evicting run");
352
+
353
+ if let Some(mut rh) = self.runs.remove(run_id) {
354
+ if let Some(buff) = rh.take_buffered_wft() {
355
+ // Don't try to apply a buffered poll for this run if we just got a new WFT
356
+ // from completing, because by definition that buffered poll is now an
357
+ // out-of-date WFT.
358
+ if wft_from_complete.is_none() {
359
+ res = self.instantiate_or_update(buff);
360
+ applied_buffered_poll_for_this_run = true;
361
+ }
360
362
  }
361
363
  }
362
- }
363
364
 
364
- // Attempt to apply a buffered poll for some *other* run, if we didn't have a wft
365
- // from complete or a buffered poll for *this* run.
366
- if wft_from_complete.is_none() && !applied_buffered_poll_for_this_run {
367
- if let Some(buff) = self.buffered_polls_need_cache_slot.pop_front() {
368
- res = self.instantiate_or_update(buff);
365
+ // Attempt to apply a buffered poll for some *other* run, if we didn't have a wft
366
+ // from complete or a buffered poll for *this* run.
367
+ if wft_from_complete.is_none() && !applied_buffered_poll_for_this_run {
368
+ if let Some(buff) = self.buffered_polls_need_cache_slot.pop_front() {
369
+ res = self.instantiate_or_update(buff);
370
+ }
369
371
  }
370
- }
371
- };
372
+ };
373
+ }
372
374
 
373
375
  if let Some((wft, pag)) = wft_from_complete {
374
376
  debug!(run_id=%wft.execution.run_id, "New WFT from completion");
@@ -25,7 +25,7 @@ mod integ_tests {
25
25
  use temporal_sdk_core_api::worker::WorkerConfigBuilder;
26
26
  use temporal_sdk_core_protos::temporal::api::workflowservice::v1::ListNamespacesRequest;
27
27
  use temporal_sdk_core_test_utils::{
28
- get_integ_server_options, get_integ_telem_options, NAMESPACE,
28
+ get_integ_server_options, get_integ_telem_options, init_integ_telem,
29
29
  };
30
30
  use url::Url;
31
31
 
@@ -58,35 +58,23 @@ mod integ_tests {
58
58
  .await;
59
59
  }
60
60
 
61
- // TODO: Currently ignored because starting up the docker image with TLS requires some hoop
62
- // jumping. We should upgrade CI to be able to do that but this was manually run against
63
- // https://github.com/temporalio/customization-samples/tree/master/tls/tls-simple
61
+ // Manually run to verify tls works against cloud. You will need certs in place in the
62
+ // indicated directory.
64
63
  #[tokio::test]
65
64
  #[ignore]
66
65
  async fn tls_test() {
67
- // Load certs/keys
68
- let root = tokio::fs::read(
69
- "/home/sushi/dev/temporal/customization-samples/tls/tls-simple/certs/ca.cert",
70
- )
71
- .await
72
- .unwrap();
73
- let client_cert = tokio::fs::read(
74
- "/home/sushi/dev/temporal/customization-samples/tls/tls-simple/certs/client.pem",
75
- )
76
- .await
77
- .unwrap();
78
- let client_private_key = tokio::fs::read(
79
- "/home/sushi/dev/temporal/customization-samples/tls/tls-simple/certs/client.key",
80
- )
81
- .await
82
- .unwrap();
66
+ init_integ_telem();
67
+ let root = tokio::fs::read("../.cloud_certs/ca.pem").await.unwrap();
68
+ let client_cert = tokio::fs::read("../.cloud_certs/client.pem").await.unwrap();
69
+ let client_private_key = tokio::fs::read("../.cloud_certs/client.key").await.unwrap();
83
70
  let sgo = ClientOptionsBuilder::default()
84
- .target_url(Url::from_str("https://localhost:7233").unwrap())
71
+ .target_url(Url::from_str("https://spencer.temporal-dev.tmprl.cloud:7233").unwrap())
85
72
  .client_name("tls_tester")
86
73
  .client_version("clientver")
87
74
  .tls_cfg(TlsConfig {
88
75
  server_root_ca_cert: Some(root),
89
- domain: Some("tls-sample".to_string()),
76
+ // Not necessary, but illustrates functionality for people using proxies, etc.
77
+ domain: Some("spencer.temporal-dev.tmprl.cloud".to_string()),
90
78
  client_tls_config: Some(ClientTlsConfig {
91
79
  client_cert,
92
80
  client_private_key,
@@ -95,9 +83,12 @@ mod integ_tests {
95
83
  .build()
96
84
  .unwrap();
97
85
  let con = sgo
98
- .connect(NAMESPACE.to_string(), None, None)
86
+ .connect("spencer.temporal-dev".to_string(), None, None)
99
87
  .await
100
88
  .unwrap();
101
- con.list_namespaces().await.unwrap();
89
+ dbg!(con
90
+ .list_workflow_executions(100, vec![], "".to_string())
91
+ .await
92
+ .unwrap());
102
93
  }
103
94
  }