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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
use crate::common::AppSysConfig;
use chrono::Local;
use rusqlite::Connection;
use std::rc::Rc;

use super::{
    core::{ConfigKey, ConfigValue},
    dal::{
        ConfigDO, ConfigDao, ConfigHistoryDO, ConfigHistoryDao, ConfigHistoryParam, ConfigParam,
    },
};

pub struct ConfigDB {
    config_dao: ConfigDao,
    config_history_dao: ConfigHistoryDao,
}

impl Default for ConfigDB {
    fn default() -> Self {
        Self::new()
    }
}

impl ConfigDB {
    pub fn new() -> Self {
        let sys_config = AppSysConfig::init_from_env();
        let config_db = sys_config.config_db_file;
        let conn = Connection::open(config_db).unwrap();
        Self::init(&conn);
        let conn = Rc::new(conn);
        let config_dao = ConfigDao::new(conn.clone());
        let config_history_dao = ConfigHistoryDao::new(conn);
        Self {
            config_dao,
            config_history_dao,
        }
    }

    fn init(conn: &Connection) {
        let create_table_sql = r"
create table if not exists tb_config(
    id integer primary key autoincrement,
    data_id varchar(255),
    `group` varchar(255),
    tenant varchar(255),
    content text,
    content_md5 varchar(36),
    last_time long
);
create index if not exists tb_config_key_idx on tb_config(data_id,`group`,tenant);

create table if not exists tb_config_history(
    id integer primary key autoincrement,
    data_id varchar(255),
    `group` varchar(255),
    tenant varchar(255),
    content text,
    last_time long
);
create index if not exists tb_config_history_key_idx on tb_config_history(data_id,`group`,tenant);
        ";
        conn.execute_batch(create_table_sql).unwrap();
    }

    fn convert_to_config_do(key: &ConfigKey, val: &ConfigValue) -> ConfigDO {
        let current_time = Local::now().timestamp_millis();
        ConfigDO {
            tenant: Some(key.tenant.as_ref().to_owned()),
            group: Some(key.group.as_ref().to_owned()),
            data_id: Some(key.data_id.as_ref().to_owned()),
            content: Some(val.content.as_ref().to_owned()),
            content_md5: Some(val.md5.as_ref().to_owned()),
            last_time: Some(current_time),
            ..Default::default()
        }
    }

    fn convert_to_config_history_do(key: &ConfigKey, val: &ConfigValue) -> ConfigHistoryDO {
        let current_time = Local::now().timestamp_millis();
        ConfigHistoryDO {
            tenant: Some(key.tenant.as_ref().to_owned()),
            group: Some(key.group.as_ref().to_owned()),
            data_id: Some(key.data_id.as_ref().to_owned()),
            content: Some(val.content.as_ref().to_owned()),
            last_time: Some(current_time),
            ..Default::default()
        }
    }

    fn convert_to_config_param(key: &ConfigKey) -> ConfigParam {
        ConfigParam {
            tenant: Some(key.tenant.as_ref().to_owned()),
            group: Some(key.group.as_ref().to_owned()),
            data_id: Some(key.data_id.as_ref().to_owned()),
            ..Default::default()
        }
    }

    fn convert_to_config_history_param(key: &ConfigKey) -> ConfigHistoryParam {
        ConfigHistoryParam {
            tenant: Some(key.tenant.as_ref().to_owned()),
            group: Some(key.group.as_ref().to_owned()),
            data_id: Some(key.data_id.as_ref().to_owned()),
            ..Default::default()
        }
    }

    pub fn update_config(&self, key: &ConfigKey, val: &ConfigValue) {
        let config = Self::convert_to_config_do(key, val);
        let config_history = Self::convert_to_config_history_do(key, val);
        let config_param = Self::convert_to_config_param(key);
        let is_update = match self.config_dao.update(&config, &config_param) {
            Ok(size) => size > 0,
            _ => false,
        };
        if !is_update {
            self.config_dao.insert(&config).unwrap();
        }
        self.config_history_dao.insert(&config_history).unwrap();
    }

    pub fn del_config(&self, key: &ConfigKey) {
        let config_param = Self::convert_to_config_param(key);
        let config_history_param = Self::convert_to_config_history_param(key);
        self.config_dao.delete(&config_param).unwrap();
        self.config_history_dao
            .delete(&config_history_param)
            .unwrap();
    }

    pub fn query_config_list(&self) -> Vec<ConfigDO> {
        let param = ConfigParam::default();
        self.config_dao.query(&param).unwrap()
    }

    pub fn query_config_history_page(
        &self,
        param: &ConfigHistoryParam,
    ) -> (usize, Vec<ConfigHistoryDO>) {
        let size = self
            .config_history_dao
            .query_count(param)
            .unwrap_or_default();
        let list = self.config_history_dao.query(param).unwrap_or_default();
        (size as usize, list)
    }
}