sylvia_iot_broker/models/memory/
network_route.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use std::{error::Error as StdError, num::NonZeroUsize, sync::Arc};

use async_trait::async_trait;
use lru::LruCache;
use tokio::sync::RwLock;

use super::super::{
    network_route::{ListOptions, ListQueryCond, NetworkRouteCache, NetworkRouteCacheUlData},
    Model,
};

pub struct Cache {
    model: Arc<dyn Model>,
    uldata: Arc<RwLock<LruCache<String, Option<NetworkRouteCacheUlData>>>>,
}

pub struct Options {
    pub uldata_size: usize,
}

const DEF_SIZE: usize = 10_000;

impl Cache {
    pub fn new(opts: &Options, model: Arc<dyn Model>) -> Self {
        let uldata = unsafe { NonZeroUsize::new_unchecked(opts.uldata_size) };
        Cache {
            model,
            uldata: Arc::new(RwLock::new(LruCache::new(uldata))),
        }
    }
}

#[async_trait]
impl NetworkRouteCache for Cache {
    async fn clear(&self) -> Result<(), Box<dyn StdError>> {
        let mut lock = self.uldata.write().await;
        lock.clear();
        Ok(())
    }

    async fn get_uldata(
        &self,
        network_id: &str,
    ) -> Result<Option<NetworkRouteCacheUlData>, Box<dyn StdError>> {
        {
            let mut lock = self.uldata.write().await;
            if let Some(value) = lock.get(network_id) {
                match value {
                    None => return Ok(None),
                    Some(value) => return Ok(Some(value.clone())),
                }
            }
        }

        let opts = ListOptions {
            cond: &ListQueryCond {
                network_id: Some(network_id),
                ..Default::default()
            },
            offset: None,
            limit: None,
            sort: None,
            cursor_max: None,
        };
        let (routes, _) = self.model.network_route().list(&opts, None).await?;
        let data = match routes.len() {
            0 => None,
            _ => {
                let mut routes_data = vec![];
                for r in routes.iter() {
                    routes_data.push(format!("{}.{}", r.unit_code, r.application_code))
                }
                Some(NetworkRouteCacheUlData {
                    app_mgr_keys: routes_data,
                })
            }
        };
        let _ = self.set_uldata(network_id, data.as_ref()).await;
        Ok(data)
    }

    async fn set_uldata(
        &self,
        network_id: &str,
        value: Option<&NetworkRouteCacheUlData>,
    ) -> Result<(), Box<dyn StdError>> {
        let key = network_id.to_string();
        let mut lock = self.uldata.write().await;
        let _ = match value {
            None => lock.push(key, None),
            Some(value) => lock.push(key, Some(value.clone())),
        };
        Ok(())
    }

    async fn del_uldata(&self, network_id: &str) -> Result<(), Box<dyn StdError>> {
        let mut lock = self.uldata.write().await;
        lock.pop(network_id);
        Ok(())
    }
}

impl Default for Options {
    fn default() -> Self {
        Options {
            uldata_size: DEF_SIZE,
        }
    }
}