Skip to main content

tablo_core/resource/
commit.rs

1//! What a mutation committed, and the one place the framework says so.
2
3use topcoat::context::Cx;
4
5use super::{Action, Resource};
6
7/// The kind of mutation a record fn performed.
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9#[non_exhaustive]
10pub enum Mutation {
11    Create,
12    Update,
13    Delete,
14    /// The custom action of this [`NAME`](super::Action::NAME).
15    Action(&'static str),
16}
17
18/// What one committed mutation wrote.
19#[derive(Debug, Clone)]
20pub struct Committed<M> {
21    mutation: Mutation,
22    records: Vec<M>,
23}
24
25impl<M> Committed<M> {
26    /// The row a create wrote.
27    pub fn created(record: M) -> Self {
28        Self {
29            mutation: Mutation::Create,
30            records: vec![record],
31        }
32    }
33
34    /// The row an update wrote, as it stands after the write.
35    pub fn updated(record: M) -> Self {
36        Self {
37            mutation: Mutation::Update,
38            records: vec![record],
39        }
40    }
41
42    /// The rows a delete removed, as they were before the delete.
43    pub fn deleted(records: Vec<M>) -> Self {
44        Self {
45            mutation: Mutation::Delete,
46            records,
47        }
48    }
49
50    /// The rows a custom [`Action`](super::Action) `A` ran on.
51    pub fn acted<R: Resource<Model = M>, A: Action<R>>(records: Vec<M>) -> Self {
52        Self {
53            mutation: Mutation::Action(A::NAME),
54            records,
55        }
56    }
57
58    /// Which record fn or custom action ran.
59    pub fn mutation(&self) -> Mutation {
60        self.mutation
61    }
62
63    /// The rows the mutation wrote, in the order the handler had them.
64    pub fn records(&self) -> &[M] {
65        &self.records
66    }
67}
68
69/// Deliver a committed mutation to the app.
70///
71/// A hook returning `Err` is logged and ignored: the write stays committed.
72pub(crate) async fn run_after_commit<R: Resource>(cx: &Cx, committed: Committed<R::Model>) {
73    if let Err(error) = R::after_commit(cx, committed).await {
74        tracing::error!(
75            error = %error,
76            resource = std::any::type_name::<R>(),
77            "after_commit failed; the write stays committed"
78        );
79    }
80}
81
82#[cfg(test)]
83mod tests;