sylvia_iot_broker/models/
unit.rs

1//! Traits and structs for units.
2
3use std::error::Error as StdError;
4
5use async_trait::async_trait;
6use chrono::{DateTime, Utc};
7use serde_json::{Map, Value};
8
9/// The item content.
10#[derive(Debug, PartialEq)]
11pub struct Unit {
12    pub unit_id: String,
13    pub code: String,
14    pub created_at: DateTime<Utc>,
15    pub modified_at: DateTime<Utc>,
16    pub owner_id: String,
17    pub member_ids: Vec<String>,
18    pub name: String,
19    pub info: Map<String, Value>,
20}
21
22/// The sort keys for the list operation.
23pub enum SortKey {
24    CreatedAt,
25    ModifiedAt,
26    Code,
27    Name,
28}
29
30/// The sort condition for the list operation.
31pub struct SortCond {
32    pub key: SortKey,
33    pub asc: bool,
34}
35
36/// The list operation options.
37pub struct ListOptions<'a> {
38    /// The query conditions.
39    pub cond: &'a ListQueryCond<'a>,
40    /// The data offset.
41    pub offset: Option<u64>,
42    /// The maximum number to query.
43    pub limit: Option<u64>,
44    /// The sort conditions.
45    pub sort: Option<&'a [SortCond]>,
46    /// The maximum number items one time the `list()` returns.
47    ///
48    /// Use cursors until reaching `limit` or all data.
49    pub cursor_max: Option<u64>,
50}
51
52/// The query condition to get item(s).
53#[derive(Default)]
54pub struct QueryCond<'a> {
55    pub unit_id: Option<&'a str>,
56    pub code: Option<&'a str>,
57    pub owner_id: Option<&'a str>,
58    pub member_id: Option<&'a str>,
59}
60
61/// The query condition for the list operation.
62#[derive(Default)]
63pub struct ListQueryCond<'a> {
64    /// To get units of the specified owner.
65    pub owner_id: Option<&'a str>,
66    /// To get units of the specified member.
67    pub member_id: Option<&'a str>,
68    /// To get the specified unit.
69    pub unit_id: Option<&'a str>,
70    /// To get unit that their **code** contains the specified (partial) word.
71    pub code_contains: Option<&'a str>,
72    /// To get unit that their **name** contains the specified (partial) word.
73    pub name_contains: Option<&'a str>,
74}
75
76/// The query condition for the update operation.
77pub struct UpdateQueryCond<'a> {
78    /// The specified unit.
79    pub unit_id: &'a str,
80}
81
82/// The update fields by using [`Some`]s.
83#[derive(Default)]
84pub struct Updates<'a> {
85    pub modified_at: Option<DateTime<Utc>>,
86    pub owner_id: Option<&'a str>,
87    pub member_ids: Option<&'a Vec<String>>,
88    pub name: Option<&'a str>,
89    pub info: Option<&'a Map<String, Value>>,
90}
91
92/// Model operations.
93#[async_trait]
94pub trait UnitModel: Sync {
95    /// To create and initialize the table/collection.
96    async fn init(&self) -> Result<(), Box<dyn StdError>>;
97
98    /// To get item count for the query condition.
99    ///
100    /// **Note**: this may take a long time.
101    async fn count(&self, cond: &ListQueryCond) -> Result<u64, Box<dyn StdError>>;
102
103    /// To get item list. The maximum number of returned items will be controlled by the
104    /// `cursor_max` of the list option.
105    ///
106    /// For the first time, `cursor` MUST use `None`. If one cursor is returned, it means that
107    /// there are more items to get. Use the returned cursor to get more data items.
108    ///
109    /// **Note**: using cursors is recommended to prevent exhausting memory.
110    async fn list(
111        &self,
112        opts: &ListOptions,
113        cursor: Option<Box<dyn Cursor>>,
114    ) -> Result<(Vec<Unit>, Option<Box<dyn Cursor>>), Box<dyn StdError>>;
115
116    /// To get an item.
117    async fn get(&self, cond: &QueryCond) -> Result<Option<Unit>, Box<dyn StdError>>;
118
119    /// To add an item.
120    async fn add(&self, unit: &Unit) -> Result<(), Box<dyn StdError>>;
121
122    /// To delete one or more items.
123    async fn del(&self, cond: &QueryCond) -> Result<(), Box<dyn StdError>>;
124
125    /// To update one or more items.
126    async fn update(
127        &self,
128        cond: &UpdateQueryCond,
129        updates: &Updates,
130    ) -> Result<(), Box<dyn StdError>>;
131}
132
133/// The operations for cursors.
134///
135/// All functions are private to let programs to pass them as arguments directly without any
136/// operation.
137#[async_trait]
138pub trait Cursor: Send {
139    async fn try_next(&mut self) -> Result<Option<Unit>, Box<dyn StdError>>;
140
141    fn offset(&self) -> u64;
142}