1pub mod constants;
6mod task_token;
7pub mod utilities;
9pub use task_token::TaskToken;
10
11pub static ENCODING_PAYLOAD_KEY: &str = "encoding";
13pub static JSON_ENCODING_VAL: &str = "json/plain";
15pub static PATCHED_MARKER_DETAILS_KEY: &str = "patch-data";
17pub static VERSION_SEARCH_ATTR_KEY: &str = "TemporalChangeVersion";
19
20macro_rules! include_proto_with_serde {
21 ($pkg:tt) => {
22 tonic::include_proto!($pkg);
23
24 #[cfg(feature = "serde_serialize")]
25 include!(concat!(env!("OUT_DIR"), concat!("/", $pkg, ".serde.rs")));
26 };
27}
28
29#[allow(
30 clippy::large_enum_variant,
31 clippy::derive_partial_eq_without_eq,
32 clippy::reserve_after_initialization
33)]
34#[allow(missing_docs)]
36pub mod coresdk {
37 tonic::include_proto!("coresdk");
39 pub use self::sdk_helpers::*;
40 mod sdk_helpers {
41 use super::*;
42
43 use crate::protos::{
44 ENCODING_PAYLOAD_KEY, JSON_ENCODING_VAL,
45 temporal::api::{
46 common::v1::{Payload, Payloads, RetryPolicy, WorkflowExecution},
47 enums::v1::{
48 ApplicationErrorCategory, TimeoutType, VersioningBehavior,
49 WorkflowTaskFailedCause,
50 },
51 failure::v1::{
52 ActivityFailureInfo, ApplicationFailureInfo, Failure, TimeoutFailureInfo,
53 failure::FailureInfo,
54 },
55 workflowservice::v1::PollActivityTaskQueueResponse,
56 },
57 };
58 use activity_task::ActivityTask;
59 use serde::{Deserialize, Serialize};
60 use std::{
61 collections::HashMap,
62 convert::TryFrom,
63 fmt::{Display, Formatter},
64 iter::FromIterator,
65 };
66 use workflow_activation::{WorkflowActivationJob, workflow_activation_job};
67 use workflow_commands::{WorkflowCommand, workflow_command, workflow_command::Variant};
68 use workflow_completion::{WorkflowActivationCompletion, workflow_activation_completion};
69
70 pub type HistoryEventId = i64;
71
72 impl From<workflow_activation_job::Variant> for WorkflowActivationJob {
73 fn from(a: workflow_activation_job::Variant) -> Self {
74 Self { variant: Some(a) }
75 }
76 }
77
78 impl From<Vec<WorkflowCommand>> for workflow_completion::Success {
79 fn from(v: Vec<WorkflowCommand>) -> Self {
80 Self {
81 commands: v,
82 used_internal_flags: vec![],
83 versioning_behavior: VersioningBehavior::Unspecified.into(),
84 }
85 }
86 }
87
88 impl From<workflow_command::Variant> for WorkflowCommand {
89 fn from(v: workflow_command::Variant) -> Self {
90 Self {
91 variant: Some(v),
92 ..Default::default()
93 }
94 }
95 }
96
97 impl workflow_completion::Success {
98 pub fn from_variants(cmds: Vec<Variant>) -> Self {
99 let cmds: Vec<_> = cmds.into_iter().map(|c| c.into()).collect();
100 cmds.into()
101 }
102 }
103
104 impl WorkflowActivationCompletion {
105 pub fn empty(run_id: impl Into<String>) -> Self {
107 let success = workflow_completion::Success::from_variants(vec![]);
108 Self {
109 run_id: run_id.into(),
110 status: Some(workflow_activation_completion::Status::Successful(success)),
111 ..Default::default()
112 }
113 }
114
115 pub fn from_cmds(
117 run_id: impl Into<String>,
118 cmds: Vec<workflow_command::Variant>,
119 ) -> Self {
120 let success = workflow_completion::Success::from_variants(cmds);
121 Self {
122 run_id: run_id.into(),
123 status: Some(workflow_activation_completion::Status::Successful(success)),
124 ..Default::default()
125 }
126 }
127
128 pub fn from_cmd(run_id: impl Into<String>, cmd: workflow_command::Variant) -> Self {
130 let success = workflow_completion::Success::from_variants(vec![cmd]);
131 Self {
132 run_id: run_id.into(),
133 status: Some(workflow_activation_completion::Status::Successful(success)),
134 ..Default::default()
135 }
136 }
137
138 pub fn fail(
139 run_id: impl Into<String>,
140 failure: Failure,
141 cause: Option<WorkflowTaskFailedCause>,
142 ) -> Self {
143 Self {
144 run_id: run_id.into(),
145 status: Some(workflow_activation_completion::Status::Failed(
146 workflow_completion::Failure {
147 failure: Some(failure),
148 force_cause: cause.unwrap_or(WorkflowTaskFailedCause::Unspecified)
149 as i32,
150 },
151 )),
152 ..Default::default()
153 }
154 }
155
156 pub fn has_execution_ending(&self) -> bool {
159 self.has_complete_workflow_execution()
160 || self.has_fail_execution()
161 || self.has_continue_as_new()
162 || self.has_cancel_workflow_execution()
163 }
164
165 pub fn has_fail_execution(&self) -> bool {
167 if let Some(workflow_activation_completion::Status::Successful(s)) = &self.status {
168 return s.commands.iter().any(|wfc| {
169 matches!(
170 wfc,
171 WorkflowCommand {
172 variant: Some(workflow_command::Variant::FailWorkflowExecution(_)),
173 ..
174 }
175 )
176 });
177 }
178 false
179 }
180
181 pub fn has_cancel_workflow_execution(&self) -> bool {
183 if let Some(workflow_activation_completion::Status::Successful(s)) = &self.status {
184 return s.commands.iter().any(|wfc| {
185 matches!(
186 wfc,
187 WorkflowCommand {
188 variant: Some(workflow_command::Variant::CancelWorkflowExecution(
189 _
190 )),
191 ..
192 }
193 )
194 });
195 }
196 false
197 }
198
199 pub fn has_continue_as_new(&self) -> bool {
201 if let Some(workflow_activation_completion::Status::Successful(s)) = &self.status {
202 return s.commands.iter().any(|wfc| {
203 matches!(
204 wfc,
205 WorkflowCommand {
206 variant: Some(
207 workflow_command::Variant::ContinueAsNewWorkflowExecution(_)
208 ),
209 ..
210 }
211 )
212 });
213 }
214 false
215 }
216
217 pub fn has_complete_workflow_execution(&self) -> bool {
219 self.complete_workflow_execution_value().is_some()
220 }
221
222 pub fn complete_workflow_execution_value(&self) -> Option<&Payload> {
224 if let Some(workflow_activation_completion::Status::Successful(s)) = &self.status {
225 s.commands.iter().find_map(|wfc| match wfc {
226 WorkflowCommand {
227 variant: Some(workflow_command::Variant::CompleteWorkflowExecution(v)),
228 ..
229 } => v.result.as_ref(),
230 _ => None,
231 })
232 } else {
233 None
234 }
235 }
236
237 pub fn is_empty(&self) -> bool {
239 if let Some(workflow_activation_completion::Status::Successful(s)) = &self.status {
240 return s.commands.is_empty();
241 }
242 false
243 }
244
245 pub fn add_internal_flags(&mut self, patch: u32) {
246 if let Some(workflow_activation_completion::Status::Successful(s)) =
247 &mut self.status
248 {
249 s.used_internal_flags.push(patch);
250 }
251 }
252 }
253
254 pub trait IntoCompletion {
256 fn into_completion(self, run_id: String) -> WorkflowActivationCompletion;
258 }
259
260 impl IntoCompletion for workflow_command::Variant {
261 fn into_completion(self, run_id: String) -> WorkflowActivationCompletion {
262 WorkflowActivationCompletion::from_cmd(run_id, self)
263 }
264 }
265
266 impl<I, V> IntoCompletion for I
267 where
268 I: IntoIterator<Item = V>,
269 V: Into<WorkflowCommand>,
270 {
271 fn into_completion(self, run_id: String) -> WorkflowActivationCompletion {
272 let success = self.into_iter().map(Into::into).collect::<Vec<_>>().into();
273 WorkflowActivationCompletion {
274 run_id,
275 status: Some(workflow_activation_completion::Status::Successful(success)),
276 ..Default::default()
277 }
278 }
279 }
280
281 impl Display for WorkflowActivationCompletion {
282 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
283 write!(
284 f,
285 "WorkflowActivationCompletion(run_id: {}, status: ",
286 &self.run_id
287 )?;
288 match &self.status {
289 None => write!(f, "empty")?,
290 Some(s) => write!(f, "{s}")?,
291 };
292 write!(f, ")")
293 }
294 }
295
296 impl Display for workflow_activation_completion::Status {
297 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
298 match self {
299 workflow_activation_completion::Status::Successful(
300 workflow_completion::Success { commands, .. },
301 ) => {
302 write!(f, "Success(")?;
303 let mut written = 0;
304 for c in commands {
305 write!(f, "{c} ")?;
306 written += 1;
307 if written >= 10 && written < commands.len() {
308 write!(f, "... {} more", commands.len() - written)?;
309 break;
310 }
311 }
312 write!(f, ")")
313 }
314 workflow_activation_completion::Status::Failed(_) => {
315 write!(f, "Failed")
316 }
317 }
318 }
319 }
320
321 impl ActivityTask {
322 pub fn start_from_poll_resp(r: PollActivityTaskQueueResponse) -> Self {
323 let (workflow_id, run_id) = r
324 .workflow_execution
325 .map(|we| (we.workflow_id, we.run_id))
326 .unwrap_or_default();
327 Self {
328 task_token: r.task_token,
329 variant: Some(activity_task::activity_task::Variant::Start(
330 activity_task::Start {
331 workflow_namespace: r.workflow_namespace,
332 workflow_type: r
333 .workflow_type
334 .map_or_else(|| "".to_string(), |wt| wt.name),
335 workflow_execution: Some(WorkflowExecution {
336 workflow_id,
337 run_id,
338 }),
339 activity_id: r.activity_id,
340 activity_type: r
341 .activity_type
342 .map_or_else(|| "".to_string(), |at| at.name),
343 header_fields: r.header.map(Into::into).unwrap_or_default(),
344 input: Vec::from_payloads(r.input),
345 heartbeat_details: Vec::from_payloads(r.heartbeat_details),
346 scheduled_time: r.scheduled_time,
347 current_attempt_scheduled_time: r.current_attempt_scheduled_time,
348 started_time: r.started_time,
349 attempt: r.attempt as u32,
350 schedule_to_close_timeout: r.schedule_to_close_timeout,
351 start_to_close_timeout: r.start_to_close_timeout,
352 heartbeat_timeout: r.heartbeat_timeout,
353 retry_policy: r.retry_policy.map(fix_retry_policy),
354 priority: r.priority,
355 is_local: false,
356 run_id: r.activity_run_id,
357 },
358 )),
359 }
360 }
361 }
362
363 impl Failure {
364 pub fn is_timeout(
365 &self,
366 ) -> Option<crate::protos::temporal::api::enums::v1::TimeoutType> {
367 match &self.failure_info {
368 Some(FailureInfo::TimeoutFailureInfo(ti)) => Some(ti.timeout_type()),
369 _ => {
370 if let Some(c) = &self.cause {
371 c.is_timeout()
372 } else {
373 None
374 }
375 }
376 }
377 }
378
379 pub fn application_failure(message: String, non_retryable: bool) -> Self {
380 Self {
381 message,
382 failure_info: Some(FailureInfo::ApplicationFailureInfo(
383 ApplicationFailureInfo {
384 non_retryable,
385 ..Default::default()
386 },
387 )),
388 ..Default::default()
389 }
390 }
391
392 pub fn application_failure_from_error(ae: anyhow::Error, non_retryable: bool) -> Self {
393 Self {
394 failure_info: Some(FailureInfo::ApplicationFailureInfo(
395 ApplicationFailureInfo {
396 non_retryable,
397 ..Default::default()
398 },
399 )),
400 ..ae.chain()
401 .rfold(None, |cause, e| {
402 Some(Self {
403 message: e.to_string(),
404 cause: cause.map(Box::new),
405 ..Default::default()
406 })
407 })
408 .unwrap_or_default()
409 }
410 }
411
412 pub fn timeout(timeout_type: TimeoutType) -> Self {
413 Self {
414 message: "Activity timed out".to_string(),
415 cause: Some(Box::new(Failure {
416 message: "Activity timed out".to_string(),
417 failure_info: Some(FailureInfo::TimeoutFailureInfo(TimeoutFailureInfo {
418 timeout_type: timeout_type.into(),
419 ..Default::default()
420 })),
421 ..Default::default()
422 })),
423 failure_info: Some(FailureInfo::ActivityFailureInfo(
424 ActivityFailureInfo::default(),
425 )),
426 ..Default::default()
427 }
428 }
429
430 pub fn maybe_application_failure(&self) -> Option<&ApplicationFailureInfo> {
432 if let Failure {
433 failure_info: Some(FailureInfo::ApplicationFailureInfo(f)),
434 ..
435 } = self
436 {
437 Some(f)
438 } else {
439 None
440 }
441 }
442
443 pub fn is_benign_application_failure(&self) -> bool {
445 self.maybe_application_failure()
446 .is_some_and(|app_info| app_info.category() == ApplicationErrorCategory::Benign)
447 }
448 }
449
450 impl Display for Failure {
451 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
452 write!(f, "Failure({}, ", self.message)?;
453 match self.failure_info.as_ref() {
454 None => write!(f, "missing info")?,
455 Some(FailureInfo::TimeoutFailureInfo(v)) => {
456 write!(f, "Timeout: {:?}", v.timeout_type())?;
457 }
458 Some(FailureInfo::ApplicationFailureInfo(v)) => {
459 write!(f, "Application Failure: {}", v.r#type)?;
460 }
461 Some(FailureInfo::CanceledFailureInfo(_)) => {
462 write!(f, "Cancelled")?;
463 }
464 Some(FailureInfo::TerminatedFailureInfo(_)) => {
465 write!(f, "Terminated")?;
466 }
467 Some(FailureInfo::ServerFailureInfo(_)) => {
468 write!(f, "Server Failure")?;
469 }
470 Some(FailureInfo::ResetWorkflowFailureInfo(_)) => {
471 write!(f, "Reset Workflow")?;
472 }
473 Some(FailureInfo::ActivityFailureInfo(v)) => {
474 write!(
475 f,
476 "Activity Failure: scheduled_event_id: {}",
477 v.scheduled_event_id
478 )?;
479 }
480 Some(FailureInfo::ChildWorkflowExecutionFailureInfo(v)) => {
481 write!(
482 f,
483 "Child Workflow: started_event_id: {}",
484 v.started_event_id
485 )?;
486 }
487 Some(FailureInfo::NexusOperationExecutionFailureInfo(v)) => {
488 write!(
489 f,
490 "Nexus Operation Failure: scheduled_event_id: {}",
491 v.scheduled_event_id
492 )?;
493 }
494 Some(FailureInfo::NexusHandlerFailureInfo(v)) => {
495 write!(f, "Nexus Handler Failure: {}", v.r#type)?;
496 }
497 }
498 write!(f, ")")
499 }
500 }
501
502 impl From<&str> for Failure {
503 fn from(v: &str) -> Self {
504 Failure::application_failure(v.to_string(), false)
505 }
506 }
507
508 impl From<String> for Failure {
509 fn from(v: String) -> Self {
510 Failure::application_failure(v, false)
511 }
512 }
513
514 impl From<anyhow::Error> for Failure {
515 fn from(ae: anyhow::Error) -> Self {
516 Failure::application_failure_from_error(ae, false)
517 }
518 }
519
520 pub trait FromPayloadsExt {
521 fn from_payloads(p: Option<Payloads>) -> Self;
522 }
523 impl<T> FromPayloadsExt for T
524 where
525 T: FromIterator<Payload>,
526 {
527 fn from_payloads(p: Option<Payloads>) -> Self {
528 match p {
529 None => std::iter::empty().collect(),
530 Some(p) => p.payloads.into_iter().collect(),
531 }
532 }
533 }
534
535 pub trait IntoPayloadsExt {
536 fn into_payloads(self) -> Option<Payloads>;
537 }
538 impl<T> IntoPayloadsExt for T
539 where
540 T: IntoIterator<Item = Payload>,
541 {
542 fn into_payloads(self) -> Option<Payloads> {
543 let mut iterd = self.into_iter().peekable();
544 if iterd.peek().is_none() {
545 None
546 } else {
547 Some(Payloads {
548 payloads: iterd.collect(),
549 })
550 }
551 }
552 }
553
554 impl From<Payload> for Payloads {
555 fn from(p: Payload) -> Self {
556 Self { payloads: vec![p] }
557 }
558 }
559
560 impl<T> From<T> for Payloads
561 where
562 T: AsRef<[u8]>,
563 {
564 fn from(v: T) -> Self {
565 Self {
566 payloads: vec![v.into()],
567 }
568 }
569 }
570
571 #[derive(thiserror::Error, Debug)]
572 pub enum PayloadDeserializeErr {
573 #[error("This deserializer does not understand this payload")]
576 DeserializerDoesNotHandle,
577 #[error("Error during deserialization: {0}")]
578 DeserializeErr(#[from] anyhow::Error),
579 }
580
581 pub trait AsJsonPayloadExt {
584 fn as_json_payload(&self) -> anyhow::Result<Payload>;
585 }
586 impl<T> AsJsonPayloadExt for T
587 where
588 T: Serialize,
589 {
590 fn as_json_payload(&self) -> anyhow::Result<Payload> {
591 let as_json = serde_json::to_string(self)?;
592 let mut metadata = HashMap::new();
593 metadata.insert(
594 ENCODING_PAYLOAD_KEY.to_string(),
595 JSON_ENCODING_VAL.as_bytes().to_vec(),
596 );
597 Ok(Payload {
598 metadata,
599 data: as_json.into_bytes(),
600 external_payloads: Default::default(),
601 })
602 }
603 }
604
605 pub trait FromJsonPayloadExt: Sized {
606 fn from_json_payload(payload: &Payload) -> Result<Self, PayloadDeserializeErr>;
607 }
608 impl<T> FromJsonPayloadExt for T
609 where
610 T: for<'de> Deserialize<'de>,
611 {
612 fn from_json_payload(payload: &Payload) -> Result<Self, PayloadDeserializeErr> {
613 if !payload.is_json_payload() {
614 return Err(PayloadDeserializeErr::DeserializerDoesNotHandle);
615 }
616 let payload_str =
617 std::str::from_utf8(&payload.data).map_err(anyhow::Error::from)?;
618 Ok(serde_json::from_str(payload_str).map_err(anyhow::Error::from)?)
619 }
620 }
621
622 #[derive(derive_more::Display, Debug)]
624 pub enum PayloadsToPayloadError {
625 MoreThanOnePayload,
626 NoPayload,
627 }
628 impl TryFrom<Payloads> for Payload {
629 type Error = PayloadsToPayloadError;
630
631 fn try_from(mut v: Payloads) -> Result<Self, Self::Error> {
632 match v.payloads.pop() {
633 None => Err(PayloadsToPayloadError::NoPayload),
634 Some(p) => {
635 if v.payloads.is_empty() {
636 Ok(p)
637 } else {
638 Err(PayloadsToPayloadError::MoreThanOnePayload)
639 }
640 }
641 }
642 }
643 }
644
645 pub(super) fn fix_retry_policy(mut retry_policy: RetryPolicy) -> RetryPolicy {
648 if retry_policy.initial_interval.is_none() {
649 retry_policy.initial_interval = Default::default();
650 }
651 retry_policy
652 }
653 }
654 #[allow(clippy::module_inception)]
655 pub mod activity_task {
656 tonic::include_proto!("coresdk.activity_task");
657 mod sdk_helpers {
658 use super::*;
659 use crate::protos::{coresdk::ActivityTaskCompletion, task_token::format_task_token};
660 use std::fmt::{Display, Formatter};
661
662 impl ActivityTask {
663 pub fn cancel_from_ids(
664 task_token: Vec<u8>,
665 reason: ActivityCancelReason,
666 details: ActivityCancellationDetails,
667 ) -> Self {
668 Self {
669 task_token,
670 variant: Some(activity_task::Variant::Cancel(Cancel {
671 reason: reason as i32,
672 details: Some(details),
673 })),
674 }
675 }
676
677 pub fn is_timeout(&self) -> bool {
679 match &self.variant {
680 Some(activity_task::Variant::Cancel(Cancel { reason, details })) => {
681 *reason == ActivityCancelReason::TimedOut as i32
682 || details.as_ref().is_some_and(|d| d.is_timed_out)
683 }
684 _ => false,
685 }
686 }
687
688 pub fn primary_reason_to_cancellation_details(
689 reason: ActivityCancelReason,
690 ) -> ActivityCancellationDetails {
691 ActivityCancellationDetails {
692 is_not_found: reason == ActivityCancelReason::NotFound,
693 is_cancelled: reason == ActivityCancelReason::Cancelled,
694 is_paused: reason == ActivityCancelReason::Paused,
695 is_timed_out: reason == ActivityCancelReason::TimedOut,
696 is_worker_shutdown: reason == ActivityCancelReason::WorkerShutdown,
697 is_reset: reason == ActivityCancelReason::Reset,
698 }
699 }
700 }
701
702 impl Display for ActivityTaskCompletion {
703 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
704 write!(
705 f,
706 "ActivityTaskCompletion(token: {}",
707 format_task_token(&self.task_token),
708 )?;
709 if let Some(r) = self.result.as_ref().and_then(|r| r.status.as_ref()) {
710 write!(f, ", {r}")?;
711 } else {
712 write!(f, ", missing result")?;
713 }
714 write!(f, ")")
715 }
716 }
717 }
718 }
719 #[allow(clippy::module_inception)]
720 pub mod activity_result {
721 tonic::include_proto!("coresdk.activity_result");
722 mod sdk_helpers {
723 use super::*;
724 use crate::protos::{
725 coresdk::activity_result::activity_resolution::Status,
726 temporal::api::{
727 common::v1::Payload,
728 enums::v1::TimeoutType,
729 failure::v1::{CanceledFailureInfo, Failure as APIFailure, failure},
730 },
731 };
732 use activity_execution_result as aer;
733 use anyhow::anyhow;
734 use std::fmt::{Display, Formatter};
735
736 impl ActivityExecutionResult {
737 pub const fn ok(result: Payload) -> Self {
738 Self {
739 status: Some(aer::Status::Completed(Success {
740 result: Some(result),
741 })),
742 }
743 }
744
745 pub fn fail(fail: APIFailure) -> Self {
746 Self {
747 status: Some(aer::Status::Failed(Failure {
748 failure: Some(fail),
749 })),
750 }
751 }
752
753 pub fn cancel(fail: APIFailure) -> Self {
754 Self {
755 status: Some(aer::Status::Cancelled(Cancellation {
756 failure: Some(fail),
757 })),
758 }
759 }
760
761 pub fn cancel_from_details(payload: Option<Payload>) -> Self {
762 Self {
763 status: Some(aer::Status::Cancelled(Cancellation::from_details(payload))),
764 }
765 }
766
767 pub const fn will_complete_async() -> Self {
768 Self {
769 status: Some(aer::Status::WillCompleteAsync(WillCompleteAsync {})),
770 }
771 }
772
773 pub fn is_cancelled(&self) -> bool {
774 matches!(self.status, Some(aer::Status::Cancelled(_)))
775 }
776 }
777
778 impl Display for aer::Status {
779 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
780 write!(f, "ActivityExecutionResult(")?;
781 match self {
782 aer::Status::Completed(v) => {
783 write!(f, "{v})")
784 }
785 aer::Status::Failed(v) => {
786 write!(f, "{v})")
787 }
788 aer::Status::Cancelled(v) => {
789 write!(f, "{v})")
790 }
791 aer::Status::WillCompleteAsync(_) => {
792 write!(f, "Will complete async)")
793 }
794 }
795 }
796 }
797
798 impl Display for Success {
799 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
800 write!(f, "Success(")?;
801 if let Some(ref v) = self.result {
802 write!(f, "{v}")?;
803 }
804 write!(f, ")")
805 }
806 }
807
808 impl Display for Failure {
809 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
810 write!(f, "Failure(")?;
811 if let Some(ref v) = self.failure {
812 write!(f, "{v}")?;
813 }
814 write!(f, ")")
815 }
816 }
817
818 impl Display for Cancellation {
819 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
820 write!(f, "Cancellation(")?;
821 if let Some(ref v) = self.failure {
822 write!(f, "{v}")?;
823 }
824 write!(f, ")")
825 }
826 }
827
828 impl From<Result<Payload, APIFailure>> for ActivityExecutionResult {
829 fn from(r: Result<Payload, APIFailure>) -> Self {
830 Self {
831 status: match r {
832 Ok(p) => Some(aer::Status::Completed(Success { result: Some(p) })),
833 Err(f) => Some(aer::Status::Failed(Failure { failure: Some(f) })),
834 },
835 }
836 }
837 }
838
839 impl ActivityResolution {
840 pub fn success_payload_or_error(self) -> Result<Option<Payload>, anyhow::Error> {
843 let Some(status) = self.status else {
844 return Err(anyhow!("Activity completed without a status"));
845 };
846
847 match status {
848 activity_resolution::Status::Completed(success) => Ok(success.result),
849 e => Err(anyhow!("Activity was not successful: {e:?}")),
850 }
851 }
852
853 pub fn unwrap_ok_payload(self) -> Payload {
854 self.success_payload_or_error().unwrap().unwrap()
855 }
856
857 pub fn completed_ok(&self) -> bool {
858 matches!(self.status, Some(activity_resolution::Status::Completed(_)))
859 }
860
861 pub fn failed(&self) -> bool {
862 matches!(self.status, Some(activity_resolution::Status::Failed(_)))
863 }
864
865 pub fn timed_out(&self) -> Option<TimeoutType> {
866 match self.status {
867 Some(activity_resolution::Status::Failed(Failure {
868 failure: Some(ref f),
869 })) => f.is_timeout(),
870 _ => None,
871 }
872 }
873
874 pub fn cancelled(&self) -> bool {
875 matches!(self.status, Some(activity_resolution::Status::Cancelled(_)))
876 }
877
878 pub fn unwrap_failure(self) -> APIFailure {
881 match self.status.unwrap() {
882 Status::Failed(f) => f.failure.unwrap(),
883 Status::Cancelled(c) => c.failure.unwrap(),
884 _ => panic!("Actvity did not fail"),
885 }
886 }
887 }
888
889 impl Cancellation {
890 pub fn from_details(details: Option<Payload>) -> Self {
893 Cancellation {
894 failure: Some(APIFailure {
895 message: "Activity cancelled".to_string(),
896 failure_info: Some(failure::FailureInfo::CanceledFailureInfo(
897 CanceledFailureInfo {
898 details: details.map(Into::into),
899 identity: Default::default(),
900 },
901 )),
902 ..Default::default()
903 }),
904 }
905 }
906 }
907 }
908 }
909 pub mod common {
910 tonic::include_proto!("coresdk.common");
911 pub use self::sdk_helpers::*;
912 mod sdk_helpers {
913 use crate::protos::{
914 PATCHED_MARKER_DETAILS_KEY,
915 coresdk::{
916 AsJsonPayloadExt, FromJsonPayloadExt, IntoPayloadsExt,
917 external_data::{LocalActivityMarkerData, PatchedMarkerData},
918 },
919 temporal::api::common::v1::{Payload, Payloads},
920 };
921 use std::collections::HashMap;
922
923 pub fn build_has_change_marker_details(
924 patch_id: impl Into<String>,
925 deprecated: bool,
926 ) -> anyhow::Result<HashMap<String, Payloads>> {
927 let mut hm = HashMap::new();
928 let encoded = PatchedMarkerData {
929 id: patch_id.into(),
930 deprecated,
931 }
932 .as_json_payload()?;
933 hm.insert(PATCHED_MARKER_DETAILS_KEY.to_string(), encoded.into());
934 Ok(hm)
935 }
936
937 pub fn decode_change_marker_details(
938 details: &HashMap<String, Payloads>,
939 ) -> Option<(String, bool)> {
940 if let Some(cd) = details.get(PATCHED_MARKER_DETAILS_KEY) {
943 let decoded =
944 PatchedMarkerData::from_json_payload(cd.payloads.first()?).ok()?;
945 return Some((decoded.id, decoded.deprecated));
946 }
947
948 let id_entry = details.get("patch_id")?.payloads.first()?;
949 let deprecated_entry = details.get("deprecated")?.payloads.first()?;
950 let name = std::str::from_utf8(&id_entry.data).ok()?;
951 let deprecated = *deprecated_entry.data.first()? != 0;
952 Some((name.to_string(), deprecated))
953 }
954
955 pub fn build_local_activity_marker_details(
956 metadata: LocalActivityMarkerData,
957 result: Option<Payload>,
958 ) -> HashMap<String, Payloads> {
959 let mut hm = HashMap::new();
960 if let Some(jsonified) = metadata.as_json_payload().into_payloads() {
963 hm.insert("data".to_string(), jsonified);
964 }
965 if let Some(res) = result {
966 hm.insert("result".to_string(), res.into());
967 }
968 hm
969 }
970
971 pub fn extract_local_activity_marker_data(
974 details: &HashMap<String, Payloads>,
975 ) -> Option<LocalActivityMarkerData> {
976 details
977 .get("data")
978 .and_then(|p| p.payloads.first())
979 .and_then(|p| std::str::from_utf8(&p.data).ok())
980 .and_then(|s| serde_json::from_str(s).ok())
981 }
982
983 pub fn extract_local_activity_marker_details(
987 details: &mut HashMap<String, Payloads>,
988 ) -> (Option<LocalActivityMarkerData>, Option<Payload>) {
989 let data = extract_local_activity_marker_data(details);
990 let result = details.remove("result").and_then(|mut p| p.payloads.pop());
991 (data, result)
992 }
993 }
994 }
995 pub mod external_data {
996 tonic::include_proto!("coresdk.external_data");
997 mod sdk_helpers {
998 use prost_types::{Duration, Timestamp};
999 use serde::{Deserialize, Deserializer, Serialize, Serializer};
1000
1001 #[derive(Serialize, Deserialize)]
1005 #[serde(remote = "Timestamp")]
1006 struct TimestampDef {
1007 seconds: i64,
1008 nanos: i32,
1009 }
1010 pub(crate) mod opt_timestamp {
1011 use super::*;
1012
1013 pub(crate) fn serialize<S>(
1014 value: &Option<Timestamp>,
1015 serializer: S,
1016 ) -> Result<S::Ok, S::Error>
1017 where
1018 S: Serializer,
1019 {
1020 #[derive(Serialize)]
1021 struct Helper<'a>(#[serde(with = "TimestampDef")] &'a Timestamp);
1022
1023 value.as_ref().map(Helper).serialize(serializer)
1024 }
1025
1026 pub(crate) fn deserialize<'de, D>(
1027 deserializer: D,
1028 ) -> Result<Option<Timestamp>, D::Error>
1029 where
1030 D: Deserializer<'de>,
1031 {
1032 #[derive(Deserialize)]
1033 struct Helper(#[serde(with = "TimestampDef")] Timestamp);
1034
1035 let helper = Option::deserialize(deserializer)?;
1036 Ok(helper.map(|Helper(external)| external))
1037 }
1038 }
1039
1040 #[derive(Serialize, Deserialize)]
1042 #[serde(remote = "Duration")]
1043 struct DurationDef {
1044 seconds: i64,
1045 nanos: i32,
1046 }
1047 pub(crate) mod opt_duration {
1048 use super::*;
1049
1050 pub(crate) fn serialize<S>(
1051 value: &Option<Duration>,
1052 serializer: S,
1053 ) -> Result<S::Ok, S::Error>
1054 where
1055 S: Serializer,
1056 {
1057 #[derive(Serialize)]
1058 struct Helper<'a>(#[serde(with = "DurationDef")] &'a Duration);
1059
1060 value.as_ref().map(Helper).serialize(serializer)
1061 }
1062
1063 pub(crate) fn deserialize<'de, D>(
1064 deserializer: D,
1065 ) -> Result<Option<Duration>, D::Error>
1066 where
1067 D: Deserializer<'de>,
1068 {
1069 #[derive(Deserialize)]
1070 struct Helper(#[serde(with = "DurationDef")] Duration);
1071
1072 let helper = Option::deserialize(deserializer)?;
1073 Ok(helper.map(|Helper(external)| external))
1074 }
1075 }
1076 }
1077 }
1078 pub mod workflow_activation {
1079 tonic::include_proto!("coresdk.workflow_activation");
1080 pub use self::sdk_helpers::*;
1081 mod sdk_helpers {
1082 use super::*;
1083 use crate::protos::{
1084 coresdk::{
1085 FromPayloadsExt,
1086 activity_result::{ActivityResolution, activity_resolution},
1087 common::NamespacedWorkflowExecution,
1088 fix_retry_policy,
1089 workflow_activation::remove_from_cache::EvictionReason,
1090 },
1091 temporal::api::{
1092 enums::v1::WorkflowTaskFailedCause,
1093 history::v1::{
1094 WorkflowExecutionCancelRequestedEventAttributes,
1095 WorkflowExecutionSignaledEventAttributes,
1096 WorkflowExecutionStartedEventAttributes,
1097 },
1098 query::v1::WorkflowQuery,
1099 },
1100 };
1101 use prost_types::Timestamp;
1102 use std::fmt::{Display, Formatter};
1103
1104 pub fn create_evict_activation(
1105 run_id: String,
1106 message: String,
1107 reason: EvictionReason,
1108 ) -> WorkflowActivation {
1109 WorkflowActivation {
1110 timestamp: None,
1111 run_id,
1112 is_replaying: false,
1113 history_length: 0,
1114 jobs: vec![WorkflowActivationJob::from(
1115 workflow_activation_job::Variant::RemoveFromCache(RemoveFromCache {
1116 message,
1117 reason: reason as i32,
1118 }),
1119 )],
1120 available_internal_flags: vec![],
1121 history_size_bytes: 0,
1122 continue_as_new_suggested: false,
1123 deployment_version_for_current_task: None,
1124 last_sdk_version: String::new(),
1125 suggest_continue_as_new_reasons: vec![],
1126 target_worker_deployment_version_changed: false,
1127 }
1128 }
1129
1130 pub fn query_to_job(id: String, q: WorkflowQuery) -> QueryWorkflow {
1131 QueryWorkflow {
1132 query_id: id,
1133 query_type: q.query_type,
1134 arguments: Vec::from_payloads(q.query_args),
1135 headers: q.header.map(|h| h.into()).unwrap_or_default(),
1136 }
1137 }
1138
1139 impl WorkflowActivation {
1140 pub fn is_only_eviction(&self) -> bool {
1142 matches!(
1143 self.jobs.as_slice(),
1144 [WorkflowActivationJob {
1145 variant: Some(workflow_activation_job::Variant::RemoveFromCache(_))
1146 }]
1147 )
1148 }
1149
1150 pub fn eviction_reason(&self) -> Option<EvictionReason> {
1152 self.jobs.iter().find_map(|j| {
1153 if let Some(workflow_activation_job::Variant::RemoveFromCache(ref rj)) =
1154 j.variant
1155 {
1156 EvictionReason::try_from(rj.reason).ok()
1157 } else {
1158 None
1159 }
1160 })
1161 }
1162 }
1163
1164 impl workflow_activation_job::Variant {
1165 pub fn is_local_activity_resolution(&self) -> bool {
1166 matches!(self, workflow_activation_job::Variant::ResolveActivity(ra) if ra.is_local)
1167 }
1168 }
1169
1170 impl Display for EvictionReason {
1171 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1172 write!(f, "{self:?}")
1173 }
1174 }
1175
1176 impl From<EvictionReason> for WorkflowTaskFailedCause {
1177 fn from(value: EvictionReason) -> Self {
1178 match value {
1179 EvictionReason::Nondeterminism => {
1180 WorkflowTaskFailedCause::NonDeterministicError
1181 }
1182 _ => WorkflowTaskFailedCause::Unspecified,
1183 }
1184 }
1185 }
1186
1187 impl Display for WorkflowActivation {
1188 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1189 write!(f, "WorkflowActivation(")?;
1190 write!(f, "run_id: {}, ", self.run_id)?;
1191 write!(f, "is_replaying: {}, ", self.is_replaying)?;
1192 write!(
1193 f,
1194 "jobs: {})",
1195 self.jobs
1196 .iter()
1197 .map(ToString::to_string)
1198 .collect::<Vec<_>>()
1199 .as_slice()
1200 .join(", ")
1201 )
1202 }
1203 }
1204
1205 impl Display for WorkflowActivationJob {
1206 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1207 match &self.variant {
1208 None => write!(f, "empty"),
1209 Some(v) => write!(f, "{v}"),
1210 }
1211 }
1212 }
1213
1214 impl Display for workflow_activation_job::Variant {
1215 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1216 match self {
1217 workflow_activation_job::Variant::InitializeWorkflow(_) => {
1218 write!(f, "InitializeWorkflow")
1219 }
1220 workflow_activation_job::Variant::FireTimer(t) => {
1221 write!(f, "FireTimer({})", t.seq)
1222 }
1223 workflow_activation_job::Variant::UpdateRandomSeed(_) => {
1224 write!(f, "UpdateRandomSeed")
1225 }
1226 workflow_activation_job::Variant::QueryWorkflow(_) => {
1227 write!(f, "QueryWorkflow")
1228 }
1229 workflow_activation_job::Variant::CancelWorkflow(_) => {
1230 write!(f, "CancelWorkflow")
1231 }
1232 workflow_activation_job::Variant::SignalWorkflow(_) => {
1233 write!(f, "SignalWorkflow")
1234 }
1235 workflow_activation_job::Variant::ResolveActivity(r) => {
1236 write!(
1237 f,
1238 "ResolveActivity({}, {})",
1239 r.seq,
1240 r.result
1241 .as_ref()
1242 .unwrap_or(&ActivityResolution { status: None })
1243 )
1244 }
1245 workflow_activation_job::Variant::NotifyHasPatch(_) => {
1246 write!(f, "NotifyHasPatch")
1247 }
1248 workflow_activation_job::Variant::ResolveChildWorkflowExecutionStart(_) => {
1249 write!(f, "ResolveChildWorkflowExecutionStart")
1250 }
1251 workflow_activation_job::Variant::ResolveChildWorkflowExecution(_) => {
1252 write!(f, "ResolveChildWorkflowExecution")
1253 }
1254 workflow_activation_job::Variant::ResolveSignalExternalWorkflow(_) => {
1255 write!(f, "ResolveSignalExternalWorkflow")
1256 }
1257 workflow_activation_job::Variant::RemoveFromCache(_) => {
1258 write!(f, "RemoveFromCache")
1259 }
1260 workflow_activation_job::Variant::ResolveRequestCancelExternalWorkflow(
1261 _,
1262 ) => {
1263 write!(f, "ResolveRequestCancelExternalWorkflow")
1264 }
1265 workflow_activation_job::Variant::DoUpdate(u) => {
1266 write!(f, "DoUpdate({})", u.id)
1267 }
1268 workflow_activation_job::Variant::ResolveNexusOperationStart(_) => {
1269 write!(f, "ResolveNexusOperationStart")
1270 }
1271 workflow_activation_job::Variant::ResolveNexusOperation(_) => {
1272 write!(f, "ResolveNexusOperation")
1273 }
1274 }
1275 }
1276 }
1277
1278 impl Display for ActivityResolution {
1279 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1280 match self.status {
1281 None => {
1282 write!(f, "None")
1283 }
1284 Some(activity_resolution::Status::Failed(_)) => {
1285 write!(f, "Failed")
1286 }
1287 Some(activity_resolution::Status::Completed(_)) => {
1288 write!(f, "Completed")
1289 }
1290 Some(activity_resolution::Status::Cancelled(_)) => {
1291 write!(f, "Cancelled")
1292 }
1293 Some(activity_resolution::Status::Backoff(_)) => {
1294 write!(f, "Backoff")
1295 }
1296 }
1297 }
1298 }
1299
1300 impl Display for QueryWorkflow {
1301 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1302 write!(
1303 f,
1304 "QueryWorkflow(id: {}, type: {})",
1305 self.query_id, self.query_type
1306 )
1307 }
1308 }
1309
1310 impl From<(WorkflowExecutionSignaledEventAttributes, i64)> for SignalWorkflow {
1311 fn from(
1312 (a, originating_event_id): (WorkflowExecutionSignaledEventAttributes, i64),
1313 ) -> Self {
1314 Self {
1315 signal_name: a.signal_name,
1316 input: Vec::from_payloads(a.input),
1317 identity: a.identity,
1318 headers: a.header.map(Into::into).unwrap_or_default(),
1319 originating_event_id,
1320 }
1321 }
1322 }
1323
1324 impl From<WorkflowExecutionCancelRequestedEventAttributes> for CancelWorkflow {
1325 fn from(a: WorkflowExecutionCancelRequestedEventAttributes) -> Self {
1326 Self { reason: a.cause }
1327 }
1328 }
1329
1330 pub fn start_workflow_from_attribs(
1332 attrs: WorkflowExecutionStartedEventAttributes,
1333 workflow_id: String,
1334 randomness_seed: u64,
1335 start_time: Timestamp,
1336 originating_event_id: i64,
1337 ) -> InitializeWorkflow {
1338 InitializeWorkflow {
1339 workflow_type: attrs.workflow_type.map(|wt| wt.name).unwrap_or_default(),
1340 workflow_id,
1341 arguments: Vec::from_payloads(attrs.input),
1342 randomness_seed,
1343 headers: attrs.header.unwrap_or_default().fields,
1344 identity: attrs.identity,
1345 parent_workflow_info: attrs.parent_workflow_execution.map(|pe| {
1346 NamespacedWorkflowExecution {
1347 namespace: attrs.parent_workflow_namespace,
1348 run_id: pe.run_id,
1349 workflow_id: pe.workflow_id,
1350 }
1351 }),
1352 workflow_execution_timeout: attrs.workflow_execution_timeout,
1353 workflow_run_timeout: attrs.workflow_run_timeout,
1354 workflow_task_timeout: attrs.workflow_task_timeout,
1355 continued_from_execution_run_id: attrs.continued_execution_run_id,
1356 continued_initiator: attrs.initiator,
1357 continued_failure: attrs.continued_failure,
1358 last_completion_result: attrs.last_completion_result,
1359 first_execution_run_id: attrs.first_execution_run_id,
1360 retry_policy: attrs.retry_policy.map(fix_retry_policy),
1361 attempt: attrs.attempt,
1362 cron_schedule: attrs.cron_schedule,
1363 workflow_execution_expiration_time: attrs.workflow_execution_expiration_time,
1364 cron_schedule_to_schedule_interval: attrs.first_workflow_task_backoff,
1365 memo: attrs.memo,
1366 search_attributes: attrs.search_attributes,
1367 start_time: Some(start_time),
1368 root_workflow: attrs.root_workflow_execution,
1369 priority: attrs.priority,
1370 originating_event_id,
1371 original_execution_run_id: attrs.original_execution_run_id,
1372 }
1373 }
1374 }
1375 }
1376 pub mod workflow_completion {
1377 tonic::include_proto!("coresdk.workflow_completion");
1378 mod sdk_helpers {
1379 use super::*;
1380 use crate::protos::temporal::api::{enums::v1::WorkflowTaskFailedCause, failure};
1381
1382 impl workflow_activation_completion::Status {
1383 pub const fn is_success(&self) -> bool {
1384 match &self {
1385 Self::Successful(_) => true,
1386 Self::Failed(_) => false,
1387 }
1388 }
1389 }
1390
1391 impl From<failure::v1::Failure> for Failure {
1392 fn from(f: failure::v1::Failure) -> Self {
1393 Failure {
1394 failure: Some(f),
1395 force_cause: WorkflowTaskFailedCause::Unspecified as i32,
1396 }
1397 }
1398 }
1399 }
1400 }
1401 pub mod child_workflow {
1402 tonic::include_proto!("coresdk.child_workflow");
1403 }
1404 pub mod nexus {
1405 tonic::include_proto!("coresdk.nexus");
1406 pub use self::sdk_helpers::*;
1407 mod sdk_helpers {
1408 use super::*;
1409 use crate::protos::temporal::api::workflowservice::v1::PollNexusTaskQueueResponse;
1410 use std::fmt::{Display, Formatter};
1411
1412 impl NexusTask {
1413 pub fn unwrap_task(self) -> PollNexusTaskQueueResponse {
1415 if let Some(nexus_task::Variant::Task(t)) = self.variant {
1416 return t;
1417 }
1418 panic!("Nexus task did not contain a server task");
1419 }
1420
1421 pub fn task_token(&self) -> &[u8] {
1423 match &self.variant {
1424 Some(nexus_task::Variant::Task(t)) => t.task_token.as_slice(),
1425 Some(nexus_task::Variant::CancelTask(c)) => c.task_token.as_slice(),
1426 None => panic!("Nexus task did not contain a task token"),
1427 }
1428 }
1429 }
1430
1431 impl Display for nexus_task_completion::Status {
1432 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1433 write!(f, "NexusTaskCompletion(")?;
1434 match self {
1435 nexus_task_completion::Status::Completed(c) => {
1436 write!(f, "{c}")
1437 }
1438 nexus_task_completion::Status::AckCancel(_) => {
1439 write!(f, "AckCancel")
1440 }
1441 #[allow(deprecated)]
1442 nexus_task_completion::Status::Error(error) => {
1443 write!(f, "Error({error:?})")
1444 }
1445 nexus_task_completion::Status::Failure(failure) => {
1446 write!(f, "{failure}")
1447 }
1448 }?;
1449 write!(f, ")")
1450 }
1451 }
1452
1453 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
1454 pub enum NexusOperationErrorState {
1455 Failed,
1456 Canceled,
1457 }
1458
1459 impl Display for NexusOperationErrorState {
1460 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1461 match self {
1462 Self::Failed => write!(f, "failed"),
1463 Self::Canceled => write!(f, "canceled"),
1464 }
1465 }
1466 }
1467 }
1468 }
1469 pub mod workflow_commands {
1470 tonic::include_proto!("coresdk.workflow_commands");
1471 mod sdk_helpers {
1472 use super::*;
1473 use crate::protos::temporal::api::{common::v1::Payloads, enums::v1::QueryResultType};
1474 use std::fmt::{Display, Formatter};
1475
1476 impl Display for WorkflowCommand {
1477 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1478 match &self.variant {
1479 None => write!(f, "Empty"),
1480 Some(v) => write!(f, "{v}"),
1481 }
1482 }
1483 }
1484
1485 impl Display for StartTimer {
1486 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1487 write!(f, "StartTimer({})", self.seq)
1488 }
1489 }
1490
1491 impl Display for ScheduleActivity {
1492 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1493 write!(f, "ScheduleActivity({}, {})", self.seq, self.activity_type)
1494 }
1495 }
1496
1497 impl Display for ScheduleLocalActivity {
1498 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1499 write!(
1500 f,
1501 "ScheduleLocalActivity({}, {})",
1502 self.seq, self.activity_type
1503 )
1504 }
1505 }
1506
1507 impl Display for QueryResult {
1508 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1509 write!(f, "RespondToQuery({})", self.query_id)
1510 }
1511 }
1512
1513 impl Display for RequestCancelActivity {
1514 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1515 write!(f, "RequestCancelActivity({})", self.seq)
1516 }
1517 }
1518
1519 impl Display for RequestCancelLocalActivity {
1520 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1521 write!(f, "RequestCancelLocalActivity({})", self.seq)
1522 }
1523 }
1524
1525 impl Display for CancelTimer {
1526 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1527 write!(f, "CancelTimer({})", self.seq)
1528 }
1529 }
1530
1531 impl Display for CompleteWorkflowExecution {
1532 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1533 write!(f, "CompleteWorkflowExecution")
1534 }
1535 }
1536
1537 impl Display for FailWorkflowExecution {
1538 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1539 write!(f, "FailWorkflowExecution")
1540 }
1541 }
1542
1543 impl Display for ContinueAsNewWorkflowExecution {
1544 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1545 write!(f, "ContinueAsNewWorkflowExecution")
1546 }
1547 }
1548
1549 impl Display for CancelWorkflowExecution {
1550 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1551 write!(f, "CancelWorkflowExecution")
1552 }
1553 }
1554
1555 impl Display for SetPatchMarker {
1556 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1557 write!(f, "SetPatchMarker({})", self.patch_id)
1558 }
1559 }
1560
1561 impl Display for StartChildWorkflowExecution {
1562 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1563 write!(
1564 f,
1565 "StartChildWorkflowExecution({}, {})",
1566 self.seq, self.workflow_type
1567 )
1568 }
1569 }
1570
1571 impl Display for RequestCancelExternalWorkflowExecution {
1572 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1573 write!(f, "RequestCancelExternalWorkflowExecution({})", self.seq)
1574 }
1575 }
1576
1577 impl Display for UpsertWorkflowSearchAttributes {
1578 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1579 let keys: Vec<_> = self
1580 .search_attributes
1581 .as_ref()
1582 .map(|sa| sa.indexed_fields.keys().collect())
1583 .unwrap_or_default();
1584 write!(f, "UpsertWorkflowSearchAttributes({:?})", keys)
1585 }
1586 }
1587
1588 impl Display for SignalExternalWorkflowExecution {
1589 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1590 write!(f, "SignalExternalWorkflowExecution({})", self.seq)
1591 }
1592 }
1593
1594 impl Display for CancelSignalWorkflow {
1595 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1596 write!(f, "CancelSignalWorkflow({})", self.seq)
1597 }
1598 }
1599
1600 impl Display for CancelChildWorkflowExecution {
1601 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1602 write!(
1603 f,
1604 "CancelChildWorkflowExecution({})",
1605 self.child_workflow_seq
1606 )
1607 }
1608 }
1609
1610 impl Display for ModifyWorkflowProperties {
1611 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1612 write!(
1613 f,
1614 "ModifyWorkflowProperties(upserted memo keys: {:?})",
1615 self.upserted_memo.as_ref().map(|m| m.fields.keys())
1616 )
1617 }
1618 }
1619
1620 impl Display for UpdateResponse {
1621 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1622 write!(
1623 f,
1624 "UpdateResponse(protocol_instance_id: {}, response: {:?})",
1625 self.protocol_instance_id, self.response
1626 )
1627 }
1628 }
1629
1630 impl Display for ScheduleNexusOperation {
1631 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1632 write!(f, "ScheduleNexusOperation({})", self.seq)
1633 }
1634 }
1635
1636 impl Display for RequestCancelNexusOperation {
1637 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1638 write!(f, "RequestCancelNexusOperation({})", self.seq)
1639 }
1640 }
1641
1642 impl QueryResult {
1643 pub fn into_components(
1645 self,
1646 ) -> (String, QueryResultType, Option<Payloads>, String) {
1647 match self {
1648 QueryResult {
1649 variant: Some(query_result::Variant::Succeeded(qs)),
1650 query_id,
1651 } => (
1652 query_id,
1653 QueryResultType::Answered,
1654 qs.response.map(Into::into),
1655 "".to_string(),
1656 ),
1657 QueryResult {
1658 variant: Some(query_result::Variant::Failed(err)),
1659 query_id,
1660 } => (query_id, QueryResultType::Failed, None, err.message),
1661 QueryResult {
1662 variant: None,
1663 query_id,
1664 } => (
1665 query_id,
1666 QueryResultType::Failed,
1667 None,
1668 "Query response was empty".to_string(),
1669 ),
1670 }
1671 }
1672 }
1673 }
1674 }
1675}
1676
1677#[allow(
1679 clippy::all,
1680 missing_docs,
1681 rustdoc::broken_intra_doc_links,
1682 rustdoc::bare_urls
1683)]
1684pub mod temporal {
1686 pub mod api {
1687 pub mod activity {
1688 pub mod v1 {
1689 tonic::include_proto!("temporal.api.activity.v1");
1690 }
1691 }
1692 pub mod batch {
1693 pub mod v1 {
1694 tonic::include_proto!("temporal.api.batch.v1");
1695 }
1696 }
1697 pub mod callback {
1698 pub mod v1 {
1699 tonic::include_proto!("temporal.api.callback.v1");
1700 }
1701 }
1702 pub mod command {
1703 pub mod v1 {
1704 tonic::include_proto!("temporal.api.command.v1");
1705 pub use self::sdk_helpers::*;
1706 mod sdk_helpers {
1707 use super::*;
1708 use crate::protos::{
1709 coresdk::{IntoPayloadsExt, workflow_commands},
1710 temporal::api::{
1711 common::v1::{ActivityType, WorkflowType},
1712 enums::v1::CommandType,
1713 },
1714 };
1715 use command::Attributes;
1716 use std::fmt::{Display, Formatter};
1717
1718 impl From<command::Attributes> for Command {
1719 fn from(c: command::Attributes) -> Self {
1720 match c {
1721 a @ Attributes::StartTimerCommandAttributes(_) => Self {
1722 command_type: CommandType::StartTimer as i32,
1723 attributes: Some(a),
1724 user_metadata: Default::default(),
1725 event_group_markers: Default::default(),
1726 },
1727 a @ Attributes::CancelTimerCommandAttributes(_) => Self {
1728 command_type: CommandType::CancelTimer as i32,
1729 attributes: Some(a),
1730 user_metadata: Default::default(),
1731 event_group_markers: Default::default(),
1732 },
1733 a @ Attributes::CompleteWorkflowExecutionCommandAttributes(_) => {
1734 Self {
1735 command_type: CommandType::CompleteWorkflowExecution as i32,
1736 attributes: Some(a),
1737 user_metadata: Default::default(),
1738 event_group_markers: Default::default(),
1739 }
1740 }
1741 a @ Attributes::FailWorkflowExecutionCommandAttributes(_) => Self {
1742 command_type: CommandType::FailWorkflowExecution as i32,
1743 attributes: Some(a),
1744 user_metadata: Default::default(),
1745 event_group_markers: Default::default(),
1746 },
1747 a @ Attributes::ScheduleActivityTaskCommandAttributes(_) => Self {
1748 command_type: CommandType::ScheduleActivityTask as i32,
1749 attributes: Some(a),
1750 user_metadata: Default::default(),
1751 event_group_markers: Default::default(),
1752 },
1753 a @ Attributes::RequestCancelActivityTaskCommandAttributes(_) => {
1754 Self {
1755 command_type: CommandType::RequestCancelActivityTask as i32,
1756 attributes: Some(a),
1757 user_metadata: Default::default(),
1758 event_group_markers: Default::default(),
1759 }
1760 }
1761 a
1762 @ Attributes::ContinueAsNewWorkflowExecutionCommandAttributes(
1763 _,
1764 ) => Self {
1765 command_type: CommandType::ContinueAsNewWorkflowExecution
1766 as i32,
1767 attributes: Some(a),
1768 user_metadata: Default::default(),
1769 event_group_markers: Default::default(),
1770 },
1771 a @ Attributes::CancelWorkflowExecutionCommandAttributes(_) => {
1772 Self {
1773 command_type: CommandType::CancelWorkflowExecution as i32,
1774 attributes: Some(a),
1775 user_metadata: Default::default(),
1776 event_group_markers: Default::default(),
1777 }
1778 }
1779 a @ Attributes::RecordMarkerCommandAttributes(_) => Self {
1780 command_type: CommandType::RecordMarker as i32,
1781 attributes: Some(a),
1782 user_metadata: Default::default(),
1783 event_group_markers: Default::default(),
1784 },
1785 a @ Attributes::ProtocolMessageCommandAttributes(_) => Self {
1786 command_type: CommandType::ProtocolMessage as i32,
1787 attributes: Some(a),
1788 user_metadata: Default::default(),
1789 event_group_markers: Default::default(),
1790 },
1791 a @ Attributes::RequestCancelNexusOperationCommandAttributes(_) => {
1792 Self {
1793 command_type: CommandType::RequestCancelNexusOperation
1794 as i32,
1795 attributes: Some(a),
1796 user_metadata: Default::default(),
1797 event_group_markers: Default::default(),
1798 }
1799 }
1800 _ => unimplemented!(),
1801 }
1802 }
1803 }
1804
1805 impl Display for Command {
1806 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1807 let ct = CommandType::try_from(self.command_type)
1808 .unwrap_or(CommandType::Unspecified);
1809 write!(f, "{:?}", ct)
1810 }
1811 }
1812
1813 pub trait CommandAttributesExt {
1814 fn as_type(&self) -> CommandType;
1815 }
1816
1817 impl CommandAttributesExt for command::Attributes {
1818 fn as_type(&self) -> CommandType {
1819 match self {
1820 Attributes::ScheduleActivityTaskCommandAttributes(_) => {
1821 CommandType::ScheduleActivityTask
1822 }
1823 Attributes::StartTimerCommandAttributes(_) => CommandType::StartTimer,
1824 Attributes::CompleteWorkflowExecutionCommandAttributes(_) => {
1825 CommandType::CompleteWorkflowExecution
1826 }
1827 Attributes::FailWorkflowExecutionCommandAttributes(_) => {
1828 CommandType::FailWorkflowExecution
1829 }
1830 Attributes::RequestCancelActivityTaskCommandAttributes(_) => {
1831 CommandType::RequestCancelActivityTask
1832 }
1833 Attributes::CancelTimerCommandAttributes(_) => CommandType::CancelTimer,
1834 Attributes::CancelWorkflowExecutionCommandAttributes(_) => {
1835 CommandType::CancelWorkflowExecution
1836 }
1837 Attributes::RequestCancelExternalWorkflowExecutionCommandAttributes(
1838 _,
1839 ) => CommandType::RequestCancelExternalWorkflowExecution,
1840 Attributes::RecordMarkerCommandAttributes(_) => {
1841 CommandType::RecordMarker
1842 }
1843 Attributes::ContinueAsNewWorkflowExecutionCommandAttributes(_) => {
1844 CommandType::ContinueAsNewWorkflowExecution
1845 }
1846 Attributes::StartChildWorkflowExecutionCommandAttributes(_) => {
1847 CommandType::StartChildWorkflowExecution
1848 }
1849 Attributes::SignalExternalWorkflowExecutionCommandAttributes(_) => {
1850 CommandType::SignalExternalWorkflowExecution
1851 }
1852 Attributes::UpsertWorkflowSearchAttributesCommandAttributes(_) => {
1853 CommandType::UpsertWorkflowSearchAttributes
1854 }
1855 Attributes::ProtocolMessageCommandAttributes(_) => {
1856 CommandType::ProtocolMessage
1857 }
1858 Attributes::ModifyWorkflowPropertiesCommandAttributes(_) => {
1859 CommandType::ModifyWorkflowProperties
1860 }
1861 Attributes::ScheduleNexusOperationCommandAttributes(_) => {
1862 CommandType::ScheduleNexusOperation
1863 }
1864 Attributes::RequestCancelNexusOperationCommandAttributes(_) => {
1865 CommandType::RequestCancelNexusOperation
1866 }
1867 }
1868 }
1869 }
1870
1871 impl Display for command::Attributes {
1872 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1873 write!(f, "{:?}", self.as_type())
1874 }
1875 }
1876
1877 impl From<workflow_commands::StartTimer> for command::Attributes {
1878 fn from(s: workflow_commands::StartTimer) -> Self {
1879 Self::StartTimerCommandAttributes(StartTimerCommandAttributes {
1880 timer_id: s.seq.to_string(),
1881 start_to_fire_timeout: s.start_to_fire_timeout,
1882 })
1883 }
1884 }
1885
1886 impl From<workflow_commands::UpsertWorkflowSearchAttributes> for command::Attributes {
1887 fn from(s: workflow_commands::UpsertWorkflowSearchAttributes) -> Self {
1888 Self::UpsertWorkflowSearchAttributesCommandAttributes(
1889 UpsertWorkflowSearchAttributesCommandAttributes {
1890 search_attributes: s.search_attributes,
1891 },
1892 )
1893 }
1894 }
1895
1896 impl From<workflow_commands::ModifyWorkflowProperties> for command::Attributes {
1897 fn from(s: workflow_commands::ModifyWorkflowProperties) -> Self {
1898 Self::ModifyWorkflowPropertiesCommandAttributes(
1899 ModifyWorkflowPropertiesCommandAttributes {
1900 upserted_memo: s.upserted_memo.map(Into::into),
1901 },
1902 )
1903 }
1904 }
1905
1906 impl From<workflow_commands::CancelTimer> for command::Attributes {
1907 fn from(s: workflow_commands::CancelTimer) -> Self {
1908 Self::CancelTimerCommandAttributes(CancelTimerCommandAttributes {
1909 timer_id: s.seq.to_string(),
1910 })
1911 }
1912 }
1913
1914 pub fn schedule_activity_cmd_to_api(
1915 s: workflow_commands::ScheduleActivity,
1916 use_workflow_build_id: bool,
1917 ) -> command::Attributes {
1918 command::Attributes::ScheduleActivityTaskCommandAttributes(
1919 ScheduleActivityTaskCommandAttributes {
1920 activity_id: s.activity_id,
1921 activity_type: Some(ActivityType {
1922 name: s.activity_type,
1923 }),
1924 task_queue: Some(s.task_queue.into()),
1925 header: Some(s.headers.into()),
1926 input: s.arguments.into_payloads(),
1927 schedule_to_close_timeout: s.schedule_to_close_timeout,
1928 schedule_to_start_timeout: s.schedule_to_start_timeout,
1929 start_to_close_timeout: s.start_to_close_timeout,
1930 heartbeat_timeout: s.heartbeat_timeout,
1931 retry_policy: s.retry_policy.map(Into::into),
1932 request_eager_execution: !s.do_not_eagerly_execute,
1933 use_workflow_build_id,
1934 priority: s.priority,
1935 },
1936 )
1937 }
1938
1939 #[allow(deprecated)]
1940 pub fn start_child_workflow_cmd_to_api(
1941 s: workflow_commands::StartChildWorkflowExecution,
1942 inherit_build_id: bool,
1943 ) -> command::Attributes {
1944 command::Attributes::StartChildWorkflowExecutionCommandAttributes(
1945 StartChildWorkflowExecutionCommandAttributes {
1946 workflow_id: s.workflow_id,
1947 workflow_type: Some(WorkflowType {
1948 name: s.workflow_type,
1949 }),
1950 control: "".into(),
1951 namespace: s.namespace,
1952 task_queue: Some(s.task_queue.into()),
1953 header: Some(s.headers.into()),
1954 memo: Some(s.memo.into()),
1955 search_attributes: s.search_attributes,
1956 input: s.input.into_payloads(),
1957 workflow_id_reuse_policy: s.workflow_id_reuse_policy,
1958 workflow_execution_timeout: s.workflow_execution_timeout,
1959 workflow_run_timeout: s.workflow_run_timeout,
1960 workflow_task_timeout: s.workflow_task_timeout,
1961 retry_policy: s.retry_policy.map(Into::into),
1962 cron_schedule: s.cron_schedule.clone(),
1963 parent_close_policy: s.parent_close_policy,
1964 inherit_build_id,
1965 priority: s.priority,
1966 versioning_override: None,
1967 },
1968 )
1969 }
1970
1971 impl From<workflow_commands::CompleteWorkflowExecution> for command::Attributes {
1972 fn from(c: workflow_commands::CompleteWorkflowExecution) -> Self {
1973 Self::CompleteWorkflowExecutionCommandAttributes(
1974 CompleteWorkflowExecutionCommandAttributes {
1975 result: c.result.map(Into::into),
1976 },
1977 )
1978 }
1979 }
1980
1981 impl From<workflow_commands::FailWorkflowExecution> for command::Attributes {
1982 fn from(c: workflow_commands::FailWorkflowExecution) -> Self {
1983 Self::FailWorkflowExecutionCommandAttributes(
1984 FailWorkflowExecutionCommandAttributes {
1985 failure: c.failure.map(Into::into),
1986 },
1987 )
1988 }
1989 }
1990
1991 #[allow(deprecated)]
1992 pub fn continue_as_new_cmd_to_api(
1993 c: workflow_commands::ContinueAsNewWorkflowExecution,
1994 inherit_build_id: bool,
1995 ) -> command::Attributes {
1996 command::Attributes::ContinueAsNewWorkflowExecutionCommandAttributes(
1997 ContinueAsNewWorkflowExecutionCommandAttributes {
1998 workflow_type: Some(c.workflow_type.into()),
1999 task_queue: Some(c.task_queue.into()),
2000 input: c.arguments.into_payloads(),
2001 workflow_run_timeout: c.workflow_run_timeout,
2002 workflow_task_timeout: c.workflow_task_timeout,
2003 memo: if c.memo.is_empty() {
2004 None
2005 } else {
2006 Some(c.memo.into())
2007 },
2008 header: if c.headers.is_empty() {
2009 None
2010 } else {
2011 Some(c.headers.into())
2012 },
2013 retry_policy: c.retry_policy,
2014 search_attributes: c.search_attributes,
2015 backoff_start_interval: c.backoff_start_interval,
2016 inherit_build_id,
2017 initial_versioning_behavior: c.initial_versioning_behavior,
2018 ..Default::default()
2019 },
2020 )
2021 }
2022
2023 impl From<workflow_commands::CancelWorkflowExecution> for command::Attributes {
2024 fn from(_c: workflow_commands::CancelWorkflowExecution) -> Self {
2025 Self::CancelWorkflowExecutionCommandAttributes(
2026 CancelWorkflowExecutionCommandAttributes { details: None },
2027 )
2028 }
2029 }
2030
2031 impl From<workflow_commands::ScheduleNexusOperation> for command::Attributes {
2032 fn from(c: workflow_commands::ScheduleNexusOperation) -> Self {
2033 Self::ScheduleNexusOperationCommandAttributes(
2034 ScheduleNexusOperationCommandAttributes {
2035 endpoint: c.endpoint,
2036 service: c.service,
2037 operation: c.operation,
2038 input: c.input,
2039 schedule_to_close_timeout: c.schedule_to_close_timeout,
2040 schedule_to_start_timeout: c.schedule_to_start_timeout,
2041 start_to_close_timeout: c.start_to_close_timeout,
2042 nexus_header: c.nexus_header,
2043 },
2044 )
2045 }
2046 }
2047 }
2048 }
2049 }
2050 #[allow(rustdoc::invalid_html_tags)]
2051 pub mod cloud {
2052 pub mod account {
2053 pub mod v1 {
2054 tonic::include_proto!("temporal.api.cloud.account.v1");
2055 }
2056 }
2057 pub mod auditlog {
2058 pub mod v1 {
2059 tonic::include_proto!("temporal.api.cloud.auditlog.v1");
2060 }
2061 }
2062 pub mod billing {
2063 pub mod v1 {
2064 tonic::include_proto!("temporal.api.cloud.billing.v1");
2065 }
2066 }
2067 pub mod cloudservice {
2068 pub mod v1 {
2069 tonic::include_proto!("temporal.api.cloud.cloudservice.v1");
2070 }
2071 }
2072 pub mod connectivityrule {
2073 pub mod v1 {
2074 tonic::include_proto!("temporal.api.cloud.connectivityrule.v1");
2075 }
2076 }
2077 pub mod identity {
2078 pub mod v1 {
2079 tonic::include_proto!("temporal.api.cloud.identity.v1");
2080 }
2081 }
2082 pub mod namespace {
2083 pub mod v1 {
2084 tonic::include_proto!("temporal.api.cloud.namespace.v1");
2085 }
2086 }
2087 pub mod nexus {
2088 pub mod v1 {
2089 tonic::include_proto!("temporal.api.cloud.nexus.v1");
2090 }
2091 }
2092 pub mod operation {
2093 pub mod v1 {
2094 tonic::include_proto!("temporal.api.cloud.operation.v1");
2095 }
2096 }
2097 pub mod region {
2098 pub mod v1 {
2099 tonic::include_proto!("temporal.api.cloud.region.v1");
2100 }
2101 }
2102 pub mod resource {
2103 pub mod v1 {
2104 tonic::include_proto!("temporal.api.cloud.resource.v1");
2105 }
2106 }
2107 pub mod sink {
2108 pub mod v1 {
2109 tonic::include_proto!("temporal.api.cloud.sink.v1");
2110 }
2111 }
2112 pub mod usage {
2113 pub mod v1 {
2114 tonic::include_proto!("temporal.api.cloud.usage.v1");
2115 }
2116 }
2117 }
2118 pub mod common {
2119 pub mod v1 {
2120 include_proto_with_serde!("temporal.api.common.v1");
2121 mod sdk_helpers {
2122 use super::*;
2123 use crate::protos::{ENCODING_PAYLOAD_KEY, JSON_ENCODING_VAL};
2124 use base64::{Engine, prelude::BASE64_STANDARD};
2125 use std::{
2126 collections::HashMap,
2127 fmt::{Display, Formatter},
2128 };
2129
2130 impl<T> From<T> for Payload
2131 where
2132 T: AsRef<[u8]>,
2133 {
2134 fn from(v: T) -> Self {
2135 let mut metadata = HashMap::new();
2138 metadata
2139 .insert(ENCODING_PAYLOAD_KEY.to_string(), b"binary/plain".to_vec());
2140 Self {
2141 metadata,
2142 data: v.as_ref().to_vec(),
2143 external_payloads: Default::default(),
2144 }
2145 }
2146 }
2147
2148 impl Payload {
2149 pub fn as_slice(&self) -> &[u8] {
2151 self.data.as_slice()
2152 }
2153
2154 pub fn is_json_payload(&self) -> bool {
2155 self.metadata
2156 .get(ENCODING_PAYLOAD_KEY)
2157 .map(|v| v.as_slice() == JSON_ENCODING_VAL.as_bytes())
2158 .unwrap_or_default()
2159 }
2160 }
2161
2162 impl std::fmt::Debug for Payload {
2163 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
2164 if std::env::var("TEMPORAL_PRINT_FULL_PAYLOADS").is_err()
2165 && self.data.len() > 64
2166 {
2167 let mut windows = self.data.as_slice().windows(32);
2168 write!(
2169 f,
2170 "[{}..{}]",
2171 BASE64_STANDARD.encode(windows.next().unwrap_or_default()),
2172 BASE64_STANDARD.encode(windows.next_back().unwrap_or_default())
2173 )
2174 } else {
2175 write!(f, "[{}]", BASE64_STANDARD.encode(&self.data))
2176 }
2177 }
2178 }
2179
2180 impl Display for Payload {
2181 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
2182 write!(f, "{:?}", self)
2183 }
2184 }
2185
2186 impl Display for Header {
2187 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
2188 write!(f, "Header(")?;
2189 for kv in &self.fields {
2190 write!(f, "{}: ", kv.0)?;
2191 write!(f, "{}, ", kv.1)?;
2192 }
2193 write!(f, ")")
2194 }
2195 }
2196
2197 impl From<Header> for HashMap<String, Payload> {
2198 fn from(h: Header) -> Self {
2199 h.fields.into_iter().map(|(k, v)| (k, v.into())).collect()
2200 }
2201 }
2202
2203 impl From<Memo> for HashMap<String, Payload> {
2204 fn from(h: Memo) -> Self {
2205 h.fields.into_iter().map(|(k, v)| (k, v.into())).collect()
2206 }
2207 }
2208
2209 impl From<SearchAttributes> for HashMap<String, Payload> {
2210 fn from(h: SearchAttributes) -> Self {
2211 h.indexed_fields
2212 .into_iter()
2213 .map(|(k, v)| (k, v.into()))
2214 .collect()
2215 }
2216 }
2217
2218 impl From<HashMap<String, Payload>> for SearchAttributes {
2219 fn from(h: HashMap<String, Payload>) -> Self {
2220 Self {
2221 indexed_fields: h.into_iter().map(|(k, v)| (k, v.into())).collect(),
2222 }
2223 }
2224 }
2225
2226 impl From<String> for ActivityType {
2227 fn from(name: String) -> Self {
2228 Self { name }
2229 }
2230 }
2231
2232 impl From<&str> for ActivityType {
2233 fn from(name: &str) -> Self {
2234 Self {
2235 name: name.to_string(),
2236 }
2237 }
2238 }
2239
2240 impl From<ActivityType> for String {
2241 fn from(at: ActivityType) -> Self {
2242 at.name
2243 }
2244 }
2245
2246 impl From<&str> for WorkflowType {
2247 fn from(v: &str) -> Self {
2248 Self {
2249 name: v.to_string(),
2250 }
2251 }
2252 }
2253 }
2254 }
2255 }
2256 pub mod compute {
2257 pub mod v1 {
2258 tonic::include_proto!("temporal.api.compute.v1");
2259 }
2260 }
2261 pub mod deployment {
2262 pub mod v1 {
2263 tonic::include_proto!("temporal.api.deployment.v1");
2264 }
2265 }
2266 pub mod enums {
2267 pub mod v1 {
2268 include_proto_with_serde!("temporal.api.enums.v1");
2269 }
2270 }
2271 pub mod errordetails {
2272 pub mod v1 {
2273 tonic::include_proto!("temporal.api.errordetails.v1");
2274 }
2275 }
2276 pub mod failure {
2277 pub mod v1 {
2278 include_proto_with_serde!("temporal.api.failure.v1");
2279 }
2280 }
2281 pub mod filter {
2282 pub mod v1 {
2283 tonic::include_proto!("temporal.api.filter.v1");
2284 }
2285 }
2286 pub mod history {
2287 pub mod v1 {
2288 tonic::include_proto!("temporal.api.history.v1");
2289 pub use self::sdk_helpers::*;
2290 mod sdk_helpers {
2291 use super::*;
2292 use crate::protos::temporal::api::{
2293 enums::v1::EventType, history::v1::history_event::Attributes,
2294 };
2295 use anyhow::bail;
2296 use std::fmt::{Display, Formatter};
2297
2298 impl History {
2299 pub fn extract_run_id_from_start(&self) -> Result<&str, anyhow::Error> {
2300 extract_original_run_id_from_events(&self.events)
2301 }
2302
2303 pub fn last_event_id(&self) -> i64 {
2306 self.events.last().map(|e| e.event_id).unwrap_or_default()
2307 }
2308 }
2309
2310 pub fn extract_original_run_id_from_events(
2311 events: &[HistoryEvent],
2312 ) -> Result<&str, anyhow::Error> {
2313 if let Some(Attributes::WorkflowExecutionStartedEventAttributes(wes)) =
2314 events.get(0).and_then(|x| x.attributes.as_ref())
2315 {
2316 Ok(&wes.original_execution_run_id)
2317 } else {
2318 bail!("First event is not WorkflowExecutionStarted?!?")
2319 }
2320 }
2321
2322 impl HistoryEvent {
2323 pub fn is_command_event(&self) -> bool {
2325 EventType::try_from(self.event_type).map_or(false, |et| match et {
2326 EventType::ActivityTaskScheduled
2327 | EventType::ActivityTaskCancelRequested
2328 | EventType::MarkerRecorded
2329 | EventType::RequestCancelExternalWorkflowExecutionInitiated
2330 | EventType::SignalExternalWorkflowExecutionInitiated
2331 | EventType::StartChildWorkflowExecutionInitiated
2332 | EventType::TimerCanceled
2333 | EventType::TimerStarted
2334 | EventType::UpsertWorkflowSearchAttributes
2335 | EventType::WorkflowPropertiesModified
2336 | EventType::NexusOperationScheduled
2337 | EventType::NexusOperationCancelRequested
2338 | EventType::WorkflowExecutionCanceled
2339 | EventType::WorkflowExecutionCompleted
2340 | EventType::WorkflowExecutionContinuedAsNew
2341 | EventType::WorkflowExecutionFailed
2342 | EventType::WorkflowExecutionUpdateAccepted
2343 | EventType::WorkflowExecutionUpdateRejected
2344 | EventType::WorkflowExecutionUpdateCompleted => true,
2345 _ => false,
2346 })
2347 }
2348
2349 pub fn get_initial_command_event_id(&self) -> Option<i64> {
2353 self.attributes.as_ref().and_then(|a| {
2354 match a {
2357 Attributes::ActivityTaskStartedEventAttributes(a) =>
2358 Some(a.scheduled_event_id),
2359 Attributes::ActivityTaskCompletedEventAttributes(a) =>
2360 Some(a.scheduled_event_id),
2361 Attributes::ActivityTaskFailedEventAttributes(a) => Some(a.scheduled_event_id),
2362 Attributes::ActivityTaskTimedOutEventAttributes(a) => Some(a.scheduled_event_id),
2363 Attributes::ActivityTaskCancelRequestedEventAttributes(a) => Some(a.scheduled_event_id),
2364 Attributes::ActivityTaskCanceledEventAttributes(a) => Some(a.scheduled_event_id),
2365 Attributes::TimerFiredEventAttributes(a) => Some(a.started_event_id),
2366 Attributes::TimerCanceledEventAttributes(a) => Some(a.started_event_id),
2367 Attributes::RequestCancelExternalWorkflowExecutionFailedEventAttributes(a) => Some(a.initiated_event_id),
2368 Attributes::ExternalWorkflowExecutionCancelRequestedEventAttributes(a) => Some(a.initiated_event_id),
2369 Attributes::StartChildWorkflowExecutionFailedEventAttributes(a) => Some(a.initiated_event_id),
2370 Attributes::ChildWorkflowExecutionStartedEventAttributes(a) => Some(a.initiated_event_id),
2371 Attributes::ChildWorkflowExecutionCompletedEventAttributes(a) => Some(a.initiated_event_id),
2372 Attributes::ChildWorkflowExecutionFailedEventAttributes(a) => Some(a.initiated_event_id),
2373 Attributes::ChildWorkflowExecutionCanceledEventAttributes(a) => Some(a.initiated_event_id),
2374 Attributes::ChildWorkflowExecutionTimedOutEventAttributes(a) => Some(a.initiated_event_id),
2375 Attributes::ChildWorkflowExecutionTerminatedEventAttributes(a) => Some(a.initiated_event_id),
2376 Attributes::SignalExternalWorkflowExecutionFailedEventAttributes(a) => Some(a.initiated_event_id),
2377 Attributes::ExternalWorkflowExecutionSignaledEventAttributes(a) => Some(a.initiated_event_id),
2378 Attributes::WorkflowTaskStartedEventAttributes(a) => Some(a.scheduled_event_id),
2379 Attributes::WorkflowTaskCompletedEventAttributes(a) => Some(a.scheduled_event_id),
2380 Attributes::WorkflowTaskTimedOutEventAttributes(a) => Some(a.scheduled_event_id),
2381 Attributes::WorkflowTaskFailedEventAttributes(a) => Some(a.scheduled_event_id),
2382 Attributes::NexusOperationStartedEventAttributes(a) => Some(a.scheduled_event_id),
2383 Attributes::NexusOperationCompletedEventAttributes(a) => Some(a.scheduled_event_id),
2384 Attributes::NexusOperationFailedEventAttributes(a) => Some(a.scheduled_event_id),
2385 Attributes::NexusOperationTimedOutEventAttributes(a) => Some(a.scheduled_event_id),
2386 Attributes::NexusOperationCanceledEventAttributes(a) => Some(a.scheduled_event_id),
2387 Attributes::NexusOperationCancelRequestedEventAttributes(a) => Some(a.scheduled_event_id),
2388 Attributes::NexusOperationCancelRequestCompletedEventAttributes(a) => Some(a.scheduled_event_id),
2389 Attributes::NexusOperationCancelRequestFailedEventAttributes(a) => Some(a.scheduled_event_id),
2390 _ => None
2391 }
2392 })
2393 }
2394
2395 pub fn get_protocol_instance_id(&self) -> Option<&str> {
2397 self.attributes.as_ref().and_then(|a| match a {
2398 Attributes::WorkflowExecutionUpdateAcceptedEventAttributes(a) => {
2399 Some(a.protocol_instance_id.as_str())
2400 }
2401 _ => None,
2402 })
2403 }
2404
2405 pub fn is_final_wf_execution_event(&self) -> bool {
2407 match self.event_type() {
2408 EventType::WorkflowExecutionCompleted => true,
2409 EventType::WorkflowExecutionCanceled => true,
2410 EventType::WorkflowExecutionFailed => true,
2411 EventType::WorkflowExecutionTimedOut => true,
2412 EventType::WorkflowExecutionContinuedAsNew => true,
2413 EventType::WorkflowExecutionTerminated => true,
2414 _ => false,
2415 }
2416 }
2417
2418 pub fn is_wft_closed_event(&self) -> bool {
2419 match self.event_type() {
2420 EventType::WorkflowTaskCompleted => true,
2421 EventType::WorkflowTaskFailed => true,
2422 EventType::WorkflowTaskTimedOut => true,
2423 _ => false,
2424 }
2425 }
2426
2427 pub fn is_ignorable(&self) -> bool {
2428 if !self.worker_may_ignore {
2429 return false;
2430 }
2431 if let Some(a) = self.attributes.as_ref() {
2434 match a {
2435 Attributes::WorkflowExecutionStartedEventAttributes(_) => false,
2436 Attributes::WorkflowExecutionCompletedEventAttributes(_) => false,
2437 Attributes::WorkflowExecutionFailedEventAttributes(_) => false,
2438 Attributes::WorkflowExecutionTimedOutEventAttributes(_) => false,
2439 Attributes::WorkflowTaskScheduledEventAttributes(_) => false,
2440 Attributes::WorkflowTaskStartedEventAttributes(_) => false,
2441 Attributes::WorkflowTaskCompletedEventAttributes(_) => false,
2442 Attributes::WorkflowTaskTimedOutEventAttributes(_) => false,
2443 Attributes::WorkflowTaskFailedEventAttributes(_) => false,
2444 Attributes::ActivityTaskScheduledEventAttributes(_) => false,
2445 Attributes::ActivityTaskStartedEventAttributes(_) => false,
2446 Attributes::ActivityTaskCompletedEventAttributes(_) => false,
2447 Attributes::ActivityTaskFailedEventAttributes(_) => false,
2448 Attributes::ActivityTaskTimedOutEventAttributes(_) => false,
2449 Attributes::TimerStartedEventAttributes(_) => false,
2450 Attributes::TimerFiredEventAttributes(_) => false,
2451 Attributes::ActivityTaskCancelRequestedEventAttributes(_) => false,
2452 Attributes::ActivityTaskCanceledEventAttributes(_) => false,
2453 Attributes::TimerCanceledEventAttributes(_) => false,
2454 Attributes::MarkerRecordedEventAttributes(_) => false,
2455 Attributes::WorkflowExecutionSignaledEventAttributes(_) => false,
2456 Attributes::WorkflowExecutionTerminatedEventAttributes(_) => false,
2457 Attributes::WorkflowExecutionCancelRequestedEventAttributes(_) => false,
2458 Attributes::WorkflowExecutionCanceledEventAttributes(_) => false,
2459 Attributes::RequestCancelExternalWorkflowExecutionInitiatedEventAttributes(_) => false,
2460 Attributes::RequestCancelExternalWorkflowExecutionFailedEventAttributes(_) => false,
2461 Attributes::ExternalWorkflowExecutionCancelRequestedEventAttributes(_) => false,
2462 Attributes::WorkflowExecutionContinuedAsNewEventAttributes(_) => false,
2463 Attributes::StartChildWorkflowExecutionInitiatedEventAttributes(_) => false,
2464 Attributes::StartChildWorkflowExecutionFailedEventAttributes(_) => false,
2465 Attributes::ChildWorkflowExecutionStartedEventAttributes(_) => false,
2466 Attributes::ChildWorkflowExecutionCompletedEventAttributes(_) => false,
2467 Attributes::ChildWorkflowExecutionFailedEventAttributes(_) => false,
2468 Attributes::ChildWorkflowExecutionCanceledEventAttributes(_) => false,
2469 Attributes::ChildWorkflowExecutionTimedOutEventAttributes(_) => false,
2470 Attributes::ChildWorkflowExecutionTerminatedEventAttributes(_) => false,
2471 Attributes::SignalExternalWorkflowExecutionInitiatedEventAttributes(_) => false,
2472 Attributes::SignalExternalWorkflowExecutionFailedEventAttributes(_) => false,
2473 Attributes::ExternalWorkflowExecutionSignaledEventAttributes(_) => false,
2474 Attributes::UpsertWorkflowSearchAttributesEventAttributes(_) => false,
2475 Attributes::WorkflowExecutionUpdateAcceptedEventAttributes(_) => false,
2476 Attributes::WorkflowExecutionUpdateRejectedEventAttributes(_) => false,
2477 Attributes::WorkflowExecutionUpdateCompletedEventAttributes(_) => false,
2478 Attributes::WorkflowPropertiesModifiedExternallyEventAttributes(_) => false,
2479 Attributes::ActivityPropertiesModifiedExternallyEventAttributes(_) => false,
2480 Attributes::WorkflowPropertiesModifiedEventAttributes(_) => false,
2481 Attributes::WorkflowExecutionUpdateAdmittedEventAttributes(_) => false,
2482 Attributes::NexusOperationScheduledEventAttributes(_) => false,
2483 Attributes::NexusOperationStartedEventAttributes(_) => false,
2484 Attributes::NexusOperationCompletedEventAttributes(_) => false,
2485 Attributes::NexusOperationFailedEventAttributes(_) => false,
2486 Attributes::NexusOperationCanceledEventAttributes(_) => false,
2487 Attributes::NexusOperationTimedOutEventAttributes(_) => false,
2488 Attributes::NexusOperationCancelRequestedEventAttributes(_) => false,
2489 Attributes::WorkflowExecutionOptionsUpdatedEventAttributes(_) => true,
2491 Attributes::NexusOperationCancelRequestCompletedEventAttributes(_) => false,
2492 Attributes::NexusOperationCancelRequestFailedEventAttributes(_) => false,
2493 Attributes::WorkflowExecutionPausedEventAttributes(_) => true,
2495 Attributes::WorkflowExecutionUnpausedEventAttributes(_) => true,
2497 Attributes::WorkflowExecutionTimeSkippingTransitionedEventAttributes(_) => true,
2499 }
2500 } else {
2501 self.worker_may_ignore
2503 }
2504 }
2505 }
2506
2507 impl Display for HistoryEvent {
2508 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
2509 write!(
2510 f,
2511 "HistoryEvent(id: {}, {:?})",
2512 self.event_id,
2513 EventType::try_from(self.event_type).unwrap_or_default()
2514 )
2515 }
2516 }
2517
2518 impl Attributes {
2519 pub fn event_type(&self) -> EventType {
2520 match self {
2522 Attributes::WorkflowExecutionStartedEventAttributes(_) => { EventType::WorkflowExecutionStarted }
2523 Attributes::WorkflowExecutionCompletedEventAttributes(_) => { EventType::WorkflowExecutionCompleted }
2524 Attributes::WorkflowExecutionFailedEventAttributes(_) => { EventType::WorkflowExecutionFailed }
2525 Attributes::WorkflowExecutionTimedOutEventAttributes(_) => { EventType::WorkflowExecutionTimedOut }
2526 Attributes::WorkflowTaskScheduledEventAttributes(_) => { EventType::WorkflowTaskScheduled }
2527 Attributes::WorkflowTaskStartedEventAttributes(_) => { EventType::WorkflowTaskStarted }
2528 Attributes::WorkflowTaskCompletedEventAttributes(_) => { EventType::WorkflowTaskCompleted }
2529 Attributes::WorkflowTaskTimedOutEventAttributes(_) => { EventType::WorkflowTaskTimedOut }
2530 Attributes::WorkflowTaskFailedEventAttributes(_) => { EventType::WorkflowTaskFailed }
2531 Attributes::ActivityTaskScheduledEventAttributes(_) => { EventType::ActivityTaskScheduled }
2532 Attributes::ActivityTaskStartedEventAttributes(_) => { EventType::ActivityTaskStarted }
2533 Attributes::ActivityTaskCompletedEventAttributes(_) => { EventType::ActivityTaskCompleted }
2534 Attributes::ActivityTaskFailedEventAttributes(_) => { EventType::ActivityTaskFailed }
2535 Attributes::ActivityTaskTimedOutEventAttributes(_) => { EventType::ActivityTaskTimedOut }
2536 Attributes::TimerStartedEventAttributes(_) => { EventType::TimerStarted }
2537 Attributes::TimerFiredEventAttributes(_) => { EventType::TimerFired }
2538 Attributes::ActivityTaskCancelRequestedEventAttributes(_) => { EventType::ActivityTaskCancelRequested }
2539 Attributes::ActivityTaskCanceledEventAttributes(_) => { EventType::ActivityTaskCanceled }
2540 Attributes::TimerCanceledEventAttributes(_) => { EventType::TimerCanceled }
2541 Attributes::MarkerRecordedEventAttributes(_) => { EventType::MarkerRecorded }
2542 Attributes::WorkflowExecutionSignaledEventAttributes(_) => { EventType::WorkflowExecutionSignaled }
2543 Attributes::WorkflowExecutionTerminatedEventAttributes(_) => { EventType::WorkflowExecutionTerminated }
2544 Attributes::WorkflowExecutionCancelRequestedEventAttributes(_) => { EventType::WorkflowExecutionCancelRequested }
2545 Attributes::WorkflowExecutionCanceledEventAttributes(_) => { EventType::WorkflowExecutionCanceled }
2546 Attributes::RequestCancelExternalWorkflowExecutionInitiatedEventAttributes(_) => { EventType::RequestCancelExternalWorkflowExecutionInitiated }
2547 Attributes::RequestCancelExternalWorkflowExecutionFailedEventAttributes(_) => { EventType::RequestCancelExternalWorkflowExecutionFailed }
2548 Attributes::ExternalWorkflowExecutionCancelRequestedEventAttributes(_) => { EventType::ExternalWorkflowExecutionCancelRequested }
2549 Attributes::WorkflowExecutionContinuedAsNewEventAttributes(_) => { EventType::WorkflowExecutionContinuedAsNew }
2550 Attributes::StartChildWorkflowExecutionInitiatedEventAttributes(_) => { EventType::StartChildWorkflowExecutionInitiated }
2551 Attributes::StartChildWorkflowExecutionFailedEventAttributes(_) => { EventType::StartChildWorkflowExecutionFailed }
2552 Attributes::ChildWorkflowExecutionStartedEventAttributes(_) => { EventType::ChildWorkflowExecutionStarted }
2553 Attributes::ChildWorkflowExecutionCompletedEventAttributes(_) => { EventType::ChildWorkflowExecutionCompleted }
2554 Attributes::ChildWorkflowExecutionFailedEventAttributes(_) => { EventType::ChildWorkflowExecutionFailed }
2555 Attributes::ChildWorkflowExecutionCanceledEventAttributes(_) => { EventType::ChildWorkflowExecutionCanceled }
2556 Attributes::ChildWorkflowExecutionTimedOutEventAttributes(_) => { EventType::ChildWorkflowExecutionTimedOut }
2557 Attributes::ChildWorkflowExecutionTerminatedEventAttributes(_) => { EventType::ChildWorkflowExecutionTerminated }
2558 Attributes::SignalExternalWorkflowExecutionInitiatedEventAttributes(_) => { EventType::SignalExternalWorkflowExecutionInitiated }
2559 Attributes::SignalExternalWorkflowExecutionFailedEventAttributes(_) => { EventType::SignalExternalWorkflowExecutionFailed }
2560 Attributes::ExternalWorkflowExecutionSignaledEventAttributes(_) => { EventType::ExternalWorkflowExecutionSignaled }
2561 Attributes::UpsertWorkflowSearchAttributesEventAttributes(_) => { EventType::UpsertWorkflowSearchAttributes }
2562 Attributes::WorkflowExecutionUpdateAdmittedEventAttributes(_) => { EventType::WorkflowExecutionUpdateAdmitted }
2563 Attributes::WorkflowExecutionUpdateRejectedEventAttributes(_) => { EventType::WorkflowExecutionUpdateRejected }
2564 Attributes::WorkflowExecutionUpdateAcceptedEventAttributes(_) => { EventType::WorkflowExecutionUpdateAccepted }
2565 Attributes::WorkflowExecutionUpdateCompletedEventAttributes(_) => { EventType::WorkflowExecutionUpdateCompleted }
2566 Attributes::WorkflowPropertiesModifiedExternallyEventAttributes(_) => { EventType::WorkflowPropertiesModifiedExternally }
2567 Attributes::ActivityPropertiesModifiedExternallyEventAttributes(_) => { EventType::ActivityPropertiesModifiedExternally }
2568 Attributes::WorkflowPropertiesModifiedEventAttributes(_) => { EventType::WorkflowPropertiesModified }
2569 Attributes::NexusOperationScheduledEventAttributes(_) => { EventType::NexusOperationScheduled }
2570 Attributes::NexusOperationStartedEventAttributes(_) => { EventType::NexusOperationStarted }
2571 Attributes::NexusOperationCompletedEventAttributes(_) => { EventType::NexusOperationCompleted }
2572 Attributes::NexusOperationFailedEventAttributes(_) => { EventType::NexusOperationFailed }
2573 Attributes::NexusOperationCanceledEventAttributes(_) => { EventType::NexusOperationCanceled }
2574 Attributes::NexusOperationTimedOutEventAttributes(_) => { EventType::NexusOperationTimedOut }
2575 Attributes::NexusOperationCancelRequestedEventAttributes(_) => { EventType::NexusOperationCancelRequested }
2576 Attributes::WorkflowExecutionOptionsUpdatedEventAttributes(_) => { EventType::WorkflowExecutionOptionsUpdated }
2577 Attributes::NexusOperationCancelRequestCompletedEventAttributes(_) => { EventType::NexusOperationCancelRequestCompleted }
2578 Attributes::NexusOperationCancelRequestFailedEventAttributes(_) => { EventType::NexusOperationCancelRequestFailed }
2579 Attributes::WorkflowExecutionPausedEventAttributes(_) => { EventType::WorkflowExecutionPaused }
2580 Attributes::WorkflowExecutionUnpausedEventAttributes(_) => { EventType::WorkflowExecutionUnpaused }
2581 Attributes::WorkflowExecutionTimeSkippingTransitionedEventAttributes(_) => { EventType::WorkflowExecutionTimeSkippingTransitioned }
2582 }
2583 }
2584 }
2585 }
2586 }
2587 }
2588 pub mod namespace {
2589 pub mod v1 {
2590 tonic::include_proto!("temporal.api.namespace.v1");
2591 }
2592 }
2593 pub mod operatorservice {
2594 pub mod v1 {
2595 tonic::include_proto!("temporal.api.operatorservice.v1");
2596 }
2597 }
2598 pub mod protocol {
2599 pub mod v1 {
2600 tonic::include_proto!("temporal.api.protocol.v1");
2601 mod sdk_helpers {
2602 use super::*;
2603 use std::fmt::{Display, Formatter};
2604
2605 impl Display for Message {
2606 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
2607 write!(f, "ProtocolMessage({})", self.id)
2608 }
2609 }
2610 }
2611 }
2612 }
2613 pub mod query {
2614 pub mod v1 {
2615 tonic::include_proto!("temporal.api.query.v1");
2616 }
2617 }
2618 pub mod replication {
2619 pub mod v1 {
2620 tonic::include_proto!("temporal.api.replication.v1");
2621 }
2622 }
2623 pub mod rules {
2624 pub mod v1 {
2625 tonic::include_proto!("temporal.api.rules.v1");
2626 }
2627 }
2628 pub mod schedule {
2629 #[allow(rustdoc::invalid_html_tags)]
2630 pub mod v1 {
2631 tonic::include_proto!("temporal.api.schedule.v1");
2632 }
2633 }
2634 pub mod sdk {
2635 pub mod v1 {
2636 tonic::include_proto!("temporal.api.sdk.v1");
2637 }
2638 }
2639 pub mod taskqueue {
2640 pub mod v1 {
2641 tonic::include_proto!("temporal.api.taskqueue.v1");
2642 mod sdk_helpers {
2643 use super::*;
2644 use crate::protos::temporal::api::enums::v1::TaskQueueKind;
2645
2646 impl From<String> for TaskQueue {
2647 fn from(name: String) -> Self {
2648 Self {
2649 name,
2650 kind: TaskQueueKind::Normal as i32,
2651 normal_name: "".to_string(),
2652 }
2653 }
2654 }
2655 }
2656 }
2657 }
2658 pub mod testservice {
2659 pub mod v1 {
2660 tonic::include_proto!("temporal.api.testservice.v1");
2661 }
2662 }
2663 pub mod update {
2664 pub mod v1 {
2665 tonic::include_proto!("temporal.api.update.v1");
2666 mod sdk_helpers {
2667 use super::*;
2668 use crate::protos::temporal::api::update::v1::outcome::Value;
2669
2670 impl Outcome {
2671 pub fn is_success(&self) -> bool {
2672 match self.value {
2673 Some(Value::Success(_)) => true,
2674 _ => false,
2675 }
2676 }
2677 }
2678 }
2679 }
2680 }
2681 pub mod version {
2682 pub mod v1 {
2683 tonic::include_proto!("temporal.api.version.v1");
2684 }
2685 }
2686 pub mod worker {
2687 pub mod v1 {
2688 tonic::include_proto!("temporal.api.worker.v1");
2689 }
2690 }
2691 pub mod workflow {
2692 pub mod v1 {
2693 tonic::include_proto!("temporal.api.workflow.v1");
2694 }
2695 }
2696 pub mod nexus {
2697 pub mod v1 {
2698 tonic::include_proto!("temporal.api.nexus.v1");
2699 pub use self::sdk_helpers::*;
2700 mod sdk_helpers {
2701 use super::*;
2702 use crate::protos::{
2703 camel_case_to_screaming_snake,
2704 temporal::api::{
2705 common::{
2706 self,
2707 v1::link::{WorkflowEvent, workflow_event},
2708 },
2709 enums::v1::EventType,
2710 failure,
2711 },
2712 };
2713 use anyhow::{anyhow, bail};
2714 use http::Uri;
2715 #[cfg(feature = "serde_serialize")]
2716 use prost::Name;
2717 #[cfg(feature = "serde_serialize")]
2718 use std::collections::HashMap;
2719 use std::fmt::{Display, Formatter};
2720
2721 impl Display for Response {
2722 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
2723 write!(f, "NexusResponse(",)?;
2724 match &self.variant {
2725 None => {}
2726 Some(v) => {
2727 write!(f, "{v}")?;
2728 }
2729 }
2730 write!(f, ")")
2731 }
2732 }
2733
2734 impl Display for response::Variant {
2735 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
2736 match self {
2737 response::Variant::StartOperation(_) => {
2738 write!(f, "StartOperation")
2739 }
2740 response::Variant::CancelOperation(_) => {
2741 write!(f, "CancelOperation")
2742 }
2743 }
2744 }
2745 }
2746
2747 impl Display for HandlerError {
2748 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
2749 write!(f, "HandlerError")
2750 }
2751 }
2752
2753 pub enum NexusTaskFailure {
2754 Legacy(HandlerError),
2755 Temporal(failure::v1::Failure),
2756 }
2757
2758 static SCHEME_PREFIX: &str = "temporal://";
2759
2760 pub fn workflow_event_link_from_nexus(
2762 l: &Link,
2763 ) -> Result<common::v1::Link, anyhow::Error> {
2764 if !l.url.starts_with(SCHEME_PREFIX) {
2765 bail!("Invalid scheme for nexus link: {:?}", l.url);
2766 }
2767 let no_authority_url = l.url.strip_prefix(SCHEME_PREFIX).unwrap();
2770 let uri = Uri::try_from(no_authority_url)?;
2771 let parts = uri.into_parts();
2772 let path = parts.path_and_query.ok_or_else(|| {
2773 anyhow!("Failed to parse nexus link, invalid path: {:?}", l)
2774 })?;
2775 let path_parts = path.path().split('/').collect::<Vec<_>>();
2776 if path_parts.get(1) != Some(&"namespaces") {
2777 bail!("Invalid path for nexus link: {:?}", l);
2778 }
2779 let namespace = path_parts.get(2).ok_or_else(|| {
2780 anyhow!("Failed to parse nexus link, no namespace: {:?}", l)
2781 })?;
2782 if path_parts.get(3) != Some(&"workflows") {
2783 bail!("Invalid path for nexus link, no workflows segment: {:?}", l);
2784 }
2785 let workflow_id = path_parts.get(4).ok_or_else(|| {
2786 anyhow!("Failed to parse nexus link, no workflow id: {:?}", l)
2787 })?;
2788 let run_id = path_parts.get(5).ok_or_else(|| {
2789 anyhow!("Failed to parse nexus link, no run id: {:?}", l)
2790 })?;
2791 if path_parts.get(6) != Some(&"history") {
2792 bail!("Invalid path for nexus link, no history segment: {:?}", l);
2793 }
2794 let reference = if let Some(query) = path.query() {
2795 let mut eventref = workflow_event::EventReference::default();
2796 let query_parts = query.split('&').collect::<Vec<_>>();
2797 for qp in query_parts {
2798 let mut kv = qp.split('=');
2799 let key = kv.next().ok_or_else(|| {
2800 anyhow!("Failed to parse nexus link query parameter: {:?}", l)
2801 })?;
2802 let val = kv.next().ok_or_else(|| {
2803 anyhow!("Failed to parse nexus link query parameter: {:?}", l)
2804 })?;
2805 match key {
2806 "eventID" => {
2807 eventref.event_id = val.parse().map_err(|_| {
2808 anyhow!("Failed to parse nexus link event id: {:?}", l)
2809 })?;
2810 }
2811 "eventType" => {
2812 eventref.event_type = EventType::from_str_name(val)
2813 .unwrap_or_else(|| {
2814 EventType::from_str_name(
2815 &("EVENT_TYPE_".to_string()
2816 + &camel_case_to_screaming_snake(val)),
2817 )
2818 .unwrap_or_default()
2819 })
2820 .into()
2821 }
2822 _ => continue,
2823 }
2824 }
2825 Some(workflow_event::Reference::EventRef(eventref))
2826 } else {
2827 None
2828 };
2829
2830 Ok(common::v1::Link {
2831 variant: Some(common::v1::link::Variant::WorkflowEvent(
2832 WorkflowEvent {
2833 namespace: namespace.to_string(),
2834 workflow_id: workflow_id.to_string(),
2835 run_id: run_id.to_string(),
2836 reference,
2837 },
2838 )),
2839 })
2840 }
2841
2842 #[cfg(feature = "serde_serialize")]
2843 impl TryFrom<failure::v1::Failure> for Failure {
2844 type Error = serde_json::Error;
2845
2846 fn try_from(mut f: failure::v1::Failure) -> Result<Self, Self::Error> {
2847 let message = std::mem::take(&mut f.message);
2849
2850 let details = serde_json::to_vec(&f)?;
2852
2853 Ok(Failure {
2855 message,
2856 stack_trace: f.stack_trace,
2857 metadata: HashMap::from([(
2858 "type".to_string(),
2859 failure::v1::Failure::full_name().into(),
2860 )]),
2861 details,
2862 cause: None,
2863 })
2864 }
2865 }
2866 }
2867 }
2868 }
2869 pub mod nexusservices {
2870 pub mod workerservice {
2871 pub mod v1 {
2872 tonic::include_proto!("temporal.api.nexusservices.workerservice.v1");
2873 }
2874 }
2875 }
2876 pub mod workflowservice {
2877 pub mod v1 {
2878 tonic::include_proto!("temporal.api.workflowservice.v1");
2879 pub use self::sdk_helpers::*;
2880 mod sdk_helpers {
2881 use super::*;
2882 use std::{
2883 convert::TryInto,
2884 fmt::{Display, Formatter},
2885 time::{Duration, SystemTime},
2886 };
2887
2888 macro_rules! sched_to_start_impl {
2889 ($sched_field:ident) => {
2890 pub fn sched_to_start(&self) -> Option<Duration> {
2893 if let Some((sch, st)) =
2894 self.$sched_field.clone().zip(self.started_time.clone())
2895 {
2896 if let Some(value) = elapsed_between_prost_times(sch, st) {
2897 return value;
2898 }
2899 }
2900 None
2901 }
2902 };
2903 }
2904
2905 fn elapsed_between_prost_times(
2906 from: prost_types::Timestamp,
2907 to: prost_types::Timestamp,
2908 ) -> Option<Option<Duration>> {
2909 let from: Result<SystemTime, _> = from.try_into();
2910 let to: Result<SystemTime, _> = to.try_into();
2911 if let (Ok(from), Ok(to)) = (from, to) {
2912 return Some(to.duration_since(from).ok());
2913 }
2914 None
2915 }
2916
2917 impl PollWorkflowTaskQueueResponse {
2918 sched_to_start_impl!(scheduled_time);
2919 }
2920
2921 impl Display for PollWorkflowTaskQueueResponse {
2922 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
2923 let last_event = self
2924 .history
2925 .as_ref()
2926 .and_then(|h| h.events.last().map(|he| he.event_id))
2927 .unwrap_or(0);
2928 write!(
2929 f,
2930 "PollWFTQResp(run_id: {}, attempt: {}, last_event: {})",
2931 self.workflow_execution
2932 .as_ref()
2933 .map_or("", |we| we.run_id.as_str()),
2934 self.attempt,
2935 last_event
2936 )
2937 }
2938 }
2939
2940 pub struct CompactHist<'a>(pub &'a PollWorkflowTaskQueueResponse);
2942 impl Display for CompactHist<'_> {
2943 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
2944 writeln!(
2945 f,
2946 "PollWorkflowTaskQueueResponse (prev_started: {}, started: {})",
2947 self.0.previous_started_event_id, self.0.started_event_id
2948 )?;
2949 if let Some(h) = self.0.history.as_ref() {
2950 for event in &h.events {
2951 writeln!(f, "{}", event)?;
2952 }
2953 }
2954 writeln!(f, "query: {:#?}", self.0.query)?;
2955 writeln!(f, "queries: {:#?}", self.0.queries)
2956 }
2957 }
2958
2959 impl PollActivityTaskQueueResponse {
2960 sched_to_start_impl!(current_attempt_scheduled_time);
2961 }
2962
2963 impl PollNexusTaskQueueResponse {
2964 pub fn sched_to_start(&self) -> Option<Duration> {
2965 if let Some((sch, st)) = self
2966 .request
2967 .as_ref()
2968 .and_then(|r| r.scheduled_time)
2969 .clone()
2970 .zip(SystemTime::now().try_into().ok())
2971 {
2972 if let Some(value) = elapsed_between_prost_times(sch, st) {
2973 return value;
2974 }
2975 }
2976 None
2977 }
2978 }
2979
2980 impl QueryWorkflowResponse {
2981 pub fn unwrap(
2983 self,
2984 ) -> Vec<crate::protos::temporal::api::common::v1::Payload>
2985 {
2986 self.query_result.unwrap().payloads
2987 }
2988 }
2989 }
2990 }
2991 }
2992 }
2993}
2994
2995#[allow(
2996 clippy::all,
2997 missing_docs,
2998 rustdoc::broken_intra_doc_links,
2999 rustdoc::bare_urls
3000)]
3001pub mod google {
3002 pub mod rpc {
3003 tonic::include_proto!("google.rpc");
3004 }
3005}
3006
3007#[allow(
3008 clippy::all,
3009 missing_docs,
3010 rustdoc::broken_intra_doc_links,
3011 rustdoc::bare_urls
3012)]
3013pub mod grpc {
3014 pub mod health {
3015 pub mod v1 {
3016 tonic::include_proto!("grpc.health.v1");
3017 }
3018 }
3019}
3020mod sdk_helpers {
3021 use std::time::Duration;
3022
3023 pub fn camel_case_to_screaming_snake(val: &str) -> String {
3025 let mut out = String::new();
3026 let mut last_was_upper = true;
3027 for c in val.chars() {
3028 if c.is_uppercase() {
3029 if !last_was_upper {
3030 out.push('_');
3031 }
3032 out.push(c.to_ascii_uppercase());
3033 last_was_upper = true;
3034 } else {
3035 out.push(c.to_ascii_uppercase());
3036 last_was_upper = false;
3037 }
3038 }
3039 out
3040 }
3041
3042 pub fn proto_ts_to_system_time(ts: &prost_types::Timestamp) -> Option<std::time::SystemTime> {
3044 std::time::SystemTime::UNIX_EPOCH.checked_add(
3045 Duration::from_secs(ts.seconds as u64) + Duration::from_nanos(ts.nanos as u64),
3046 )
3047 }
3048
3049 #[cfg(test)]
3050 mod tests {
3051 use crate::protos::{
3052 coresdk::{activity_task, activity_task::ActivityTask},
3053 temporal::api::{
3054 failure::v1::Failure, workflowservice::v1::PollActivityTaskQueueResponse,
3055 },
3056 };
3057 use anyhow::anyhow;
3058
3059 #[test]
3060 fn start_from_poll_resp_standalone_activity_populates_run_id() {
3061 let resp = PollActivityTaskQueueResponse {
3062 task_token: vec![1, 2, 3],
3063 activity_run_id: "test-run-id-123".to_string(),
3064 activity_id: "my-activity".to_string(),
3065 ..Default::default()
3066 };
3067 let task = ActivityTask::start_from_poll_resp(resp);
3068 let start = match task.variant {
3069 Some(activity_task::activity_task::Variant::Start(s)) => s,
3070 _ => panic!("expected Start variant"),
3071 };
3072 assert_eq!(start.run_id, "test-run-id-123");
3073 assert!(!start.is_local);
3074 }
3075
3076 #[test]
3077 fn start_from_poll_resp_workflow_activity_has_empty_run_id() {
3078 use crate::protos::temporal::api::common::v1::WorkflowExecution;
3079 let resp = PollActivityTaskQueueResponse {
3080 task_token: vec![4, 5, 6],
3081 activity_id: "my-workflow-activity".to_string(),
3082 workflow_execution: Some(WorkflowExecution {
3083 workflow_id: "wf-123".to_string(),
3084 run_id: "wf-run-456".to_string(),
3085 }),
3086 ..Default::default()
3088 };
3089 let task = ActivityTask::start_from_poll_resp(resp);
3090 let start = match task.variant {
3091 Some(activity_task::activity_task::Variant::Start(s)) => s,
3092 _ => panic!("expected Start variant"),
3093 };
3094 assert!(start.run_id.is_empty());
3095 assert_eq!(start.workflow_execution.unwrap().run_id, "wf-run-456");
3097 }
3098
3099 #[test]
3100 fn anyhow_to_failure_conversion() {
3101 let no_causes: Failure = anyhow!("no causes").into();
3102 assert_eq!(no_causes.cause, None);
3103 assert_eq!(no_causes.message, "no causes");
3104 let orig = anyhow!("fail 1");
3105 let mid = orig.context("fail 2");
3106 let top = mid.context("fail 3");
3107 let as_fail: Failure = top.into();
3108 assert_eq!(as_fail.message, "fail 3");
3109 assert_eq!(as_fail.cause.as_ref().unwrap().message, "fail 2");
3110 assert_eq!(as_fail.cause.unwrap().cause.unwrap().message, "fail 1");
3111 }
3112 }
3113}
3114pub use self::sdk_helpers::*;