sylvia_iot_data/routes/
mod.rs1use std::{collections::HashMap, error::Error as StdError, sync::Arc};
2
3use axum::{response::IntoResponse, Router};
4use reqwest;
5use serde::{Deserialize, Serialize};
6
7use general_mq::Queue;
8use sylvia_iot_corelib::{
9 constants::DbEngine,
10 http::{Json, Query},
11};
12
13use crate::{
14 libs::{
15 config::{self, Config},
16 mq::{self, Connection},
17 },
18 models::{self, ConnOptions, Model, MongoDbOptions, SqliteOptions},
19};
20
21pub mod middleware;
22mod v1;
23
24#[derive(Clone)]
26pub struct State {
27 pub scope_path: &'static str,
33 pub model: Arc<dyn Model>,
35 pub auth_base: String,
39 pub broker_base: String,
43 pub client: reqwest::Client,
45 pub mq_conns: HashMap<String, Connection>,
47 pub data_receivers: HashMap<String, Queue>,
49}
50
51pub struct ErrReq;
54
55#[derive(Deserialize)]
57pub struct GetVersionQuery {
58 q: Option<String>,
59}
60
61#[derive(Serialize)]
62struct GetVersionRes<'a> {
63 data: GetVersionResData<'a>,
64}
65
66#[derive(Serialize)]
67struct GetVersionResData<'a> {
68 name: &'a str,
69 version: &'a str,
70}
71
72const SERV_NAME: &'static str = env!("CARGO_PKG_NAME");
73const SERV_VER: &'static str = env!("CARGO_PKG_VERSION");
74
75impl ErrReq {
76 pub const UNIT_NOT_EXIST: (u16, &'static str) = (400, "err_data_unit_not_exist");
77 pub const USER_NOT_EXIST: (u16, &'static str) = (400, "err_data_user_not_exist");
78}
79
80pub async fn new_state(
82 scope_path: &'static str,
83 conf: &Config,
84) -> Result<State, Box<dyn StdError>> {
85 let conf = config::apply_default(conf);
86 let db_opts = match conf.db.as_ref().unwrap().engine.as_ref().unwrap().as_str() {
87 DbEngine::MONGODB => {
88 let conf = conf.db.as_ref().unwrap().mongodb.as_ref().unwrap();
89 ConnOptions::MongoDB(MongoDbOptions {
90 url: conf.url.as_ref().unwrap().to_string(),
91 db: conf.database.as_ref().unwrap().to_string(),
92 pool_size: conf.pool_size,
93 })
94 }
95 _ => {
96 let conf = conf.db.as_ref().unwrap().sqlite.as_ref().unwrap();
97 ConnOptions::Sqlite(SqliteOptions {
98 path: conf.path.as_ref().unwrap().to_string(),
99 })
100 }
101 };
102 let model = models::new(&db_opts).await?;
103 let auth_base = conf.auth.as_ref().unwrap().clone();
104 let broker_base = conf.broker.as_ref().unwrap().clone();
105 let mut mq_conns = HashMap::new();
106 let ch_conf = conf.mq_channels.as_ref().unwrap();
107 let data_receivers = new_data_receivers(&model, &mut mq_conns, ch_conf)?;
108 let state = State {
109 scope_path,
110 model,
111 auth_base,
112 broker_base,
113 client: reqwest::Client::new(),
114 mq_conns,
115 data_receivers,
116 };
117 Ok(state)
118}
119
120pub fn new_service(state: &State) -> Router {
122 Router::new().nest(
123 &state.scope_path,
124 Router::new()
125 .merge(v1::application_uldata::new_service(
126 "/api/v1/application-uldata",
127 state,
128 ))
129 .merge(v1::application_dldata::new_service(
130 "/api/v1/application-dldata",
131 state,
132 ))
133 .merge(v1::network_uldata::new_service(
134 "/api/v1/network-uldata",
135 state,
136 ))
137 .merge(v1::network_dldata::new_service(
138 "/api/v1/network-dldata",
139 state,
140 ))
141 .merge(v1::coremgr_opdata::new_service(
142 "/api/v1/coremgr-opdata",
143 state,
144 )),
145 )
146}
147
148pub fn new_data_receivers(
149 model: &Arc<dyn Model>,
150 mq_conns: &mut HashMap<String, Connection>,
151 ch_conf: &config::MqChannels,
152) -> Result<HashMap<String, Queue>, Box<dyn StdError>> {
153 let mut data_receivers = HashMap::<String, Queue>::new();
154
155 let conf = ch_conf.broker.as_ref().unwrap();
156 let q = mq::broker::new(model.clone(), mq_conns, &conf)?;
157 data_receivers.insert("broker.data".to_string(), q);
158
159 let conf = ch_conf.coremgr.as_ref().unwrap();
160 let q = mq::coremgr::new(model.clone(), mq_conns, &conf)?;
161 data_receivers.insert("coremgr.data".to_string(), q);
162
163 Ok(data_receivers)
164}
165
166pub async fn get_version(Query(query): Query<GetVersionQuery>) -> impl IntoResponse {
167 if let Some(q) = query.q.as_ref() {
168 match q.as_str() {
169 "name" => return SERV_NAME.into_response(),
170 "version" => return SERV_VER.into_response(),
171 _ => (),
172 }
173 }
174
175 Json(GetVersionRes {
176 data: GetVersionResData {
177 name: SERV_NAME,
178 version: SERV_VER,
179 },
180 })
181 .into_response()
182}