sqlx_ledger/tx_template/
repo.rs

1use cached::proc_macro::cached;
2use sqlx::{Pool, Postgres};
3use std::sync::Arc;
4use tracing::instrument;
5
6use super::{core::*, entity::*};
7use crate::{error::*, primitives::*};
8
9/// Provides methods to interact with `TxTemplateCore` entities.
10#[derive(Debug, Clone)]
11pub struct TxTemplates {
12    pool: Pool<Postgres>,
13}
14
15impl TxTemplates {
16    pub fn new(pool: &Pool<Postgres>) -> Self {
17        Self { pool: pool.clone() }
18    }
19
20    #[instrument(name = "sqlx_ledger.tx_templates.create", skip_all)]
21    pub async fn create(
22        &self,
23        NewTxTemplate {
24            id,
25            code,
26            description,
27            params,
28            tx_input,
29            entries,
30            metadata,
31        }: NewTxTemplate,
32    ) -> Result<TxTemplateId, SqlxLedgerError> {
33        let params_json = serde_json::to_value(&params)?;
34        let tx_input_json = serde_json::to_value(&tx_input)?;
35        let entries_json = serde_json::to_value(&entries)?;
36        let record = sqlx::query!(
37            r#"INSERT INTO sqlx_ledger_tx_templates (id, code, description, params, tx_input, entries, metadata)
38            VALUES ($1, $2, $3, $4, $5, $6, $7)
39            RETURNING id, version, created_at"#,
40            id as TxTemplateId,
41            code,
42            description,
43            params_json,
44            tx_input_json,
45            entries_json,
46            metadata
47        )
48        .fetch_one(&self.pool)
49        .await?;
50        Ok(TxTemplateId::from(record.id))
51    }
52
53    #[instrument(level = "trace", name = "sqlx_ledger.tx_templates.find_core", skip_all)]
54    pub(crate) async fn find_core(
55        &self,
56        code: &str,
57    ) -> Result<Arc<TxTemplateCore>, SqlxLedgerError> {
58        cached_find_core(&self.pool, code).await
59    }
60}
61
62#[cached(
63    key = "String",
64    convert = r#"{ code.to_string() }"#,
65    result = true,
66    sync_writes = true
67)]
68async fn cached_find_core(
69    pool: &Pool<Postgres>,
70    code: &str,
71) -> Result<Arc<TxTemplateCore>, SqlxLedgerError> {
72    let record = sqlx::query!(
73            r#"SELECT id, code, params, tx_input, entries FROM sqlx_ledger_tx_templates WHERE code = $1 LIMIT 1"#,
74            code
75        )
76        .fetch_one(pool)
77        .await?;
78    let params = match record.params {
79        Some(serde_json::Value::Null) => None,
80        Some(params) => Some(serde_json::from_value(params)?),
81        None => None,
82    };
83    let tx_input = serde_json::from_value(record.tx_input)?;
84    Ok(Arc::new(TxTemplateCore {
85        id: TxTemplateId::from(record.id),
86        _code: record.code,
87        params,
88        entries: serde_json::from_value(record.entries)?,
89        tx_input,
90    }))
91}