pub enum KnlError {
Busy(String),
Storage(String),
Corruption(String),
Closed(String),
Validation(String),
Unsupported(String),
Timeout(String),
Refused(String),
}Expand description
What went wrong in the kernel core, classified.
A failure is not one thing. A contended database will succeed if it is asked again; a row that will not decode never will. A caller that passed a negative amount has a bug in its own code; a caller that wrote to a closed handle has finished with the session and needs a new one. Folding all four into one opaque string leaves every caller — the Lua shell most of all — matching on message text to tell them apart, and message text is the one part of an error that is meant to change.
So the variant is the classification, and it is the whole of it: the
payload is a human-readable sentence and nothing a caller should branch
on. KnlError::kind names the class in one stable word, and
KnlError::is_retryable answers the only question whose answer is a
program’s rather than a person’s.
The core does not know which Lua method the caller invoked, so the
message carries the reason only; the adapter renders the
knl: <method>: <kind>: <reason> attribution.
Variants§
Busy(String)
Lock contention: the store was busy and the same call may succeed if
it is made again. The one retryable class (KnlError::is_retryable).
Storage(String)
The store could not do the work — an IO fault, a connection that is gone, an encode failure on the way in. Not busy, so retrying it is a caller’s gamble rather than the kernel’s advice.
Corruption(String)
A stored row could not be read back as the event it was written as.
Distinct from KnlError::Storage on purpose: the IO succeeded and
the bytes came back, so what is wrong is the data, and no retry and
no reconnect will change it.
Closed(String)
The session is over — this handle closed, or a resume was pointed at a stream whose log already carries its ending. A session is disposable, so the answer is to open another, not to try again.
Validation(String)
The caller asked for something the kernel refuses to record: an event that does not meet its kind’s shape, a kernel-only kind, a negative amount, an unknown view or a malformed option. Nothing was written.
Unsupported(String)
The request is well-formed but this backend cannot serve it — a query put to a store that keeps no queryable table.
Internal to the SPI: nothing a Lua caller does produces one today.
Both sites that raise it are EventStore trait defaults — the
query a backend with no table cannot answer, and the two-stream
append_if_many a backend with one stream cannot write — and the only
backend the product has (SqliteEventStore) overrides both. The
shape a caller might expect here answers differently on purpose: an
unknown view name is a KnlError::Validation, because the argument
was wrong and the message says which.
It stays in the vocabulary all the same, and is published to Lua with
the rest (KnlError::KINDS): a store may return it — the trait
says so — and a class a backend can produce but a caller was never told
about is a class nobody handles. A test double that keeps one stream
reaches both defaults today.
Timeout(String)
A read ran past the time it was given and was cut short. Distinct
from KnlError::Busy on purpose: nothing was contended, the work
itself was too slow, so making the same call again buys nothing —
what changes the answer is a narrower query or a longer deadline.
Refused(String)
A quota did not cover what was asked for, and the refusal was recorded.
The one class that reports a decision rather than a fault. Nothing
is wrong: the request was well-formed, the store answered, and the
answer is no — Session::open_child raises it when the parent’s
balance will not cover the allocation, having written the
budget_refused that says so. Distinct from
KnlError::Validation because the caller’s arguments were fine, and
not retryable, because the same call against the same balance gets the
same answer; what changes it is the owner granting more.
Session::reserve does not raise this — it answers false,
because a reservation is asked for in a loop that is expected to be
told no. An allocation is not: it either produced a child or it did
not, and there is no half-opened session to hand back.
Implementations§
Source§impl KnlError
impl KnlError
Sourcepub const BUSY: &'static str = "busy"
pub const BUSY: &'static str = "busy"
The stable name of the KnlError::Busy class.
Sourcepub const STORAGE: &'static str = "storage"
pub const STORAGE: &'static str = "storage"
The stable name of the KnlError::Storage class.
Sourcepub const CORRUPTION: &'static str = "corruption"
pub const CORRUPTION: &'static str = "corruption"
The stable name of the KnlError::Corruption class.
Sourcepub const CLOSED: &'static str = "closed"
pub const CLOSED: &'static str = "closed"
The stable name of the KnlError::Closed class.
Sourcepub const VALIDATION: &'static str = "validation"
pub const VALIDATION: &'static str = "validation"
The stable name of the KnlError::Validation class.
Sourcepub const UNSUPPORTED: &'static str = "unsupported"
pub const UNSUPPORTED: &'static str = "unsupported"
The stable name of the KnlError::Unsupported class.
Sourcepub const TIMEOUT: &'static str = "timeout"
pub const TIMEOUT: &'static str = "timeout"
The stable name of the KnlError::Timeout class.
Sourcepub const REFUSED: &'static str = "refused"
pub const REFUSED: &'static str = "refused"
The stable name of the KnlError::Refused class.
Sourcepub const KINDS: &'static [&'static str]
pub const KINDS: &'static [&'static str]
Every class a kernel failure can have, in one closed list.
Published so a caller can hold its own error vocabulary against the
kernel’s — the Lua bridge hands this to knl.api(), and the shell’s
declaration is checked against it rather than against a list somebody
retyped.
Sourcepub fn kind(&self) -> &'static str
pub fn kind(&self) -> &'static str
This failure’s class, as one of KnlError::KINDS.
Sourcepub fn is_retryable(&self) -> bool
pub fn is_retryable(&self) -> bool
Whether making the same call again could succeed.
True for KnlError::Busy and nothing else. A storage fault might
clear, but the kernel does not know that it will, and an error that
says “try again” when it means “maybe” is how a retry loop becomes an
infinite one.
Sourcepub fn kind_is_retryable(kind: &str) -> bool
pub fn kind_is_retryable(kind: &str) -> bool
Whether a class name is the retryable one.
The same answer as KnlError::is_retryable, for a caller that has
the word rather than the value — the Lua bridge, which parses a kind
back out of an attributed message.
Trait Implementations§
impl Eq for KnlError
Source§impl Error for KnlError
impl Error for KnlError
1.30.0 · Source§fn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
1.0.0 · Source§fn description(&self) -> &str
fn description(&self) -> &str
use the Display impl or to_string()
Source§impl From<Error> for KnlError
Classify a rusqlite error into the kernel’s vocabulary.
impl From<Error> for KnlError
Classify a rusqlite error into the kernel’s vocabulary.
The store’s own SQL goes through eventsdb, which has its own classification
(From<eventsdb_core::Error>); what is left on this path is the SQL the
kernel runs itself — the legacy migration’s plain connection
(super::logs). The split is the one the caller can act on: a contended
lock is KnlError::Busy — the same call may succeed if it is made again
— and everything else is KnlError::Storage, a fault the kernel cannot
promise anything about. Matched on the SQLite error code, never the
message text, so the classification does not drift with a library’s
wording.
Source§impl From<Error> for KnlError
Translate the store’s failure into the kernel’s vocabulary.
impl From<Error> for KnlError
Translate the store’s failure into the kernel’s vocabulary.
One class each, because the two vocabularies were drawn along the same line — what a caller can do about it — and the six that exist on both sides mean the same thing on both sides. The message travels as it was written: it is the reason, and the kernel renders the class itself.
The rest go to KnlError::Storage with their text. Truncated,
HeadMismatch, and the two retention refusals are answers to calls this
kernel does not make — nothing here removes history, and no append names
the head it expects — so a caller meeting one is meeting the store failing
to do the work, which is what Storage says. The enum is
#[non_exhaustive], so a class added later lands there too rather than
failing to compile.
impl StructuralPartialEq for KnlError
Auto Trait Implementations§
impl Freeze for KnlError
impl RefUnwindSafe for KnlError
impl Send for KnlError
impl Sync for KnlError
impl Unpin for KnlError
impl UnsafeUnpin for KnlError
impl UnwindSafe for KnlError
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<E> ExternalError for E
impl<E> ExternalError for E
fn into_lua_err(self) -> Error
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreimpl<T> MaybeSend for T
impl<T> MaybeSync for T
Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
Source§impl<T> ToStringFallible for Twhere
T: Display,
impl<T> ToStringFallible for Twhere
T: Display,
Source§fn try_to_string(&self) -> Result<String, TryReserveError>
fn try_to_string(&self) -> Result<String, TryReserveError>
ToString::to_string, but without panic on OOM.