Skip to main content

keepsake_sqlx/repository/
types.rs

1use chrono::{DateTime, Utc};
2use keepsake::{ExpiryPolicy, Keepsake};
3use serde::{Deserialize, Serialize};
4use uuid::Uuid;
5
6#[cfg(feature = "postgres")]
7use sqlx::{Row, postgres::PgRow};
8
9/// Keyset cursor for active relation membership scans.
10#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
11pub struct MembershipCursor {
12    /// Last seen subject kind.
13    pub subject_kind: String,
14    /// Last seen subject id.
15    pub subject_id: String,
16    /// Last seen keepsake id.
17    pub keepsake_id: Uuid,
18}
19
20impl MembershipCursor {
21    /// Creates a cursor positioned after a returned keepsake.
22    #[must_use]
23    pub fn after(keepsake: &Keepsake) -> Self {
24        Self {
25            subject_kind: keepsake.subject().kind.clone(),
26            subject_id: keepsake.subject().id.clone(),
27            keepsake_id: keepsake.id(),
28        }
29    }
30}
31
32/// Result of an apply operation.
33#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
34pub struct AppliedKeepsake {
35    /// Created keepsake, or the existing active keepsake for duplicate applies.
36    pub keepsake: Keepsake,
37    /// Whether a duplicate active keepsake was prevented.
38    pub duplicate_prevented: bool,
39}
40
41/// Due timed expiry candidate.
42#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
43#[cfg_attr(feature = "postgres", derive(sqlx::FromRow))]
44pub struct TimedExpiryCandidate {
45    /// Keepsake id.
46    pub keepsake_id: Uuid,
47    /// Relation id.
48    pub relation_id: Uuid,
49    /// Subject kind.
50    pub subject_kind: String,
51    /// Subject id.
52    pub subject_id: String,
53    /// Due timestamp.
54    pub due_at: DateTime<Utc>,
55}
56
57/// Due fulfillment expiry candidate.
58#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
59pub struct FulfilledExpiryCandidate {
60    /// Keepsake id.
61    pub keepsake_id: Uuid,
62    /// Relation id.
63    pub relation_id: Uuid,
64    /// Subject kind.
65    pub subject_kind: String,
66    /// Subject id.
67    pub subject_id: String,
68    /// Copied expiry policy.
69    pub expiry_policy: ExpiryPolicy,
70}
71
72#[cfg(feature = "postgres")]
73impl<'row> sqlx::FromRow<'row, PgRow> for FulfilledExpiryCandidate {
74    fn from_row(row: &'row PgRow) -> Result<Self, sqlx::Error> {
75        let expiry_policy = serde_json::from_value(row.try_get("expiry_policy")?)
76            .map_err(|error| sqlx::Error::Decode(Box::new(error)))?;
77        Ok(Self {
78            keepsake_id: row.try_get("keepsake_id")?,
79            relation_id: row.try_get("relation_id")?,
80            subject_kind: row.try_get("subject_kind")?,
81            subject_id: row.try_get("subject_id")?,
82            expiry_policy,
83        })
84    }
85}