|
@@ -1,20 +1,21 @@
|
|
|
use std::sync::Arc;
|
|
use std::sync::Arc;
|
|
|
use std::sync::atomic::{AtomicBool, Ordering};
|
|
use std::sync::atomic::{AtomicBool, Ordering};
|
|
|
use actix_web::{web, App, HttpResponse, HttpServer, Responder, get};
|
|
use actix_web::{web, App, HttpResponse, HttpServer, Responder, get};
|
|
|
|
|
+use chrono::Utc;
|
|
|
|
|
+use rust_decimal::Decimal;
|
|
|
use serde::{Deserialize, Serialize};
|
|
use serde::{Deserialize, Serialize};
|
|
|
use serde_json::Value;
|
|
use serde_json::Value;
|
|
|
use tracing::{info};
|
|
use tracing::{info};
|
|
|
|
|
+use crate::db_connector::get_trades_json;
|
|
|
|
|
|
|
|
// 定义用于反序列化查询参数的结构体
|
|
// 定义用于反序列化查询参数的结构体
|
|
|
#[derive(Serialize, Deserialize, Clone)]
|
|
#[derive(Serialize, Deserialize, Clone)]
|
|
|
-pub struct TradesQuery {
|
|
|
|
|
|
|
+pub struct IndicatorQuery {
|
|
|
symbol: Option<String>,
|
|
symbol: Option<String>,
|
|
|
- exchange: Option<String>,
|
|
|
|
|
- start_time: Option<i64>,
|
|
|
|
|
- end_time: Option<i64>,
|
|
|
|
|
|
|
+ exchange: Option<String>
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-impl TradesQuery {
|
|
|
|
|
|
|
+impl IndicatorQuery {
|
|
|
pub fn validate(&self) -> bool {
|
|
pub fn validate(&self) -> bool {
|
|
|
if self.symbol.is_none() {
|
|
if self.symbol.is_none() {
|
|
|
return false
|
|
return false
|
|
@@ -24,45 +25,72 @@ impl TradesQuery {
|
|
|
return false
|
|
return false
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if self.start_time.is_none() {
|
|
|
|
|
- return false
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if self.end_time.is_none() {
|
|
|
|
|
- return false
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
true
|
|
true
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
#[derive(Serialize, Deserialize)]
|
|
|
pub struct Response {
|
|
pub struct Response {
|
|
|
- message: Option<String>,
|
|
|
|
|
- query_string: Value,
|
|
|
|
|
- data: Value,
|
|
|
|
|
- code: i32,
|
|
|
|
|
|
|
+ pub message: Option<String>,
|
|
|
|
|
+ pub query_string: Value,
|
|
|
|
|
+ pub data: Value,
|
|
|
|
|
+ pub code: i32,
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
|
|
|
+pub struct Trade {
|
|
|
|
|
+ pub id: String,
|
|
|
|
|
+ pub time: Decimal,
|
|
|
|
|
+ pub size: Decimal,
|
|
|
|
|
+ pub price: Decimal
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 句柄 GET 请求
|
|
// 句柄 GET 请求
|
|
|
-#[get("/trades")]
|
|
|
|
|
-async fn get_trades(query: web::Query<TradesQuery>) -> impl Responder {
|
|
|
|
|
|
|
+#[get("/get_symbols")]
|
|
|
|
|
+async fn get_symbols_by_filter() -> impl Responder {
|
|
|
|
|
+ let response = Response {
|
|
|
|
|
+ query_string: Value::Null,
|
|
|
|
|
+ message: Some("get_symbols_by_filter 这个接口还没做".to_string()),
|
|
|
|
|
+ code: 400,
|
|
|
|
|
+ data: Value::Null,
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ let json_string = serde_json::to_string(&response).unwrap();
|
|
|
|
|
+ HttpResponse::BadRequest().content_type("application/json").body(json_string)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#[get("/get_indicator")]
|
|
|
|
|
+async fn get_indicator(query: web::Query<IndicatorQuery>) -> impl Responder {
|
|
|
if query.validate() {
|
|
if query.validate() {
|
|
|
- let response_data = Value::Null;
|
|
|
|
|
|
|
+ // 链接数据服务器查询数据
|
|
|
|
|
+ let end_time = Utc::now().timestamp_millis();
|
|
|
|
|
+ let start_time = end_time - 4 * 60 * 60 * 1000;
|
|
|
|
|
+ let db_response = get_trades_json(
|
|
|
|
|
+ query.exchange.clone().unwrap().as_str(),
|
|
|
|
|
+ query.symbol.clone().unwrap().as_str(),
|
|
|
|
|
+ start_time,
|
|
|
|
|
+ end_time,
|
|
|
|
|
+ ).await;
|
|
|
|
|
|
|
|
- let response = Response {
|
|
|
|
|
- query_string: serde_json::to_value(&query.into_inner()).unwrap(),
|
|
|
|
|
- message: Some("查询成功".to_string()),
|
|
|
|
|
- code: 200,
|
|
|
|
|
- data: response_data,
|
|
|
|
|
- };
|
|
|
|
|
|
|
+ // 对数据库返回的数据进行容错处理
|
|
|
|
|
+ if db_response.code == 200 {
|
|
|
|
|
+ let response = Response {
|
|
|
|
|
+ query_string: serde_json::to_value(&query.into_inner()).unwrap(),
|
|
|
|
|
+ message: Some("指标生成完毕".to_string()),
|
|
|
|
|
+ code: 200,
|
|
|
|
|
+ data: db_response.data,
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
- let json_string = serde_json::to_string(&response).unwrap();
|
|
|
|
|
- HttpResponse::Ok().content_type("application/json").body(json_string)
|
|
|
|
|
|
|
+ let json_string = serde_json::to_string(&response).unwrap();
|
|
|
|
|
+ HttpResponse::Ok().content_type("application/json").body(json_string)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ let json_string = serde_json::to_string(&db_response).unwrap();
|
|
|
|
|
+ HttpResponse::Ok().content_type("application/json").body(json_string)
|
|
|
|
|
+ }
|
|
|
} else {
|
|
} else {
|
|
|
let response = Response {
|
|
let response = Response {
|
|
|
query_string: serde_json::to_value(&query.into_inner()).unwrap(),
|
|
query_string: serde_json::to_value(&query.into_inner()).unwrap(),
|
|
|
- message: Some("查询内容有误,必须包含四个参数:[symbol, exchange, start_time, end_time]".to_string()),
|
|
|
|
|
|
|
+ message: Some("[symbol以及exchange必传]".to_string()),
|
|
|
code: 400,
|
|
code: 400,
|
|
|
data: Value::Null,
|
|
data: Value::Null,
|
|
|
};
|
|
};
|
|
@@ -79,7 +107,8 @@ pub fn run_server(port: u32, running: Arc<AtomicBool>) {
|
|
|
// 启动server
|
|
// 启动server
|
|
|
let server_fut = HttpServer::new(move || {
|
|
let server_fut = HttpServer::new(move || {
|
|
|
App::new()
|
|
App::new()
|
|
|
- .service(get_trades)
|
|
|
|
|
|
|
+ .service(get_symbols_by_filter)
|
|
|
|
|
+ .service(get_indicator)
|
|
|
})
|
|
})
|
|
|
.bind(addr)
|
|
.bind(addr)
|
|
|
.expect("Bind port error")
|
|
.expect("Bind port error")
|