Skip to main content

hataori_runtime/
error.rs

1use hataori_runtime_foundation::{
2    protocol::{ActionId, DomainId, LocalityId, ObjectId, ObjectLocation, ObjectTypeId, RequestId},
3    transport::TransportError,
4};
5use std::{fmt, time::Duration};
6
7pub const MAX_ERROR_BYTES: usize = 4096;
8
9#[derive(Clone, Copy, Debug, Eq, PartialEq)]
10pub enum RuntimeState {
11    Created,
12    Bootstrapping,
13    Running,
14    Draining,
15    Stopped,
16    Failed,
17}
18
19#[derive(Clone, Copy, Debug, Eq, PartialEq)]
20pub enum ResourceKind {
21    PendingCalls,
22    ActionQueue,
23    DedupEntries,
24    DedupBytes,
25    SendTickets,
26    Objects,
27    ObjectMailbox,
28    ResolverEntries,
29    LocalityLeases,
30    ObjectRoots,
31    PlacementTickets,
32    LeaseTransfers,
33    Migrations,
34    PreparedMigrations,
35    Forwarders,
36    SnapshotBytes,
37    SnapshotSegments,
38}
39
40#[derive(Clone, Debug, Eq, PartialEq)]
41pub enum ActionError {
42    Codec(String),
43    User(String),
44    Panic,
45}
46
47impl ActionError {
48    pub fn codec(message: impl Into<String>) -> Self {
49        Self::Codec(cap(message.into()))
50    }
51
52    pub fn user(message: impl Into<String>) -> Self {
53        Self::User(cap(message.into()))
54    }
55
56    pub(crate) fn message(&self) -> String {
57        match self {
58            Self::Codec(message) | Self::User(message) => message.clone(),
59            Self::Panic => "action handler panicked".into(),
60        }
61    }
62}
63
64impl fmt::Display for ActionError {
65    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
66        write!(formatter, "action error: {self:?}")
67    }
68}
69
70impl std::error::Error for ActionError {}
71
72#[derive(Clone, Debug, Eq, PartialEq)]
73pub enum RuntimeError {
74    InvalidLimits(&'static str),
75    BuilderSealed,
76    HandshakeNotPrepared,
77    InvalidState {
78        expected: RuntimeState,
79        actual: RuntimeState,
80    },
81    DuplicateAction(ActionId),
82    UnknownAction(ActionId),
83    UnknownDomain(DomainId),
84    DuplicateObjectType(ObjectTypeId),
85    UnknownObjectType(ObjectTypeId),
86    UnknownObject(ObjectId),
87    ObjectCollected(ObjectId),
88    StaleObjectLocation(ObjectId),
89    ObjectAction(String),
90    InvalidObjectTypeId,
91    InvalidObjectConcurrency,
92    PinnedObjectType(ObjectTypeId),
93    MigrationInProgress(ObjectId),
94    MigrationConflict(ObjectId),
95    Migration {
96        request: RequestId,
97        message: String,
98    },
99    MigrationRolledBack(ObjectId),
100    MigrationCommittedFailure {
101        object: ObjectId,
102        message: String,
103    },
104    SnapshotTooLarge {
105        bytes: usize,
106        limit: usize,
107    },
108    Moved {
109        object: ObjectId,
110        location: ObjectLocation,
111    },
112    RedirectLimit(ObjectId),
113    InvalidActionId,
114    InvalidSchema,
115    InvalidDeadline,
116    InvalidMembership(LocalityId),
117    ResourceExhausted {
118        resource: ResourceKind,
119        limit: usize,
120    },
121    DeadlineExceeded {
122        request: RequestId,
123        deadline: Duration,
124    },
125    Cancelled(RequestId),
126    RemoteAction {
127        request: RequestId,
128        message: String,
129    },
130    RemoteObject {
131        request: RequestId,
132        message: String,
133    },
134    Placement {
135        request: RequestId,
136        message: String,
137    },
138    Lease {
139        request: RequestId,
140        message: String,
141    },
142    LeaseTransferExpired(ObjectId),
143    DuplicateResultUnavailable(RequestId),
144    Protocol(String),
145    Transport(TransportError),
146    PeerFailed(LocalityId),
147    Shutdown,
148    ShutdownTimeout,
149    RetainedResources,
150}
151
152impl fmt::Display for RuntimeError {
153    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
154        write!(formatter, "runtime error: {self:?}")
155    }
156}
157
158impl std::error::Error for RuntimeError {}
159
160impl From<TransportError> for RuntimeError {
161    fn from(error: TransportError) -> Self {
162        Self::Transport(error)
163    }
164}
165
166pub(crate) fn cap(mut message: String) -> String {
167    if message.len() <= MAX_ERROR_BYTES {
168        return message;
169    }
170    let mut end = MAX_ERROR_BYTES;
171    while !message.is_char_boundary(end) {
172        end -= 1;
173    }
174    message.truncate(end);
175    message
176}