1use std::borrow::Cow;
4use std::net::SocketAddr;
5use std::path::PathBuf;
6
7use aion::EngineError;
8use aion_core::{ActivityId, WorkflowId};
9use aion_proto::WireError;
10use aion_store::StoreError;
11use thiserror::Error;
12
13#[path = "error_engine.rs"]
14mod engine;
15
16use engine::{durability_trace_fields, simple_engine_fields, store_trace_fields};
17#[path = "error_process_exit.rs"]
18mod process_exit;
19
20#[derive(Debug, Error)]
22pub enum ServerError {
23 #[error("configuration error: {message}")]
25 Config {
26 message: String,
28 },
29
30 #[error(
32 "unsafe store.data_dir `{}`: ancestor `{}` is not owner-controlled: {reason}; \
33 leave store.data_dir unset so it defaults beneath the private Aion home \
34 (`$AION_HOME`, default `$HOME/.aion`), or set a path whose ancestor chain is \
35 owner-only (a leading `~` expands against $HOME; a relative path resolves \
36 against the server's working directory)",
37 .data_root.display(),
38 .component.display()
39 )]
40 UnsafeDataRootAncestor {
41 data_root: PathBuf,
43 component: PathBuf,
45 reason: String,
47 },
48
49 #[error("{transport} transport failed at {address}: {message}")]
51 TransportBind {
52 transport: &'static str,
54 address: SocketAddr,
56 message: String,
58 },
59
60 #[error("{transport} transport task failed: {message}")]
62 Transport {
63 transport: &'static str,
65 message: String,
67 },
68
69 #[error("{listener} listener failed: {message}")]
71 SignalListener {
72 listener: &'static str,
74 message: String,
76 },
77
78 #[error("death note error: {message}")]
81 DeathNote {
82 message: String,
84 },
85
86 #[error("pid file error: {message}")]
88 PidFile {
89 message: String,
91 },
92
93 #[error(transparent)]
99 HomeAlreadyClaimed {
100 refusal: Box<crate::control::claim::HomeAlreadyClaimed>,
104 },
105
106 #[error("incarnation identity error: {message}")]
109 Incarnation {
110 message: String,
112 },
113
114 #[error("namespace error: {message}")]
116 Namespace {
117 message: String,
119 },
120
121 #[error("engine call failed: {source}")]
123 EngineCall {
124 #[from]
126 source: EngineError,
127 },
128
129 #[error("store backend failed: {source}")]
131 StoreBackend {
132 #[from]
134 source: StoreError,
135 },
136
137 #[error("stream failure: {failure}")]
139 Stream {
140 failure: StreamFailure,
142 },
143
144 #[error(
146 "worker dispatch failed for namespace {namespace}, activity type {activity_type}: {reason}"
147 )]
148 WorkerDispatch {
149 namespace: String,
151 activity_type: String,
153 reason: String,
155 },
156
157 #[error("worker connection lost during dispatch on {channel}: {detail}")]
170 WorkerConnectionLost {
171 channel: String,
173 detail: String,
175 },
176
177 #[error("worker connection busy during dispatch on {channel}: {detail}")]
188 WorkerBusy {
189 channel: String,
191 detail: String,
193 },
194
195 #[error("dispatch is unservable on {channel}: {detail}")]
214 WorkerDispatchUnservable {
215 channel: String,
217 detail: String,
220 },
221
222 #[error(
233 "pending activity collision for workflow {workflow_id}, activity {activity_id}: \
234 attempt {incoming_attempt} arrived while attempt {held_attempt} still holds this \
235 execution site, and does not supersede it"
236 )]
237 PendingActivityCollision {
238 workflow_id: WorkflowId,
240 activity_id: ActivityId,
242 held_attempt: u32,
244 incoming_attempt: u32,
246 },
247
248 #[error(
251 "activity completion rejected for workflow {workflow_id}, activity {activity_id}: {reason}"
252 )]
253 ActivityCompletionRejected {
254 workflow_id: WorkflowId,
256 activity_id: ActivityId,
258 reason: CompletionRejectionReason,
260 },
261
262 #[error(
273 "declared command for workflow {workflow_id}, activity {activity_id} attempt {attempt} \
274 is already executing at this server"
275 )]
276 DeclaredAttemptCollision {
277 workflow_id: WorkflowId,
279 activity_id: ActivityId,
281 attempt: u32,
283 },
284
285 #[error(
295 "declared command for workflow {workflow_id}, activity {activity_id} attempt {attempt} \
296 refused: this server is draining and starts no new work"
297 )]
298 DrainingRefusedDeclaredAttempt {
299 workflow_id: WorkflowId,
301 activity_id: ActivityId,
303 attempt: u32,
305 },
306
307 #[error("{resource} lock was poisoned")]
309 LockPoisoned {
310 resource: &'static str,
312 },
313
314 #[error("wire error: {wire}")]
316 Wire {
317 wire: WireError,
319 },
320}
321
322#[derive(Clone, Copy, Debug, Eq, Error, PartialEq)]
324pub enum CompletionRejectionReason {
325 #[error("completion token is missing (worker registration era is incompatible)")]
327 MissingCompletionToken,
328 #[error("no execution generation is currently accepting completion")]
330 NoCurrentGeneration,
331 #[error("completion token belongs to a stale execution generation")]
333 StaleGeneration,
334}
335
336#[derive(Clone, Copy, Debug, Eq, Error, PartialEq)]
338pub enum StreamFailure {
339 #[error("consumer lagged behind bounded buffer")]
341 Lagged,
342 #[error("subscriber connection closed")]
344 Closed,
345 #[error("engine event stream closed")]
347 UpstreamClosed,
348}
349
350impl From<WireError> for ServerError {
351 fn from(wire: WireError) -> Self {
352 Self::Wire { wire }
353 }
354}
355
356impl ServerError {
357 #[must_use]
360 pub fn to_wire_error(&self) -> WireError {
361 match self {
362 Self::Config { .. }
363 | Self::UnsafeDataRootAncestor { .. }
364 | Self::TransportBind { .. }
365 | Self::Transport { .. }
366 | Self::SignalListener { .. }
367 | Self::DeathNote { .. }
368 | Self::PidFile { .. }
369 | Self::HomeAlreadyClaimed { .. }
370 | Self::Incarnation { .. }
371 | Self::LockPoisoned { .. } => WireError::backend("server backend failure"),
372 Self::ActivityCompletionRejected { .. } => {
373 WireError::backend("stale activity completion rejected")
374 }
375 Self::PendingActivityCollision { .. } => {
376 WireError::backend("pending activity collision")
377 }
378 Self::DeclaredAttemptCollision { .. } => {
379 WireError::backend("declared command attempt collision")
380 }
381 Self::DrainingRefusedDeclaredAttempt { .. } => {
382 WireError::backend("declared command refused: server draining")
383 }
384 Self::WorkerDispatch { .. } => WireError::backend("worker dispatch failed"),
385 Self::WorkerConnectionLost { .. } => {
386 WireError::backend("worker connection lost during dispatch")
387 }
388 Self::WorkerBusy { .. } => WireError::backend("worker connection busy during dispatch"),
389 Self::WorkerDispatchUnservable { .. } => {
390 WireError::backend("dispatch frame exceeds the worker connection's outbound bound")
391 }
392 Self::Namespace { message } => WireError::namespace_denied(message.clone()),
393 Self::EngineCall { source } => wire_from_engine(source),
394 Self::StoreBackend { source } => wire_from_store(source),
395 Self::Stream { failure } => match failure {
396 StreamFailure::Lagged => WireError::lagged("subscriber lagged behind"),
397 StreamFailure::Closed | StreamFailure::UpstreamClosed => {
398 WireError::backend("event stream closed")
399 }
400 },
401 Self::Wire { wire } => wire.clone(),
402 }
403 }
404
405 #[must_use]
407 pub const fn is_config(&self) -> bool {
408 matches!(
414 self,
415 Self::Config { .. }
416 | Self::UnsafeDataRootAncestor { .. }
417 | Self::HomeAlreadyClaimed { .. }
418 )
419 }
420
421 #[must_use]
423 pub fn namespace_denied(message: impl Into<String>) -> Self {
424 Self::Namespace {
425 message: message.into(),
426 }
427 }
428
429 #[must_use]
437 pub fn placement_admission_denied(
438 namespace: &str,
439 worker_node: Option<&str>,
440 required: &std::collections::BTreeSet<String>,
441 ) -> Self {
442 let node = worker_node.unwrap_or("none");
443 let required = required
444 .iter()
445 .map(String::as_str)
446 .collect::<Vec<_>>()
447 .join(", ");
448 Self::namespace_denied(format!(
449 "worker registration rejected: namespace {namespace} is Pinned to node label(s) \
450 [{required}] but the worker advertises node {node}, which is not in the required set"
451 ))
452 }
453
454 #[must_use]
457 pub fn deploy_denied(message: impl Into<String>) -> Self {
458 Self::Wire {
459 wire: WireError::deploy_denied(message),
460 }
461 }
462
463 #[must_use]
473 pub fn grant_denied(message: impl Into<String>) -> Self {
474 Self::Wire {
475 wire: WireError::grant_denied(message),
476 }
477 }
478
479 #[must_use]
481 pub const fn lagged_stream() -> Self {
482 Self::Stream {
483 failure: StreamFailure::Lagged,
484 }
485 }
486
487 #[must_use]
489 pub fn worker_dispatch(
490 namespace: impl Into<String>,
491 activity_type: impl Into<String>,
492 reason: impl Into<String>,
493 ) -> Self {
494 Self::WorkerDispatch {
495 namespace: namespace.into(),
496 activity_type: activity_type.into(),
497 reason: reason.into(),
498 }
499 }
500
501 #[must_use]
504 pub fn worker_connection_lost(channel: impl Into<String>, detail: impl Into<String>) -> Self {
505 Self::WorkerConnectionLost {
506 channel: channel.into(),
507 detail: detail.into(),
508 }
509 }
510
511 #[must_use]
514 pub fn worker_dispatch_unservable(
515 channel: impl Into<String>,
516 detail: impl Into<String>,
517 ) -> Self {
518 Self::WorkerDispatchUnservable {
519 channel: channel.into(),
520 detail: detail.into(),
521 }
522 }
523
524 #[must_use]
530 pub const fn is_worker_connection_lost(&self) -> bool {
531 matches!(self, Self::WorkerConnectionLost { .. })
532 }
533
534 #[must_use]
537 pub fn worker_busy(channel: impl Into<String>, detail: impl Into<String>) -> Self {
538 Self::WorkerBusy {
539 channel: channel.into(),
540 detail: detail.into(),
541 }
542 }
543
544 #[must_use]
551 pub const fn is_worker_busy(&self) -> bool {
552 matches!(self, Self::WorkerBusy { .. })
553 }
554
555 #[must_use]
562 pub const fn is_worker_dispatch_unservable(&self) -> bool {
563 matches!(self, Self::WorkerDispatchUnservable { .. })
564 }
565
566 #[must_use]
568 pub const fn lock_poisoned(resource: &'static str) -> Self {
569 Self::LockPoisoned { resource }
570 }
571}
572
573#[derive(Clone)]
575pub struct ErrorTraceFields<'a> {
576 pub error_type: Cow<'a, str>,
578 pub store_error_type: Option<&'static str>,
580 pub reason: &'a dyn std::fmt::Display,
582}
583
584impl<'a> ErrorTraceFields<'a> {
585 fn plain(error_type: &'static str, reason: &'a dyn std::fmt::Display) -> Self {
587 Self {
588 error_type: Cow::Borrowed(error_type),
589 store_error_type: None,
590 reason,
591 }
592 }
593}
594
595impl ServerError {
596 #[must_use]
598 pub fn trace_fields(&self) -> ErrorTraceFields<'_> {
599 match self {
600 Self::Config { message } => ErrorTraceFields::plain("Config", message),
601 Self::UnsafeDataRootAncestor { reason, .. } => {
602 ErrorTraceFields::plain("UnsafeDataRootAncestor", reason)
603 }
604 Self::TransportBind { message, .. } => {
605 ErrorTraceFields::plain("TransportBind", message)
606 }
607 Self::Transport { message, .. } => ErrorTraceFields::plain("Transport", message),
608 Self::SignalListener { message, .. } => {
609 ErrorTraceFields::plain("SignalListener", message)
610 }
611 Self::PidFile { message } => ErrorTraceFields::plain("PidFile", message),
612 Self::HomeAlreadyClaimed { refusal } => {
613 ErrorTraceFields::plain("HomeAlreadyClaimed", refusal.as_ref())
614 }
615 Self::Incarnation { message } => ErrorTraceFields::plain("Incarnation", message),
616 Self::DeathNote { message } => ErrorTraceFields::plain("DeathNote", message),
617 Self::Namespace { message } => ErrorTraceFields::plain("Namespace", message),
618 Self::EngineCall { source } => engine_trace_fields(source),
619 Self::StoreBackend { source } => store_trace_fields(source),
620 Self::Stream { failure } => ErrorTraceFields::plain("Stream", failure),
621 Self::WorkerDispatch { reason, .. } => {
622 ErrorTraceFields::plain("WorkerDispatch", reason)
623 }
624 Self::WorkerConnectionLost { detail, .. } => {
625 ErrorTraceFields::plain("WorkerConnectionLost", detail)
626 }
627 Self::WorkerBusy { detail, .. } => ErrorTraceFields::plain("WorkerBusy", detail),
628 Self::WorkerDispatchUnservable { detail, .. } => {
629 ErrorTraceFields::plain("WorkerDispatchUnservable", detail)
630 }
631 Self::PendingActivityCollision { activity_id, .. } => {
632 ErrorTraceFields::plain("PendingActivityCollision", activity_id)
633 }
634 Self::DeclaredAttemptCollision { activity_id, .. } => {
635 ErrorTraceFields::plain("DeclaredAttemptCollision", activity_id)
636 }
637 Self::DrainingRefusedDeclaredAttempt { activity_id, .. } => {
638 ErrorTraceFields::plain("DrainingRefusedDeclaredAttempt", activity_id)
639 }
640 Self::ActivityCompletionRejected { reason, .. } => {
641 ErrorTraceFields::plain("ActivityCompletionRejected", reason)
642 }
643 Self::LockPoisoned { resource } => ErrorTraceFields::plain("LockPoisoned", resource),
644 Self::Wire { wire } => ErrorTraceFields {
645 error_type: wire
646 .error_type
647 .as_deref()
648 .map_or_else(|| Cow::Borrowed(wire.code.as_str()), Cow::Borrowed),
649 store_error_type: None,
650 reason: wire,
651 },
652 }
653 }
654}
655
656fn never_alive_error_type(source: &EngineError) -> &'static str {
668 match source {
669 EngineError::TerminalWriterUnavailable { .. } => "TerminalWriterUnavailable",
670 EngineError::TerminalWriterHeld { .. } => "TerminalWriterHeld",
671 EngineError::WorkflowWriterHeld { .. } => "WorkflowWriterHeld",
672 EngineError::WorkflowIdAlreadyLive { .. } => "WorkflowIdAlreadyLive",
673 EngineError::WorkflowWritersAmbiguous { .. } => "WorkflowWritersAmbiguous",
674 EngineError::RunIsRecoverable { .. } => "RunIsRecoverable",
675 EngineError::NoResidencyVerdict { .. } => "NoResidencyVerdict",
676 _ => "EngineError",
677 }
678}
679
680fn engine_trace_fields(source: &EngineError) -> ErrorTraceFields<'_> {
681 match source {
682 EngineError::WorkflowNotFound { .. } => simple_engine_fields("WorkflowNotFound", source),
683 EngineError::TerminalWriterUnavailable { .. }
685 | EngineError::TerminalWriterHeld { .. }
686 | EngineError::WorkflowWriterHeld { .. }
691 | EngineError::WorkflowIdAlreadyLive { .. }
692 | EngineError::WorkflowWritersAmbiguous { .. }
693 | EngineError::RunIsRecoverable { .. }
694 | EngineError::NoResidencyVerdict { .. } => {
695 simple_engine_fields(never_alive_error_type(source), source)
696 }
697 EngineError::InvalidState { .. } => simple_engine_fields("InvalidState", source),
698 EngineError::ScheduleNotFound { .. } => simple_engine_fields("ScheduleNotFound", source),
699 EngineError::ShuttingDown => simple_engine_fields("ShuttingDown", source),
700 EngineError::EngineTaskEpochClosed { .. } => {
701 simple_engine_fields("EngineTaskEpochClosed", source)
702 }
703 EngineError::Store(store) => store_trace_fields(store),
704 EngineError::Durability(durability) => durability_trace_fields(durability, source),
705 EngineError::MissingStore
706 | EngineError::MissingVisibilityStore
707 | EngineError::MissingStopDrainTimeout
708 | EngineError::ZeroStopDrainTimeout
709 | EngineError::ConflictingEventPublisher => builder_trace_fields(source),
710 EngineError::EventStreaming(_) => simple_engine_fields("EventStreaming", source),
711 EngineError::Load { .. } => simple_engine_fields("Load", source),
712 EngineError::UnenforceableContract { .. } => {
713 simple_engine_fields("UnenforceableContract", source)
714 }
715 EngineError::UnknownVersion { .. } => simple_engine_fields("UnknownVersion", source),
716 EngineError::VersionPinned { .. } => simple_engine_fields("VersionPinned", source),
717 EngineError::RouteActive { .. } => simple_engine_fields("RouteActive", source),
718 EngineError::ManifestMismatch { .. } => simple_engine_fields("ManifestMismatch", source),
719 EngineError::Package(_) => simple_engine_fields("Package", source),
720 EngineError::ContractIdentity { .. } => simple_engine_fields("ContractIdentity", source),
721 EngineError::NoQueueDeclaration { .. } => {
722 simple_engine_fields("NoQueueDeclaration", source)
723 }
724 EngineError::StartInputRefused { .. } => simple_engine_fields("StartInputRefused", source),
725 EngineError::SignalRefused { .. } => simple_engine_fields("SignalRefused", source),
726 EngineError::ActivityLeaseAfterTerminal { .. } => {
727 simple_engine_fields("ActivityLeaseAfterTerminal", source)
728 }
729 EngineError::Schedule { .. } => simple_engine_fields("Schedule", source),
730 EngineError::Runtime { .. } => simple_engine_fields("Runtime", source),
731 EngineError::Gate3BifReplacementMissing { .. } => {
732 simple_engine_fields("Gate3BifReplacementMissing", source)
733 }
734 EngineError::StartupRecoveryNotDeferred => {
735 simple_engine_fields("StartupRecoveryNotDeferred", source)
736 }
737 EngineError::StartupRecoveryAlreadyRan => {
738 simple_engine_fields("StartupRecoveryAlreadyRan", source)
739 }
740 EngineError::StartupCatchupBeforeWorkflowRecovery => {
741 simple_engine_fields("StartupCatchupBeforeWorkflowRecovery", source)
742 }
743 EngineError::StartupRecoverySlotPoisoned => {
744 simple_engine_fields("StartupRecoverySlotPoisoned", source)
745 }
746 EngineError::CleanupExecutorPoisoned => {
747 simple_engine_fields("CleanupExecutorPoisoned", source)
748 }
749 EngineError::CleanupExecutorShutdownTimedOut { .. } => {
750 simple_engine_fields("CleanupExecutorShutdownTimedOut", source)
751 }
752 EngineError::RunNotInHistory { .. } => simple_engine_fields("RunNotInHistory", source),
753 EngineError::ProcessExitRegistryPoisoned => {
754 simple_engine_fields("ProcessExitRegistryPoisoned", source)
755 }
756 EngineError::ProcessExitOwnershipPoisoned { .. } => {
757 simple_engine_fields("ProcessExitOwnershipPoisoned", source)
758 }
759 EngineError::ProcessExitStatePoisoned { .. }
760 | EngineError::ProcessExitSubscriptionUnavailable
761 | EngineError::ProcessExitDrainerSpawn { .. }
762 | EngineError::ProcessExitDrainerPoisoned
763 | EngineError::ProcessExitOutcomeMissingAfterEvent { .. }
764 | EngineError::ProcessExitEventStreamDisconnected
765 | EngineError::ProcessExitDrainerShutdownTimedOut { .. }
766 | EngineError::ProcessExitDrainerPanicked => process_exit::drainer_trace(source),
767 EngineError::ProcessExitCallbackDispatcherPoisoned
768 | EngineError::ProcessExitCallbackDispatcherUnavailable
769 | EngineError::ProcessExitCallbackDispatcherShutdownTimedOut { .. } => {
770 process_exit::callback_trace(source)
771 }
772 EngineError::ProcessExitAlreadyTerminal { .. } => {
773 simple_engine_fields("ProcessExitAlreadyTerminal", source)
774 }
775 EngineError::ActivityDeliveryPoisoned { .. } => {
776 simple_engine_fields("ActivityDeliveryPoisoned", source)
777 }
778 EngineError::RegistryPoisoned => simple_engine_fields("RegistryPoisoned", source),
779 EngineError::CatalogPoisoned => simple_engine_fields("CatalogPoisoned", source),
780 EngineError::NifRegistration { .. } => simple_engine_fields("NifRegistration", source),
781 EngineError::SignalRouter(_) => simple_engine_fields("SignalRouter", source),
782 EngineError::Query(query) => simple_engine_fields(engine::query_error_type(query), source),
783 }
784}
785
786fn builder_trace_fields(source: &EngineError) -> ErrorTraceFields<'_> {
789 match source {
790 EngineError::MissingStore => simple_engine_fields("MissingStore", source),
791 EngineError::MissingVisibilityStore => {
792 simple_engine_fields("MissingVisibilityStore", source)
793 }
794 EngineError::MissingStopDrainTimeout => {
795 simple_engine_fields("MissingStopDrainTimeout", source)
796 }
797 EngineError::ZeroStopDrainTimeout => simple_engine_fields("ZeroStopDrainTimeout", source),
798 EngineError::ConflictingEventPublisher => {
799 simple_engine_fields("ConflictingEventPublisher", source)
800 }
801 _ => simple_engine_fields("EngineBuilder", source),
802 }
803}
804
805fn wire_from_engine(source: &EngineError) -> WireError {
806 use EngineError as E;
807 use engine::backend_wire as backend;
808
809 match source {
810 EngineError::WorkflowNotFound { .. } => {
811 WireError::not_found_with_type("WorkflowNotFound", source.to_string())
812 }
813 EngineError::InvalidState { reason } => engine::invalid_state_wire(reason),
815 E::TerminalWriterUnavailable { .. }
821 | E::TerminalWriterHeld { .. }
822 | E::WorkflowWriterHeld { .. }
830 | E::WorkflowIdAlreadyLive { .. }
831 | E::WorkflowWritersAmbiguous { .. }
832 | E::RunIsRecoverable { .. }
833 | E::NoResidencyVerdict { .. } => engine::invalid_state_wire(&source.to_string())
834 .with_error_type(never_alive_error_type(source)),
835 EngineError::ScheduleNotFound { .. } => {
836 WireError::not_found_with_type("ScheduleNotFound", source.to_string())
837 }
838 EngineError::ShuttingDown => {
839 WireError::not_running_with_type("ShuttingDown", source.to_string())
840 }
841 E::EngineTaskEpochClosed { .. } => backend("EngineTaskEpochClosed", source),
862 E::ActivityLeaseAfterTerminal { .. } => engine::invalid_state_wire(&source.to_string())
868 .with_error_type("ActivityLeaseAfterTerminal"),
869 EngineError::Store(store) => wire_from_store(store),
870 EngineError::Durability(durability) => engine::durability_wire(durability, source),
871 E::MissingStore => backend("MissingStore", source),
872 E::MissingVisibilityStore => backend("MissingVisibilityStore", source),
873 E::MissingStopDrainTimeout => backend("MissingStopDrainTimeout", source),
874 E::ZeroStopDrainTimeout => backend("ZeroStopDrainTimeout", source),
875 E::ConflictingEventPublisher => backend("ConflictingEventPublisher", source),
876 E::EventStreaming(_) => backend("EventStreaming", source),
877 E::Load { .. } => backend("Load", source),
878 EngineError::UnenforceableContract { .. } => {
881 WireError::invalid_input(source.to_string()).with_error_type("UnenforceableContract")
882 }
883 EngineError::UnknownVersion { .. } => {
885 WireError::not_found_with_type("UnknownVersion", source.to_string())
886 }
887 EngineError::VersionPinned { .. } => {
888 WireError::version_pinned(source.to_string()).with_error_type("VersionPinned")
889 }
890 EngineError::RouteActive { .. } => {
891 WireError::version_pinned(source.to_string()).with_error_type("RouteActive")
892 }
893 EngineError::ManifestMismatch { .. } => {
894 WireError::invalid_input(source.to_string()).with_error_type("ManifestMismatch")
895 }
896 E::Package(_) => backend("Package", source),
897 E::ContractIdentity { .. } => engine::contract_refusal_wire("ContractIdentity", source),
898 E::NoQueueDeclaration { .. } => engine::contract_refusal_wire("NoQueueDeclaration", source),
899 E::StartInputRefused { .. } => engine::declared_contract_wire("StartInputRefused", source),
900 E::SignalRefused { .. } => engine::declared_contract_wire("SignalRefused", source),
901 EngineError::Schedule { .. } => backend("Schedule", source),
902 E::Runtime { .. } => backend("Runtime", source),
903 E::Gate3BifReplacementMissing { .. } => backend("Gate3BifReplacementMissing", source),
904 E::StartupRecoveryNotDeferred => backend("StartupRecoveryNotDeferred", source),
907 E::StartupRecoveryAlreadyRan => backend("StartupRecoveryAlreadyRan", source),
908 E::StartupCatchupBeforeWorkflowRecovery => {
909 backend("StartupCatchupBeforeWorkflowRecovery", source)
910 }
911 E::StartupRecoverySlotPoisoned => backend("StartupRecoverySlotPoisoned", source),
912 E::CleanupExecutorPoisoned => backend("CleanupExecutorPoisoned", source),
913 E::CleanupExecutorShutdownTimedOut { .. } => {
914 backend("CleanupExecutorShutdownTimedOut", source)
915 }
916 E::RunNotInHistory { .. } => backend("RunNotInHistory", source),
922 E::ProcessExitRegistryPoisoned => backend("ProcessExitRegistryPoisoned", source),
923 E::ProcessExitOwnershipPoisoned { .. } => backend("ProcessExitOwnershipPoisoned", source),
924 EngineError::ProcessExitStatePoisoned { .. }
925 | EngineError::ProcessExitSubscriptionUnavailable
926 | EngineError::ProcessExitDrainerSpawn { .. }
927 | EngineError::ProcessExitDrainerPoisoned
928 | EngineError::ProcessExitOutcomeMissingAfterEvent { .. }
929 | EngineError::ProcessExitEventStreamDisconnected
930 | EngineError::ProcessExitDrainerShutdownTimedOut { .. }
931 | EngineError::ProcessExitDrainerPanicked => process_exit::drainer_wire(source),
932 EngineError::ProcessExitCallbackDispatcherPoisoned
933 | EngineError::ProcessExitCallbackDispatcherUnavailable
934 | EngineError::ProcessExitCallbackDispatcherShutdownTimedOut { .. } => {
935 process_exit::callback_wire(source)
936 }
937 E::ProcessExitAlreadyTerminal { .. } => backend("ProcessExitAlreadyTerminal", source),
938 E::ActivityDeliveryPoisoned { .. } => backend("ActivityDeliveryPoisoned", source),
939 E::CatalogPoisoned => backend("CatalogPoisoned", source),
940 E::RegistryPoisoned => backend("RegistryPoisoned", source),
941 E::NifRegistration { .. } => backend("NifRegistration", source),
942 E::SignalRouter(_) => backend("SignalRouter", source),
943 EngineError::Query(query) => engine::query_wire(query, source),
944 }
945}
946
947fn wire_from_store(source: &StoreError) -> WireError {
948 match source {
949 StoreError::SequenceConflict { .. } => WireError::new_with_type(
950 aion_proto::WireErrorCode::SequenceConflict,
951 "SequenceConflict",
952 source.to_string(),
953 ),
954 StoreError::NotFound { .. } => {
955 WireError::not_found_with_type("NotFound", source.to_string())
956 }
957 StoreError::AssistantSessionNotFound { .. } => {
961 WireError::not_found_with_type("AssistantSessionNotFound", source.to_string())
962 }
963 StoreError::NotOwner { .. } => {
964 WireError::not_owner(source.to_string()).with_error_type("NotOwner")
965 }
966 StoreError::Backend(_) => WireError::backend_with_type("Backend", source.to_string()),
967 StoreError::Serialization(_) => {
968 WireError::backend_with_type("Serialization", source.to_string())
969 }
970 StoreError::InvalidQuery(_) => {
974 WireError::invalid_input(source.to_string()).with_error_type("InvalidQuery")
975 }
976 }
977}
978
979#[cfg(test)]
980#[path = "error_tests.rs"]
981mod tests;