Skip to main content

coven_core/
write.rs

1//! Durable identity and publication status for one host transaction.
2
3use std::fmt;
4
5use serde::{Deserialize, Serialize};
6
7use crate::sync::store_commit::{StoreBatchCommitRef, StoreSerialPredecessor};
8
9/// Store-wide ordering policy selected by the application and signed into the
10/// Store protocol root.
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
12#[serde(rename_all = "snake_case")]
13pub enum WritePolicy {
14    MergeConcurrent,
15    Serial,
16}
17
18/// Stable identity of one successfully committed host transaction.
19#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
20#[serde(transparent)]
21pub struct WriteId(String);
22
23impl WriteId {
24    pub(crate) fn from_generated(value: String) -> Self {
25        Self(value)
26    }
27
28    pub fn as_str(&self) -> &str {
29        &self.0
30    }
31}
32
33impl fmt::Display for WriteId {
34    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
35        formatter.write_str(&self.0)
36    }
37}
38
39/// Exact policy-specific position that made a write visible to peers.
40#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
41#[serde(rename_all = "snake_case", deny_unknown_fields)]
42pub enum PublishedPosition {
43    MergeConcurrent {
44        device_id: String,
45        commit: StoreBatchCommitRef,
46    },
47    Serial {
48        commit: StoreBatchCommitRef,
49    },
50}
51
52impl PublishedPosition {
53    pub fn commit(&self) -> &StoreBatchCommitRef {
54        match self {
55            Self::MergeConcurrent { commit, .. } | Self::Serial { commit } => commit,
56        }
57    }
58}
59
60/// Stable identity of the one ordered provisional Serial branch.
61#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
62#[serde(transparent)]
63pub struct PendingBranchId(WriteId);
64
65impl PendingBranchId {
66    pub(crate) fn from_first_write(write_id: WriteId) -> Self {
67        Self(write_id)
68    }
69
70    pub fn first_write_id(&self) -> &WriteId {
71        &self.0
72    }
73}
74
75/// A Serial branch ran against `base`, but storage now commits `current`.
76#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
77#[serde(deny_unknown_fields)]
78pub struct SerializationConflict {
79    pub branch_id: PendingBranchId,
80    pub base: StoreSerialPredecessor,
81    pub current: StoreSerialPredecessor,
82}
83
84/// A semantic write fault. Retrying transport cannot change this result.
85#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
86#[serde(rename_all = "snake_case", deny_unknown_fields)]
87pub enum WriteBlock {
88    InvalidPackage { reason: String },
89    InvalidProtocolState { reason: String },
90    MissingBlob { namespace: String, id: String },
91    LocalUserBlob { namespace: String, id: String },
92}
93
94/// Current durable state of one host transaction.
95#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
96#[serde(rename_all = "snake_case", deny_unknown_fields)]
97pub enum WriteStatus {
98    LocalOnly,
99    Pending,
100    Publishing,
101    Published(Box<PublishedPosition>),
102    Conflict(Box<SerializationConflict>),
103    Blocked(WriteBlock),
104    Resolved(WriteResolution),
105}
106
107#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
108#[serde(rename_all = "snake_case", deny_unknown_fields)]
109pub enum WriteResolution {
110    Discarded,
111    Replaced { replacement: WriteId },
112}
113
114/// One table/primary-key identity affected by the shared part of a write.
115#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
116#[serde(deny_unknown_fields)]
117pub struct AffectedRow {
118    pub table: String,
119    pub primary_key: String,
120}
121
122/// Durable write information returned by `CovenHandle::pending_writes`.
123#[derive(Debug, Clone, PartialEq, Eq)]
124pub struct PendingWrite {
125    pub write_id: WriteId,
126    pub status: WriteStatus,
127    pub affected_rows: Vec<AffectedRow>,
128}
129
130#[derive(Debug, Clone, PartialEq, Eq)]
131pub struct PendingBranch {
132    pub branch_id: PendingBranchId,
133    pub base: StoreSerialPredecessor,
134    pub current: StoreSerialPredecessor,
135    pub writes: Vec<PendingWrite>,
136}
137
138/// Result of one successful host transaction and its durable publication identity.
139#[derive(Debug, Clone, PartialEq, Eq)]
140pub struct WriteReceipt<R> {
141    pub value: R,
142    pub write_id: WriteId,
143    pub status: WriteStatus,
144    /// The ordered provisional branch containing this write. MergeConcurrent
145    /// writes and transactions with no synchronized changes have no branch.
146    pub pending_branch_id: Option<PendingBranchId>,
147}