1use std::collections::{HashMap, HashSet};
10use std::sync::atomic::{AtomicBool, Ordering};
11use std::sync::{Arc, Condvar, Mutex};
12use std::time::{Duration, SystemTime};
13
14use dex_protocol::dex::{
15 AttributeWrite, ChannelInfo, ChannelMessage as ProtoChannelMessage, ChannelMessageDeletion,
16 ChannelValues, ConditionResults, ConditionStatus, Context as ProtoContext, Kv, StepStreamWrite,
17 Value as ProtoValue, value,
18};
19
20use crate::attribute::{
21 AttributeWriteSettings, require_registered_hard_delete_setting,
22 validate_hard_delete_attribute_write,
23};
24use crate::persistence::PersistenceKind;
25use crate::registry::{RegisteredFlow, decode_instance, physical_name, validate_map_instance};
26use crate::server_protocol::NegotiatedServerProtocolVersion;
27use crate::value_mapper;
28use crate::worker_output::StepOutputEmitter;
29use crate::{
30 Attribute, AttributeMap, Channel, ChannelMap, ChannelMessage, FlowResult, HandlerError,
31 HandlerResult, Stream, Value,
32};
33
34#[derive(Clone, Copy, Eq, PartialEq)]
35pub(crate) enum InvocationMethod {
36 WaitFor,
37 Execute,
38 Rpc,
39}
40
41pub(crate) struct ContextInput {
42 pub(crate) method: InvocationMethod,
43 pub(crate) flow: RegisteredFlow,
44 pub(crate) metadata: ProtoContext,
45 pub(crate) attributes: Vec<Kv>,
46 pub(crate) locals: Vec<Kv>,
47 pub(crate) condition_results: Option<ConditionResults>,
48 pub(crate) channel_infos: HashMap<String, ChannelInfo>,
49 pub(crate) loaded_channel_messages: HashMap<String, ChannelValues>,
50 pub(crate) loaded_attribute_map_instances: Vec<String>,
51 pub(crate) loaded_channel_names: Vec<String>,
52 pub(crate) loaded_channel_map_instances: Vec<String>,
53 pub(crate) negotiated_protocol_version: NegotiatedServerProtocolVersion,
54}
55
56pub(crate) struct InvocationOutputs {
57 pub(crate) attributes: Vec<AttributeWrite>,
58 pub(crate) locals: Vec<Kv>,
59 pub(crate) events: Vec<Kv>,
60 pub(crate) publications: Vec<ProtoChannelMessage>,
61 pub(crate) channel_deletions: Vec<ChannelMessageDeletion>,
62}
63
64#[derive(Clone, Debug, Eq, PartialEq)]
77pub struct RecoveryErrorInfo {
78 detail: String,
79 error_type: String,
80 attempt_progress: StepAttemptProgress,
81}
82
83#[derive(Clone, Copy, Debug, Eq, PartialEq)]
109#[non_exhaustive]
110pub enum StepAttemptProgress {
111 Unspecified,
113 NotStarted,
115 NotCompleted,
117}
118
119impl StepAttemptProgress {
120 fn from_protocol_value(value: i32) -> Self {
121 match dex_protocol::dex::StepAttemptProgress::try_from(value) {
122 Ok(dex_protocol::dex::StepAttemptProgress::NotStarted) => Self::NotStarted,
123 Ok(dex_protocol::dex::StepAttemptProgress::NotCompleted) => Self::NotCompleted,
124 Ok(dex_protocol::dex::StepAttemptProgress::Unspecified) | Err(_) => Self::Unspecified,
125 }
126 }
127}
128
129impl RecoveryErrorInfo {
130 pub fn attempt_progress(&self) -> StepAttemptProgress {
137 self.attempt_progress
138 }
139
140 pub fn detail(&self) -> &str {
142 &self.detail
143 }
144
145 pub fn error_type(&self) -> &str {
147 &self.error_type
148 }
149}
150
151pub struct Context {
167 method: InvocationMethod,
168 flow: RegisteredFlow,
169 output_emitter: Option<StepOutputEmitter>,
170 metadata: ProtoContext,
171 recovery_error: Option<RecoveryErrorInfo>,
172 attributes: HashMap<String, ProtoValue>,
173 locals: HashMap<String, ProtoValue>,
174 condition_results: Option<ConditionResults>,
175 channel_infos: HashMap<String, ChannelInfo>,
176 loaded_channel_messages: HashMap<String, ChannelValues>,
177 loaded_attribute_map_instances: HashSet<String>,
178 loaded_channel_names: HashSet<String>,
179 loaded_channel_map_instances: HashSet<String>,
180 attribute_writes: HashMap<String, AttributeWrite>,
181 local_writes: HashMap<String, Kv>,
182 events: Vec<Kv>,
183 event_names: HashSet<String>,
184 publications: Vec<ProtoChannelMessage>,
185 channel_deletions: Vec<ChannelMessageDeletion>,
186 cancellation: InvocationCancellation,
187 runtime: Option<tokio::runtime::Handle>,
188 step_output_finalizers: Vec<Arc<dyn StepOutputFinalizer>>,
189 step_outputs_finalized: bool,
190 negotiated_protocol_version: NegotiatedServerProtocolVersion,
191}
192
193pub(crate) trait StepOutputFinalizer: Send + Sync {
194 fn finalize_step_output(&self) -> HandlerResult<()>;
195}
196
197impl Context {
198 pub(crate) fn new(
199 input: ContextInput,
200 output_emitter: Option<StepOutputEmitter>,
201 cancellation: InvocationCancellation,
202 ) -> HandlerResult<Self> {
203 let recovery_error =
204 input
205 .metadata
206 .recovery_error
207 .as_ref()
208 .map(|error| RecoveryErrorInfo {
209 attempt_progress: StepAttemptProgress::from_protocol_value(
210 error.attempt_progress,
211 ),
212 detail: error.detail.clone(),
213 error_type: error.error_type.clone(),
214 });
215 Ok(Self {
216 method: input.method,
217 flow: input.flow,
218 output_emitter,
219 metadata: input.metadata,
220 recovery_error,
221 attributes: map_values("Attribute", input.attributes)?,
222 locals: map_values("step-execution local", input.locals)?,
223 condition_results: input.condition_results,
224 channel_infos: input.channel_infos,
225 loaded_channel_messages: input.loaded_channel_messages,
226 loaded_attribute_map_instances: input
227 .loaded_attribute_map_instances
228 .into_iter()
229 .collect(),
230 loaded_channel_names: input.loaded_channel_names.into_iter().collect(),
231 loaded_channel_map_instances: input.loaded_channel_map_instances.into_iter().collect(),
232 attribute_writes: HashMap::new(),
233 local_writes: HashMap::new(),
234 events: Vec::new(),
235 event_names: HashSet::new(),
236 publications: Vec::new(),
237 channel_deletions: Vec::new(),
238 cancellation,
239 runtime: tokio::runtime::Handle::try_current().ok(),
240 step_output_finalizers: Vec::new(),
241 step_outputs_finalized: false,
242 negotiated_protocol_version: input.negotiated_protocol_version,
243 })
244 }
245
246 pub fn flow_id(&self) -> &str {
248 &self.metadata.flow_id
249 }
250
251 pub fn run_id(&self) -> &str {
258 &self.metadata.run_id
259 }
260
261 pub fn flow_started_at(&self) -> SystemTime {
263 system_time(self.metadata.flow_started_timestamp)
264 }
265
266 pub fn step_execution_id(&self) -> &str {
270 &self.metadata.step_execution_id
271 }
272
273 pub fn from_step_execution_id(&self) -> &str {
275 &self.metadata.from_step_execution_id
276 }
277
278 pub fn recovery_error(&self) -> Option<&RecoveryErrorInfo> {
280 self.recovery_error.as_ref()
281 }
282
283 pub fn first_attempt_at(&self) -> SystemTime {
285 system_time(self.metadata.first_attempt_timestamp)
286 }
287
288 pub fn attempt(&self) -> u32 {
296 u32::try_from(self.metadata.attempt).unwrap_or_default()
297 }
298
299 pub fn record_heartbeat(&mut self) -> HandlerResult<()> {
309 self.step_output_emitter()?.send_heartbeat(None)
310 }
311
312 pub fn record_heartbeat_value<T: Value>(&mut self, value: T) -> HandlerResult<()> {
341 let value = value_mapper::encode_handler(&value)?;
342 self.step_output_emitter()?.send_heartbeat(Some(value))
343 }
344
345 pub fn last_heartbeat_value<T: Value>(&self) -> HandlerResult<Option<T>> {
356 if self.method == InvocationMethod::Rpc {
357 return Err(HandlerError::new(
358 "dex_sdk::HandlerError",
359 "Heartbeat values require a Step Context",
360 ));
361 }
362 self.metadata
363 .last_heartbeat_value
364 .as_ref()
365 .map(value_mapper::decode_handler)
366 .transpose()
367 }
368
369 pub fn has_any_timer_fired(&self) -> bool {
371 self.condition_results.as_ref().is_some_and(|results| {
372 results
373 .timer_results
374 .iter()
375 .any(|timer| timer.condition_status == ConditionStatus::Completed as i32)
376 })
377 }
378
379 pub fn has_timer_fired(&self, index: usize) -> bool {
383 self.condition_results
384 .as_ref()
385 .and_then(|results| results.timer_results.get(index))
386 .is_some_and(|timer| timer.condition_status == ConditionStatus::Completed as i32)
387 }
388
389 pub fn wait_for_method_failed(&self) -> bool {
391 self.condition_results
392 .as_ref()
393 .is_some_and(|results| results.wait_for_failed)
394 }
395
396 pub(crate) fn sub_flow_result(&self, index: usize) -> HandlerResult<FlowResult> {
397 if self.method != InvocationMethod::Execute {
398 return Err(HandlerError::new(
399 "dex_sdk::HandlerError",
400 "SubFlow results are available only during execute",
401 ));
402 }
403 let result = self
404 .condition_results
405 .as_ref()
406 .and_then(|results| results.sub_flow_results.get(index))
407 .ok_or_else(|| {
408 HandlerError::new(
409 "dex_sdk::HandlerError",
410 format!("SubFlow result index is unavailable: {index}"),
411 )
412 })?;
413 FlowResult::from_proto(result).map_err(HandlerError::from_error)
414 }
415
416 pub(crate) fn sub_flow_id(&self, index: usize) -> HandlerResult<String> {
417 self.sub_flow_result(index)?;
418 Ok(format!(
419 "SubFlow:{}-{}-{index}",
420 self.flow_id(),
421 self.step_execution_id()
422 ))
423 }
424
425 pub fn wait_for_cancellation(&self) {
429 self.cancellation.wait();
430 }
431
432 pub fn is_cancelled(&self) -> bool {
434 self.cancellation.is_cancelled()
435 }
436
437 pub fn set_step_execution_local<T: Value>(&mut self, key: &str, value: T) -> HandlerResult<()> {
443 require_name(key, "step-execution local key")?;
444 let value = value_mapper::encode_handler(&value)?;
445 self.local_writes.insert(
446 key.to_string(),
447 Kv {
448 key: key.to_string(),
449 value: Some(value),
450 },
451 );
452 Ok(())
453 }
454
455 pub fn step_execution_local<T: Value>(&self, key: &str) -> HandlerResult<T> {
461 require_name(key, "step-execution local key")?;
462 let value = self
463 .local_writes
464 .get(key)
465 .and_then(|entry| entry.value.as_ref())
466 .or_else(|| self.locals.get(key))
467 .ok_or_else(|| {
468 HandlerError::new(
469 "dex_sdk::HandlerError",
470 format!("step-execution local {key} is missing"),
471 )
472 })?;
473 value_mapper::decode_handler(value)
474 }
475
476 pub fn record_event<T: Value>(&mut self, name: &str, value: T) -> HandlerResult<()> {
484 require_name(name, "event name")?;
485 if !self.event_names.insert(name.to_string()) {
486 return Err(HandlerError::new(
487 "dex_sdk::HandlerError",
488 format!("event was already recorded: {name}"),
489 ));
490 }
491 self.events.push(Kv {
492 key: name.to_string(),
493 value: Some(value_mapper::encode_handler(&value)?),
494 });
495 Ok(())
496 }
497
498 pub fn get_attribute<T: Value>(&self, attribute: &Attribute<T>) -> HandlerResult<Option<T>> {
500 self.get_attribute_value(attribute.name(), PersistenceKind::Attribute, None)
501 }
502
503 pub fn get_attribute_map<T: Value>(
505 &self,
506 attribute: &AttributeMap<T>,
507 instance: &str,
508 ) -> HandlerResult<Option<T>> {
509 self.get_attribute_value(
510 attribute.name(),
511 PersistenceKind::AttributeMap,
512 Some(instance),
513 )
514 }
515
516 pub fn set_attribute<T: Value>(
518 &mut self,
519 attribute: &Attribute<T>,
520 value: T,
521 ) -> HandlerResult<()> {
522 self.set_attribute_value(
523 attribute.name(),
524 PersistenceKind::Attribute,
525 None,
526 value_mapper::encode_handler(&value)?,
527 attribute.write_settings(),
528 )
529 }
530
531 pub fn set_attribute_map<T: Value>(
533 &mut self,
534 attribute: &AttributeMap<T>,
535 instance: &str,
536 value: T,
537 ) -> HandlerResult<()> {
538 self.set_attribute_value(
539 attribute.name(),
540 PersistenceKind::AttributeMap,
541 Some(instance),
542 value_mapper::encode_handler(&value)?,
543 attribute.write_settings(),
544 )
545 }
546
547 pub fn delete_attribute<T>(&mut self, attribute: &Attribute<T>) -> HandlerResult<()> {
549 self.set_attribute_value(
550 attribute.name(),
551 PersistenceKind::Attribute,
552 None,
553 value_mapper::deletion(),
554 attribute.write_settings(),
555 )
556 }
557
558 pub fn delete_attribute_map<T>(
560 &mut self,
561 attribute: &AttributeMap<T>,
562 instance: &str,
563 ) -> HandlerResult<()> {
564 self.set_attribute_value(
565 attribute.name(),
566 PersistenceKind::AttributeMap,
567 Some(instance),
568 value_mapper::deletion(),
569 attribute.write_settings(),
570 )
571 }
572
573 pub(crate) fn attribute_map_keys<T>(
574 &self,
575 attribute: &AttributeMap<T>,
576 ) -> HandlerResult<Vec<String>> {
577 self.registered_name(
578 attribute.name(),
579 PersistenceKind::AttributeMap,
580 Some("key-check"),
581 )?;
582 if !self
583 .loaded_attribute_map_instances
584 .contains(&format!("{}/", attribute.name()))
585 {
586 return Err(attribute_map_not_loaded(format!(
587 "all AttributeMap instances were not loaded for this invocation: {}",
588 attribute.name()
589 )));
590 }
591 let prefix = format!("{}/", attribute.name());
592 let mut physical_keys = self
593 .attributes
594 .keys()
595 .filter(|key| key.starts_with(&prefix))
596 .cloned()
597 .collect::<HashSet<_>>();
598 for (key, write) in &self.attribute_writes {
599 if !key.starts_with(&prefix) {
600 continue;
601 }
602 if matches!(
603 write.value.as_ref().and_then(|value| value.kind.as_ref()),
604 Some(value::Kind::NullValue(_))
605 ) {
606 physical_keys.remove(key);
607 } else {
608 physical_keys.insert(key.clone());
609 }
610 }
611 sorted_instance_keys(&prefix, physical_keys)
612 }
613
614 pub fn publish<T: Value>(&mut self, channel: &Channel<T>, value: T) -> HandlerResult<()> {
616 self.publish_value(
617 channel.name(),
618 PersistenceKind::Channel,
619 None,
620 value_mapper::encode_handler(&value)?,
621 )
622 }
623
624 pub fn publish_map<T: Value>(
626 &mut self,
627 channel: &ChannelMap<T>,
628 instance: &str,
629 value: T,
630 ) -> HandlerResult<()> {
631 self.publish_value(
632 channel.name(),
633 PersistenceKind::ChannelMap,
634 Some(instance),
635 value_mapper::encode_handler(&value)?,
636 )
637 }
638
639 pub fn channel_size<T>(&self, channel: &Channel<T>) -> HandlerResult<usize> {
641 self.channel_size_value(channel.name(), PersistenceKind::Channel, None)
642 }
643
644 pub fn channel_map_size<T>(
646 &self,
647 channel: &ChannelMap<T>,
648 instance: &str,
649 ) -> HandlerResult<usize> {
650 self.channel_size_value(channel.name(), PersistenceKind::ChannelMap, Some(instance))
651 }
652
653 pub fn pending_channel_messages<T: Value>(
655 &self,
656 channel: &Channel<T>,
657 ) -> HandlerResult<Vec<ChannelMessage<T>>> {
658 self.pending_channel_messages_value(channel.name(), PersistenceKind::Channel, None)
659 }
660
661 pub fn pending_channel_map_messages<T: Value>(
663 &self,
664 channel: &ChannelMap<T>,
665 instance: &str,
666 ) -> HandlerResult<Vec<ChannelMessage<T>>> {
667 self.pending_channel_messages_value(
668 channel.name(),
669 PersistenceKind::ChannelMap,
670 Some(instance),
671 )
672 }
673
674 pub(crate) fn channel_map_keys<T>(
675 &self,
676 channel: &ChannelMap<T>,
677 ) -> HandlerResult<Vec<String>> {
678 self.registered_name(
679 channel.name(),
680 PersistenceKind::ChannelMap,
681 Some("key-check"),
682 )?;
683 let prefix = format!("{}/", channel.name());
684 let physical_keys = self
685 .channel_infos
686 .iter()
687 .filter(|(key, info)| key.starts_with(&prefix) && info.size > 0)
688 .map(|(key, _)| key.clone())
689 .collect::<HashSet<_>>();
690 sorted_instance_keys(&prefix, physical_keys)
691 }
692
693 pub fn channel_results<T: Value>(&self, channel: &Channel<T>) -> HandlerResult<Vec<T>> {
695 self.channel_results_value(channel.name(), PersistenceKind::Channel, None)
696 }
697
698 pub fn channel_map_results<T: Value>(
700 &self,
701 channel: &ChannelMap<T>,
702 instance: &str,
703 ) -> HandlerResult<Vec<T>> {
704 self.channel_results_value(channel.name(), PersistenceKind::ChannelMap, Some(instance))
705 }
706
707 pub fn write_stream<T: Value>(&mut self, stream: &Stream<T>, value: T) -> HandlerResult<()> {
718 let output_emitter = self.step_output_emitter()?.clone();
719 let definition = self
720 .flow
721 .persistence
722 .get(stream.name())
723 .filter(|definition| {
724 definition.kind == PersistenceKind::Stream
725 && definition.stream_identity == Some(stream.identity())
726 })
727 .ok_or_else(|| {
728 HandlerError::new(
729 "dex_sdk::HandlerError",
730 format!("Stream does not belong to Flow: {}", stream.name()),
731 )
732 })?;
733 if definition.stream_capacity_bytes != Some(stream.stream_capacity_bytes()) {
734 return Err(HandlerError::new(
735 "dex_sdk::HandlerError",
736 format!(
737 "Stream capacity does not match its registered definition: {}",
738 stream.name()
739 ),
740 ));
741 }
742 output_emitter.send_stream_write(StepStreamWrite {
743 stream_name: stream.name().to_string(),
744 stream_capacity_bytes: stream.stream_capacity_bytes(),
745 value: Some(value_mapper::encode_handler(&value)?),
746 })
747 }
748
749 pub(crate) fn prepare_buffered_text_stream(
750 &self,
751 stream: &Stream<String>,
752 ) -> HandlerResult<(
753 StepOutputEmitter,
754 InvocationCancellation,
755 tokio::runtime::Handle,
756 )> {
757 let output_emitter = self.step_output_emitter()?.clone();
758 let definition = self
759 .flow
760 .persistence
761 .get(stream.name())
762 .filter(|definition| {
763 definition.kind == PersistenceKind::Stream
764 && definition.stream_identity == Some(stream.identity())
765 })
766 .ok_or_else(|| {
767 HandlerError::new(
768 "dex_sdk::HandlerError",
769 format!("Stream does not belong to Flow: {}", stream.name()),
770 )
771 })?;
772 if definition.stream_capacity_bytes != Some(stream.stream_capacity_bytes()) {
773 return Err(HandlerError::new(
774 "dex_sdk::HandlerError",
775 format!(
776 "Stream capacity does not match its registered definition: {}",
777 stream.name()
778 ),
779 ));
780 }
781 let runtime = self.runtime.clone().ok_or_else(|| {
782 HandlerError::new(
783 "dex_sdk::HandlerError",
784 "Buffered Stream runtime is unavailable",
785 )
786 })?;
787 Ok((output_emitter, self.cancellation.clone(), runtime))
788 }
789
790 pub(crate) fn register_step_output_finalizer(
791 &mut self,
792 finalizer: Arc<dyn StepOutputFinalizer>,
793 ) -> HandlerResult<()> {
794 if self.step_outputs_finalized {
795 return Err(HandlerError::new(
796 "dex_sdk::HandlerError",
797 "Buffered Stream invocation has finished",
798 ));
799 }
800 self.step_output_finalizers.push(finalizer);
801 Ok(())
802 }
803
804 pub(crate) fn finalize_step_outputs<T>(
805 &mut self,
806 result: HandlerResult<T>,
807 ) -> HandlerResult<T> {
808 if self.step_outputs_finalized {
809 return result;
810 }
811 self.step_outputs_finalized = true;
812 let mut result = result;
813 for finalizer in &self.step_output_finalizers {
814 if let Err(finalization_failure) = finalizer.finalize_step_output() {
815 match &mut result {
816 Ok(_) => result = Err(finalization_failure),
817 Err(handler_failure) => {
818 handler_failure.attach_finalizer_error(&finalization_failure);
819 }
820 }
821 }
822 }
823 result
824 }
825
826 pub(crate) fn cancellation(&self) -> InvocationCancellation {
827 self.cancellation.clone()
828 }
829
830 pub(crate) fn take_outputs(self) -> InvocationOutputs {
831 InvocationOutputs {
832 attributes: self.attribute_writes.into_values().collect(),
833 locals: self.local_writes.into_values().collect(),
834 events: self.events,
835 publications: self.publications,
836 channel_deletions: self.channel_deletions,
837 }
838 }
839
840 fn step_output_emitter(&self) -> HandlerResult<&StepOutputEmitter> {
841 if self.method == InvocationMethod::Rpc {
842 return Err(HandlerError::new(
843 "dex_sdk::HandlerError",
844 "Step progress requires a Step Context",
845 ));
846 }
847 if self.cancellation.is_cancelled() {
848 return Err(HandlerError::new(
849 "dex_sdk::HandlerError",
850 "Step invocation is canceled",
851 ));
852 }
853 self.output_emitter.as_ref().ok_or_else(|| {
854 HandlerError::new("dex_sdk::HandlerError", "Step output stream is unavailable")
855 })
856 }
857
858 fn get_attribute_value<T: Value>(
859 &self,
860 name: &str,
861 kind: PersistenceKind,
862 instance: Option<&str>,
863 ) -> HandlerResult<Option<T>> {
864 let key = self.registered_name(name, kind, instance)?;
865 if kind == PersistenceKind::AttributeMap {
866 let is_loaded = self
867 .loaded_attribute_map_instances
868 .contains(&format!("{name}/"))
869 || self.loaded_attribute_map_instances.contains(&key);
870 if !is_loaded {
871 return Err(attribute_map_not_loaded(format!(
872 "AttributeMap instance was not loaded for this invocation: {key}"
873 )));
874 }
875 }
876 if let Some(write) = self.attribute_writes.get(&key) {
877 let value = write.value.as_ref().ok_or_else(|| {
878 HandlerError::new(
879 "dex_sdk::HandlerError",
880 format!("Attribute write {key} has no Value"),
881 )
882 })?;
883 if matches!(value.kind, Some(value::Kind::NullValue(_))) {
884 return Ok(None);
885 }
886 return value_mapper::decode_handler(value).map(Some);
887 }
888 self.attributes
889 .get(&key)
890 .map(value_mapper::decode_handler)
891 .transpose()
892 }
893
894 fn set_attribute_value(
895 &mut self,
896 name: &str,
897 kind: PersistenceKind,
898 instance: Option<&str>,
899 value: ProtoValue,
900 write_settings: AttributeWriteSettings,
901 ) -> HandlerResult<()> {
902 let key = self.registered_name(name, kind, instance)?;
903 let is_registered_hard_delete_on_null = self
904 .flow
905 .persistence
906 .get(name)
907 .is_some_and(|definition| definition.is_hard_delete_on_null);
908 require_registered_hard_delete_setting(
909 name,
910 is_registered_hard_delete_on_null,
911 write_settings.is_hard_delete_on_null,
912 )
913 .map_err(|error| HandlerError::new("dex_sdk::HandlerError", error))?;
914 let write = write_settings.attribute_write(key.clone(), value);
915 validate_hard_delete_attribute_write(&write)
916 .map_err(|error| HandlerError::new("dex_sdk::HandlerError", error))?;
917 if write.is_hard_delete_on_null {
918 self.negotiated_protocol_version
919 .require_hard_delete_attribute_support(&key)
920 .map_err(|error| HandlerError::new("dex_sdk::HandlerError", error))?;
921 }
922 self.attribute_writes.insert(key, write);
923 Ok(())
924 }
925
926 fn publish_value(
927 &mut self,
928 name: &str,
929 kind: PersistenceKind,
930 instance: Option<&str>,
931 value: ProtoValue,
932 ) -> HandlerResult<()> {
933 let channel_name = self.registered_name(name, kind, instance)?;
934 self.publications.push(ProtoChannelMessage {
935 channel_name: channel_name.clone(),
936 value: Some(value),
937 message_id: String::new(),
938 });
939 self.channel_infos
940 .entry(channel_name)
941 .and_modify(|info| info.size += 1)
942 .or_insert(ChannelInfo { size: 1 });
943 Ok(())
944 }
945
946 pub fn delete_channel_message<T>(
948 &mut self,
949 channel: &Channel<T>,
950 message_id: &str,
951 ) -> HandlerResult<()> {
952 self.delete_channel_message_value(
953 channel.name(),
954 PersistenceKind::Channel,
955 None,
956 message_id,
957 )
958 }
959
960 pub fn delete_channel_map_message<T>(
962 &mut self,
963 channel: &ChannelMap<T>,
964 instance: &str,
965 message_id: &str,
966 ) -> HandlerResult<()> {
967 self.delete_channel_message_value(
968 channel.name(),
969 PersistenceKind::ChannelMap,
970 Some(instance),
971 message_id,
972 )
973 }
974
975 fn delete_channel_message_value(
976 &mut self,
977 name: &str,
978 kind: PersistenceKind,
979 instance: Option<&str>,
980 message_id: &str,
981 ) -> HandlerResult<()> {
982 if message_id.is_empty() {
983 return Err(HandlerError::new(
984 "dex_sdk::HandlerError",
985 "Channel message ID must not be empty",
986 ));
987 }
988 let channel_name = self.registered_name(name, kind, instance)?;
989 self.channel_deletions.push(ChannelMessageDeletion {
990 channel_name: channel_name.clone(),
991 message_id: message_id.to_string(),
992 });
993 if let Some(info) = self.channel_infos.get_mut(&channel_name) {
994 info.size = info.size.saturating_sub(1);
995 }
996 Ok(())
997 }
998
999 fn channel_size_value(
1000 &self,
1001 name: &str,
1002 kind: PersistenceKind,
1003 instance: Option<&str>,
1004 ) -> HandlerResult<usize> {
1005 let channel_name = self.registered_name(name, kind, instance)?;
1006 Ok(self
1007 .channel_infos
1008 .get(&channel_name)
1009 .map_or(0, |info| usize::try_from(info.size).unwrap_or_default()))
1010 }
1011
1012 fn channel_results_value<T: Value>(
1013 &self,
1014 name: &str,
1015 kind: PersistenceKind,
1016 instance: Option<&str>,
1017 ) -> HandlerResult<Vec<T>> {
1018 let channel_name = self.registered_name(name, kind, instance)?;
1019 let Some(results) = &self.condition_results else {
1020 return Ok(Vec::new());
1021 };
1022 let mut decoded = Vec::new();
1023 for result in &results.channel_results {
1024 if result.channel_name == channel_name
1025 && result.condition_status == ConditionStatus::Completed as i32
1026 {
1027 for value in &result.values {
1028 decoded.push(value_mapper::decode_handler(value)?);
1029 }
1030 }
1031 }
1032 Ok(decoded)
1033 }
1034
1035 fn pending_channel_messages_value<T: Value>(
1036 &self,
1037 name: &str,
1038 kind: PersistenceKind,
1039 instance: Option<&str>,
1040 ) -> HandlerResult<Vec<ChannelMessage<T>>> {
1041 let physical_name = self.registered_name(name, kind, instance)?;
1042 let is_loaded = match kind {
1043 PersistenceKind::Channel => self.loaded_channel_names.contains(&physical_name),
1044 PersistenceKind::ChannelMap => {
1045 self.loaded_channel_map_instances
1046 .contains(&format!("{name}/"))
1047 || self.loaded_channel_map_instances.contains(&physical_name)
1048 }
1049 _ => false,
1050 };
1051 if !is_loaded {
1052 return Err(channel_messages_not_loaded(format!(
1053 "Channel messages were not loaded for this invocation: {physical_name}"
1054 )));
1055 }
1056 self.loaded_channel_messages
1057 .get(&physical_name)
1058 .map_or(&[][..], |values| values.messages.as_slice())
1059 .iter()
1060 .map(|message| {
1061 let value = message.value.as_ref().ok_or_else(|| {
1062 HandlerError::new(
1063 "dex_sdk::HandlerError",
1064 format!("Channel message {} has no Value", message.message_id),
1065 )
1066 })?;
1067 Ok(ChannelMessage {
1068 message_id: message.message_id.clone(),
1069 value: value_mapper::decode_handler(value)?,
1070 })
1071 })
1072 .collect()
1073 }
1074
1075 fn registered_name(
1076 &self,
1077 name: &str,
1078 kind: PersistenceKind,
1079 instance: Option<&str>,
1080 ) -> HandlerResult<String> {
1081 let definition = self.flow.persistence.get(name).ok_or_else(|| {
1082 HandlerError::new(
1083 "dex_sdk::HandlerError",
1084 format!("persistence definition does not belong to Flow: {name}"),
1085 )
1086 })?;
1087 if definition.kind != kind {
1088 return Err(HandlerError::new(
1089 "dex_sdk::HandlerError",
1090 format!("persistence definition kind does not match: {name}"),
1091 ));
1092 }
1093 match kind {
1094 PersistenceKind::AttributeMap | PersistenceKind::ChannelMap => {
1095 let instance = instance.ok_or_else(|| {
1096 HandlerError::new(
1097 "dex_sdk::HandlerError",
1098 format!("{name} requires an instance"),
1099 )
1100 })?;
1101 validate_map_instance(instance)
1102 .map_err(|error| HandlerError::new("dex_sdk::HandlerError", error))?;
1103 Ok(physical_name(name, instance))
1104 }
1105 PersistenceKind::Attribute | PersistenceKind::Channel if instance.is_none() => {
1106 Ok(name.to_string())
1107 }
1108 _ => Err(HandlerError::new(
1109 "dex_sdk::HandlerError",
1110 format!("static persistence definition cannot use an instance: {name}"),
1111 )),
1112 }
1113 }
1114}
1115
1116fn attribute_map_not_loaded(message: impl Into<String>) -> HandlerError {
1117 HandlerError::new("dex_sdk::AttributeMapNotLoadedError", message)
1118}
1119
1120fn channel_messages_not_loaded(message: impl Into<String>) -> HandlerError {
1121 HandlerError::new("dex_sdk::ChannelMessagesNotLoadedError", message)
1122}
1123
1124fn sorted_instance_keys(
1125 prefix: &str,
1126 physical_keys: HashSet<String>,
1127) -> HandlerResult<Vec<String>> {
1128 let mut keys = physical_keys
1129 .iter()
1130 .map(|key| {
1131 decode_instance(key, prefix)
1132 .map_err(|error| HandlerError::new("dex_sdk::HandlerError", error))
1133 })
1134 .collect::<HandlerResult<Vec<_>>>()?;
1135 keys.sort();
1136 Ok(keys)
1137}
1138
1139#[derive(Clone)]
1140pub(crate) struct InvocationCancellation {
1141 inner: Arc<InvocationCancellationInner>,
1142}
1143
1144struct InvocationCancellationInner {
1145 cancelled: AtomicBool,
1146 mutex: Mutex<()>,
1147 condition: Condvar,
1148 notification: tokio::sync::Notify,
1149}
1150
1151impl InvocationCancellation {
1152 pub(crate) fn new() -> Self {
1153 Self {
1154 inner: Arc::new(InvocationCancellationInner {
1155 cancelled: AtomicBool::new(false),
1156 mutex: Mutex::new(()),
1157 condition: Condvar::new(),
1158 notification: tokio::sync::Notify::new(),
1159 }),
1160 }
1161 }
1162
1163 fn wait(&self) {
1164 let mut guard = self.inner.mutex.lock().expect("cancellation lock");
1165 while !self.is_cancelled() {
1166 guard = self.inner.condition.wait(guard).expect("cancellation lock");
1167 }
1168 }
1169
1170 pub(crate) fn is_cancelled(&self) -> bool {
1171 self.inner.cancelled.load(Ordering::Acquire)
1172 }
1173
1174 pub(crate) fn cancel(&self) {
1175 let _guard = self.inner.mutex.lock().expect("cancellation lock");
1176 self.inner.cancelled.store(true, Ordering::Release);
1177 self.inner.condition.notify_all();
1178 self.inner.notification.notify_waiters();
1179 }
1180
1181 pub(crate) async fn cancelled(&self) {
1182 let notified = self.inner.notification.notified();
1183 if self.is_cancelled() {
1184 return;
1185 }
1186 notified.await;
1187 }
1188}
1189
1190fn system_time(timestamp: i64) -> SystemTime {
1191 if timestamp >= 0 {
1192 SystemTime::UNIX_EPOCH + Duration::from_secs(timestamp as u64)
1193 } else {
1194 SystemTime::UNIX_EPOCH - Duration::from_secs(timestamp.unsigned_abs())
1195 }
1196}
1197
1198fn map_values(kind: &str, entries: Vec<Kv>) -> HandlerResult<HashMap<String, ProtoValue>> {
1199 let mut mapped = HashMap::new();
1200 for entry in entries {
1201 require_name(&entry.key, kind)?;
1202 let value = entry.value.ok_or_else(|| {
1203 HandlerError::new(
1204 "dex_sdk::HandlerError",
1205 format!("{kind} {} has no Value", entry.key),
1206 )
1207 })?;
1208 if mapped.insert(entry.key.clone(), value).is_some() {
1209 return Err(HandlerError::new(
1210 "dex_sdk::HandlerError",
1211 format!("duplicate {kind} {}", entry.key),
1212 ));
1213 }
1214 }
1215 Ok(mapped)
1216}
1217
1218fn require_name(value: &str, kind: &str) -> HandlerResult<()> {
1219 if value.is_empty() {
1220 Err(HandlerError::new(
1221 "dex_sdk::HandlerError",
1222 format!("{kind} is required"),
1223 ))
1224 } else {
1225 Ok(())
1226 }
1227}
1228
1229#[cfg(test)]
1230#[path = "context_tests.rs"]
1231mod tests;