sylvia_iot_broker/models/
mod.rs

1//! Traits and implementations for accessing databases and caches.
2//!
3//! Currently we only provide pure MongoDB/SQLite implementation. Mixing implementation is
4//! possible. For example, put units/devices in MongoDB and put routes in Redis. Then use a
5//! model struct and impl to mix both databases.
6
7use std::{error::Error as StdError, sync::Arc};
8
9use async_trait::async_trait;
10
11pub mod application;
12pub mod device;
13pub mod device_route;
14pub mod dldata_buffer;
15pub mod network;
16pub mod network_route;
17pub mod unit;
18
19mod cache_memory;
20mod memory;
21mod model_mongodb;
22mod model_sqlite;
23mod mongodb;
24mod sqlite;
25
26pub use self::{
27    cache_memory::{Cache as MemoryCache, Options as MemoryOptions},
28    memory::{
29        device::Options as DeviceOptions, device_route::Options as DeviceRouteOptions,
30        network_route::Options as NetworkRouteOptions,
31    },
32    mongodb::conn::{self as mongodb_conn, Options as MongoDbOptions},
33    sqlite::conn::{self as sqlite_conn, Options as SqliteOptions},
34};
35pub use model_mongodb::Model as MongoDbModel;
36pub use model_sqlite::Model as SqliteModel;
37
38/// Database connection options for model implementation.
39pub enum ConnOptions {
40    // Pure MongoDB model implementation.
41    MongoDB(MongoDbOptions),
42    /// Pure SQLite model implementation.
43    Sqlite(SqliteOptions),
44}
45
46/// Database connection options for cache implementation.
47pub enum CacheConnOptions {
48    Memory {
49        device: DeviceOptions,
50        device_route: DeviceRouteOptions,
51        network_route: NetworkRouteOptions,
52    },
53}
54
55/// The top level trait to get all models (tables/collections).
56#[async_trait]
57pub trait Model: Send + Sync {
58    /// Close database connection.
59    async fn close(&self) -> Result<(), Box<dyn StdError>>;
60
61    /// To get the unit model.
62    fn unit(&self) -> &dyn unit::UnitModel;
63
64    /// To get the application model.
65    fn application(&self) -> &dyn application::ApplicationModel;
66
67    /// To get the network model.
68    fn network(&self) -> &dyn network::NetworkModel;
69
70    /// To get the device model.
71    fn device(&self) -> &dyn device::DeviceModel;
72
73    /// To get the device route model.
74    fn device_route(&self) -> &dyn device_route::DeviceRouteModel;
75
76    /// To get the network route model.
77    fn network_route(&self) -> &dyn network_route::NetworkRouteModel;
78
79    /// To get the downlink data buffer model.
80    fn dldata_buffer(&self) -> &dyn dldata_buffer::DlDataBufferModel;
81}
82
83/// The top level trait to get all caches.
84#[async_trait]
85pub trait Cache: Send + Sync {
86    /// Close database connection.
87    async fn close(&self) -> Result<(), Box<dyn StdError>>;
88
89    /// To get the device cache.
90    fn device(&self) -> &dyn device::DeviceCache;
91
92    /// To get the device route cache.
93    fn device_route(&self) -> &dyn device_route::DeviceRouteCache;
94
95    /// To get the network route cache.
96    fn network_route(&self) -> &dyn network_route::NetworkRouteCache;
97}
98
99/// To create the database model with the specified database implementation.
100pub async fn new(opts: &ConnOptions) -> Result<Arc<dyn Model>, Box<dyn StdError>> {
101    let model: Arc<dyn Model> = match opts {
102        ConnOptions::MongoDB(opts) => Arc::new(MongoDbModel::new(opts).await?),
103        ConnOptions::Sqlite(opts) => Arc::new(SqliteModel::new(opts).await?),
104    };
105    model.unit().init().await?;
106    model.application().init().await?;
107    model.network().init().await?;
108    model.device().init().await?;
109    model.device_route().init().await?;
110    model.network_route().init().await?;
111    model.dldata_buffer().init().await?;
112    Ok(model)
113}
114
115/// To create the database cache with the specified database implementation.
116pub async fn new_cache(
117    opts: &CacheConnOptions,
118    model: &Arc<dyn Model>,
119) -> Result<Arc<dyn Cache>, Box<dyn StdError>> {
120    let cache: Arc<dyn Cache> = match opts {
121        CacheConnOptions::Memory {
122            device,
123            device_route,
124            network_route,
125        } => {
126            let opts = MemoryOptions {
127                device: &device,
128                device_route: &device_route,
129                network_route: &network_route,
130            };
131            Arc::new(MemoryCache::new(&opts, model))
132        }
133    };
134    Ok(cache)
135}