use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; use std::time::Duration; use actix_web::{web, App, HttpResponse, HttpServer, Responder, post, get}; use tokio::sync::Mutex; use tracing::{info}; use global::cci::CentralControlInfo; #[derive(Clone)] struct Arcs { running: Arc, cci_cache_arc: Arc> } // 句柄 GET 请求 #[get("/account")] async fn get_account(arcs: web::Data) -> impl Responder { // --------------------------------数据解锁处理-------------------------------- let cci = arcs.cci_cache_arc.lock().await; // --------------------------------回报-------------------------------- let json_string = serde_json::to_string(&(cci.clone())).unwrap(); HttpResponse::Ok().content_type("application/json").body(json_string) } // 句柄 POST 请求 #[post("/exit")] async fn on_change(arcs: web::Data) -> impl Responder { arcs.running.store(false, Ordering::Relaxed); HttpResponse::Ok().body("程序已收到退出信号,将在清退仓位后退出。".to_string()) } pub fn run_cci_cache(cci_arc: Arc>) -> Arc> { // cci缓存,防止中控因等待时间过长杀死rust let cci_cache = CentralControlInfo { now_balance: Default::default(), unrealized_pn_l: Default::default(), pos: Default::default(), entry_price: Default::default(), now_price: Default::default(), }; let cci_cache_arc = Arc::new(Mutex::new(cci_cache)); let cci_cache_arc_clone = cci_cache_arc.clone(); tokio::spawn(async move { loop { tokio::time::sleep(Duration::from_secs(1)).await; let cci = cci_arc.lock().await; { let cci_cache = cci_cache_arc_clone.lock().await; cci_cache.now_price = cci.now_price; cci_cache.pos = cci.pos; cci_cache.unrealized_pn_l = cci.unrealized_pn_l; cci_cache.now_balance = cci.now_balance; cci_cache.entry_price = cci.entry_price; } } }); return cci_cache_arc; } pub fn run_server(port: u32, running: Arc, cci_arc: Arc>) { let addr = format!("0.0.0.0:{}", port); info!("中控绑定地址:{}", addr); // 启动server let arcs = Arcs { running: running.clone(), cci_cache_arc: run_cci_cache(cci_arc), }; let server_fut = HttpServer::new(move || { let arcs_clone = arcs.clone(); App::new() .app_data(web::Data::new(arcs_clone)) .service(get_account) .service(on_change) }) .bind(addr) .expect("Bind port error") .run(); info!("中控服务已运行。"); let r = running.clone(); tokio::spawn(async move { server_fut.await.expect("error running the server"); r.store(false, Ordering::Relaxed); }); }