ns_indexer/db/
model_service_protocol.rs

1use ns_axum_web::erring::HTTPError;
2use ns_scylla_orm::{ColumnsMap, ToCqlVal};
3use ns_scylla_orm_macros::CqlOrm;
4
5use ns_protocol::state;
6
7use crate::db::scylladb;
8
9#[derive(Debug, Default, Clone, CqlOrm, PartialEq)]
10pub struct ServiceProtocol {
11    pub code: i64,
12    pub version: i32,
13    pub protocol: Vec<u8>,
14    pub submitter: String,
15    pub sequence: i64,
16
17    pub _fields: Vec<String>, // selected fields,field with `_` will be ignored by CqlOrm
18}
19
20impl ServiceProtocol {
21    pub fn with_pk(code: i64, version: i32) -> Self {
22        Self {
23            code,
24            version,
25            ..Default::default()
26        }
27    }
28
29    pub fn from_index(value: &state::ServiceProtocol) -> anyhow::Result<Self> {
30        let protocol = state::to_bytes(&value.protocol)?;
31        Ok(Self {
32            code: value.code as i64,
33            version: value.version as i32,
34            protocol,
35            submitter: value.submitter.clone(),
36            sequence: value.sequence as i64,
37            _fields: Self::fields(),
38        })
39    }
40
41    pub fn to_index(&self) -> anyhow::Result<state::ServiceProtocol> {
42        let protocol = state::from_bytes(&self.protocol)?;
43        Ok(state::ServiceProtocol {
44            code: self.code as u64,
45            version: self.version as u16,
46            protocol,
47            submitter: self.submitter.clone(),
48            sequence: self.sequence as u64,
49        })
50    }
51
52    pub fn select_fields(select_fields: Vec<String>, with_pk: bool) -> anyhow::Result<Vec<String>> {
53        if select_fields.is_empty() {
54            return Ok(Self::fields());
55        }
56
57        let fields = Self::fields();
58        let mut select_fields = select_fields;
59        for field in &select_fields {
60            if !fields.contains(field) {
61                return Err(HTTPError::new(400, format!("Invalid field: {}", field)).into());
62            }
63        }
64
65        let field = "submitter".to_string();
66        if !select_fields.contains(&field) {
67            select_fields.push(field);
68        }
69        let field = "sequence".to_string();
70        if !select_fields.contains(&field) {
71            select_fields.push(field);
72        }
73
74        if with_pk {
75            let field = "code".to_string();
76            if !select_fields.contains(&field) {
77                select_fields.push(field);
78            }
79            let field = "version".to_string();
80            if !select_fields.contains(&field) {
81                select_fields.push(field);
82            }
83        }
84
85        Ok(select_fields)
86    }
87
88    pub async fn get_one(
89        &mut self,
90        db: &scylladb::ScyllaDB,
91        select_fields: Vec<String>,
92    ) -> anyhow::Result<()> {
93        let fields = Self::select_fields(select_fields, false)?;
94        self._fields = fields.clone();
95
96        let query = format!(
97            "SELECT {} FROM service_protocol WHERE code=? AND version=? LIMIT 1",
98            fields.join(",")
99        );
100        let params = (self.code.to_cql(), self.version.to_cql());
101        let res = db.execute(query, params).await?.single_row()?;
102
103        let mut cols = ColumnsMap::with_capacity(fields.len());
104        cols.fill(res, &fields)?;
105        self.fill(&cols);
106
107        Ok(())
108    }
109
110    pub async fn get_latest(
111        db: &scylladb::ScyllaDB,
112        code: i64,
113        select_fields: Vec<String>,
114    ) -> anyhow::Result<Self> {
115        let fields = Self::select_fields(select_fields, true)?;
116
117        let query = format!(
118            "SELECT {} FROM service_protocol WHERE code=? LIMIT 1",
119            fields.join(",")
120        );
121        let params = (code.to_cql(),);
122        let res = db.execute(query, params).await?.single_row()?;
123
124        let mut cols = ColumnsMap::with_capacity(fields.len());
125        cols.fill(res, &fields)?;
126        let mut doc = Self::default();
127        doc.fill(&cols);
128        doc._fields = fields.clone();
129
130        Ok(doc)
131    }
132}