Skip to main content

loonfs_core/commit/
publish_error.rs

1//! [`CommitHeadPublishError`]: failures of the segment PUT and head
2//! compare-and-swap.
3
4use loonfs_api::{ChangeSeq, NamespaceId, WriterEpoch};
5use serde::{Deserialize, Serialize};
6use thiserror::Error;
7
8#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Error)]
9pub enum CommitHeadPublishError {
10    #[error("expected head etag must not be empty")]
11    EmptyExpectedHeadEtag,
12    #[error("publish namespace mismatch: head `{head}`, plan `{plan}`")]
13    NamespaceMismatch {
14        head: NamespaceId,
15        plan: NamespaceId,
16    },
17    #[error("WAL segment namespace mismatch: head `{head}`, wal `{wal}`")]
18    WalSegmentNamespaceMismatch { head: NamespaceId, wal: NamespaceId },
19    #[error("WAL segment writer epoch mismatch: expected `{expected}`, actual `{actual}`")]
20    WalSegmentWriterEpochMismatch {
21        expected: WriterEpoch,
22        actual: WriterEpoch,
23    },
24    #[error("WAL segment base head seq mismatch: expected `{expected}`, actual `{actual}`")]
25    WalSegmentBaseHeadSeqMismatch {
26        expected: ChangeSeq,
27        actual: ChangeSeq,
28    },
29    #[error("WAL segment start seq mismatch: expected `{expected}`, actual `{actual}`")]
30    WalSegmentStartSeqMismatch {
31        expected: ChangeSeq,
32        actual: ChangeSeq,
33    },
34    #[error("WAL segment end seq mismatch: expected `{expected}`, actual `{actual}`")]
35    WalSegmentEndSeqMismatch {
36        expected: ChangeSeq,
37        actual: ChangeSeq,
38    },
39    #[error("WAL segment contains no records")]
40    EmptyWalSegment,
41    /// The successor head this publish built does not carry the
42    /// namespace's immutable identity forward. A construction bug, caught
43    /// before the compare-and-swap so it can never become durable.
44    #[error("{0}")]
45    HeadIdentityDrift(loonfs_api::wire::control::HeadIdentityDrift),
46    #[error("sequence counter overflow")]
47    SeqOverflow,
48    #[error("namespace head changed since the publish view was loaded")]
49    StaleHead,
50    /// The self-enforced publish budget elapsed between starting the WAL
51    /// segment PUT and reaching the head CAS. The segment is abandoned as an
52    /// orphan for GC and the commit must be rebuilt as a fresh segment, so
53    /// callers retry exactly as they do for `StaleHead`.
54    #[error("publish budget exceeded: elapsed `{elapsed_ms}` ms over budget `{budget_ms}` ms")]
55    PublishBudgetExceeded { elapsed_ms: u64, budget_ms: u64 },
56    /// The head compare-and-swap was sent but its outcome was never
57    /// observed (for example, a transport failure waiting for the
58    /// response). The commit may or may not be visible.
59    #[error("head compare-and-swap outcome unknown: {0}")]
60    OutcomeUnknown(String),
61    #[error("head codec error for `{object_key}`: {message}")]
62    Codec { object_key: String, message: String },
63    #[error("head object store error for `{object_key}`: {message}")]
64    Store { object_key: String, message: String },
65}