Skip to main content

triplox_client/
node.rs

1use anyhow::{Error, Result};
2use edn::query::ParsedQuery;
3
4use crate::ops::{QueryArg, TxOp};
5use crate::query::QueryResult;
6use crate::transaction::{TransactionResult, TxKey};
7
8#[allow(async_fn_in_trait)]
9pub trait SubmitNode {
10    async fn submit_tx<O: IntoTxOp>(&self, ops: Vec<O>) -> Result<TxKey, Error>;
11    async fn execute_tx<O: IntoTxOp>(&self, ops: Vec<O>) -> Result<TransactionResult, Error>;
12}
13
14/// Per-element conversion to `TxOp`. Lets `submit_tx`/`execute_tx` accept
15/// either `Vec<TxOp>` or `Vec<&str>`/`Vec<String>` (each string parsed as one EDN tx op).
16pub trait IntoTxOp {
17    fn into_tx_op(self) -> Result<TxOp, Error>;
18}
19
20impl IntoTxOp for TxOp {
21    fn into_tx_op(self) -> Result<TxOp, Error> {
22        Ok(self)
23    }
24}
25
26impl IntoTxOp for &str {
27    fn into_tx_op(self) -> Result<TxOp, Error> {
28        self.parse()
29    }
30}
31
32impl IntoTxOp for String {
33    fn into_tx_op(self) -> Result<TxOp, Error> {
34        self.as_str().into_tx_op()
35    }
36}
37
38pub fn collect_tx_ops<O: IntoTxOp>(ops: Vec<O>) -> Result<Vec<TxOp>, Error> {
39    ops.into_iter().map(IntoTxOp::into_tx_op).collect()
40}
41
42pub trait IntoQuery {
43    fn into_query(self) -> Result<ParsedQuery, Error>;
44}
45
46impl IntoQuery for ParsedQuery {
47    fn into_query(self) -> Result<ParsedQuery, Error> {
48        Ok(self)
49    }
50}
51
52// TODO: consider using Cow or a lifetime on the trait to avoid cloning
53impl IntoQuery for &ParsedQuery {
54    fn into_query(self) -> Result<ParsedQuery, Error> {
55        Ok(self.clone())
56    }
57}
58
59impl IntoQuery for &str {
60    fn into_query(self) -> Result<ParsedQuery, Error> {
61        self.parse()
62            .map_err(|e| anyhow::anyhow!("EDN parse error: {}", e))
63    }
64}
65
66impl IntoQuery for String {
67    fn into_query(self) -> Result<ParsedQuery, Error> {
68        self.as_str().into_query()
69    }
70}
71
72#[allow(async_fn_in_trait)]
73pub trait Database {
74    async fn query(&self, query: impl IntoQuery) -> Result<QueryResult, Error>;
75
76    async fn query_with_args(
77        &self,
78        query: &ParsedQuery,
79        args: &[QueryArg],
80    ) -> Result<QueryResult, Error>;
81}
82
83#[allow(async_fn_in_trait)]
84pub trait QueryNode {
85    type DB: Database;
86    async fn db(&self) -> Result<Self::DB, Error>;
87    async fn db_as_of(&self, tx_key: TxKey) -> Result<Self::DB, Error>;
88}