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