sylvia_iot_broker/models/memory/
network_route.rs

1use std::{error::Error as StdError, num::NonZeroUsize, sync::Arc};
2
3use async_trait::async_trait;
4use lru::LruCache;
5use tokio::sync::RwLock;
6
7use super::super::{
8    network_route::{ListOptions, ListQueryCond, NetworkRouteCache, NetworkRouteCacheUlData},
9    Model,
10};
11
12pub struct Cache {
13    model: Arc<dyn Model>,
14    uldata: Arc<RwLock<LruCache<String, Option<NetworkRouteCacheUlData>>>>,
15}
16
17pub struct Options {
18    pub uldata_size: usize,
19}
20
21const DEF_SIZE: usize = 10_000;
22
23impl Cache {
24    pub fn new(opts: &Options, model: Arc<dyn Model>) -> Self {
25        let uldata = unsafe { NonZeroUsize::new_unchecked(opts.uldata_size) };
26        Cache {
27            model,
28            uldata: Arc::new(RwLock::new(LruCache::new(uldata))),
29        }
30    }
31}
32
33#[async_trait]
34impl NetworkRouteCache for Cache {
35    async fn clear(&self) -> Result<(), Box<dyn StdError>> {
36        let mut lock = self.uldata.write().await;
37        lock.clear();
38        Ok(())
39    }
40
41    async fn get_uldata(
42        &self,
43        network_id: &str,
44    ) -> Result<Option<NetworkRouteCacheUlData>, Box<dyn StdError>> {
45        {
46            let mut lock = self.uldata.write().await;
47            if let Some(value) = lock.get(network_id) {
48                match value {
49                    None => return Ok(None),
50                    Some(value) => return Ok(Some(value.clone())),
51                }
52            }
53        }
54
55        let opts = ListOptions {
56            cond: &ListQueryCond {
57                network_id: Some(network_id),
58                ..Default::default()
59            },
60            offset: None,
61            limit: None,
62            sort: None,
63            cursor_max: None,
64        };
65        let (routes, _) = self.model.network_route().list(&opts, None).await?;
66        let data = match routes.len() {
67            0 => None,
68            _ => {
69                let mut routes_data = vec![];
70                for r in routes.iter() {
71                    routes_data.push(format!("{}.{}", r.unit_code, r.application_code))
72                }
73                Some(NetworkRouteCacheUlData {
74                    app_mgr_keys: routes_data,
75                })
76            }
77        };
78        let _ = self.set_uldata(network_id, data.as_ref()).await;
79        Ok(data)
80    }
81
82    async fn set_uldata(
83        &self,
84        network_id: &str,
85        value: Option<&NetworkRouteCacheUlData>,
86    ) -> Result<(), Box<dyn StdError>> {
87        let key = network_id.to_string();
88        let mut lock = self.uldata.write().await;
89        let _ = match value {
90            None => lock.push(key, None),
91            Some(value) => lock.push(key, Some(value.clone())),
92        };
93        Ok(())
94    }
95
96    async fn del_uldata(&self, network_id: &str) -> Result<(), Box<dyn StdError>> {
97        let mut lock = self.uldata.write().await;
98        lock.pop(network_id);
99        Ok(())
100    }
101}
102
103impl Default for Options {
104    fn default() -> Self {
105        Options {
106            uldata_size: DEF_SIZE,
107        }
108    }
109}