Init
This commit is contained in:
@@ -5,6 +5,7 @@ use crate::database::Database;
|
||||
use crate::http::server::HttpServer;
|
||||
use crate::metrics::{reporter, AppMetrics};
|
||||
use crate::repositories::Repositories;
|
||||
use crate::routes::gateway::GatewayManager;
|
||||
use crate::udp::server::UdpServer;
|
||||
use event_bus::EventBus;
|
||||
use migration::{Migrator, MigratorTrait};
|
||||
@@ -32,6 +33,9 @@ impl App {
|
||||
// Initialize shared repositories
|
||||
let repositories = Repositories::new(db.clone(), event_bus.clone());
|
||||
|
||||
// Initialize gateway manager
|
||||
let gateway = Arc::new(GatewayManager::default());
|
||||
|
||||
// Init one server if no one exist
|
||||
let default_server = match repositories.server.get_default().await? {
|
||||
Some(server) => server,
|
||||
@@ -69,6 +73,8 @@ impl App {
|
||||
init_token: Arc::new(RwLock::new(init_token)),
|
||||
default_server: Arc::new(default_server),
|
||||
metrics,
|
||||
gateway,
|
||||
event_bus,
|
||||
};
|
||||
|
||||
Ok(Self { state })
|
||||
|
||||
@@ -2,6 +2,8 @@ use crate::config::AppConfig;
|
||||
use crate::metrics::AppMetrics;
|
||||
use crate::models::server;
|
||||
use crate::repositories::Repositories;
|
||||
use crate::routes::gateway::GatewayManager;
|
||||
use event_bus::EventBus;
|
||||
use sea_orm::DatabaseConnection;
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
@@ -13,6 +15,8 @@ pub struct AppState {
|
||||
pub init_token: Arc<RwLock<Option<uuid::Uuid>>>,
|
||||
pub default_server: Arc<server::Model>,
|
||||
pub metrics: AppMetrics,
|
||||
pub gateway: Arc<GatewayManager>,
|
||||
pub event_bus: Arc<EventBus>,
|
||||
}
|
||||
|
||||
impl AppState {}
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
use crate::auth::token::verify_jwt;
|
||||
use crate::core::AppState;
|
||||
use crate::http::context::CurrentUser;
|
||||
use crate::models::user::Model as User;
|
||||
use crate::routes::gateway::GatewayClient;
|
||||
use axum::{
|
||||
extract::{
|
||||
ws::{Message, WebSocket, WebSocketUpgrade}, Query,
|
||||
State,
|
||||
},
|
||||
response::IntoResponse,
|
||||
};
|
||||
use futures_util::{sink::SinkExt, stream::StreamExt};
|
||||
use serde::Deserialize;
|
||||
use tokio::sync::mpsc;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct WsQuery {
|
||||
token: String,
|
||||
}
|
||||
|
||||
pub async fn ws_handler(
|
||||
Query(query): Query<WsQuery>,
|
||||
ws: WebSocketUpgrade,
|
||||
State(state): State<AppState>,
|
||||
CurrentUser(user): CurrentUser,
|
||||
) -> impl IntoResponse {
|
||||
ws.on_upgrade(move |socket| handle_socket(socket, state, user))
|
||||
|
||||
// let token = query.token;
|
||||
|
||||
// Vérification du JWT
|
||||
// match verify_jwt(&token, &state.config.jwt.secret) {
|
||||
// Ok(claims) => ws.on_upgrade(move |socket| handle_socket(socket, state, claims.user_id)),
|
||||
// Err(e) => {
|
||||
// tracing::error!("WS auth error: {:?}", e);
|
||||
// (axum::http::StatusCode::UNAUTHORIZED, "Invalid token").into_response()
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
async fn handle_socket(socket: WebSocket, state: AppState, user: User) {
|
||||
let (mut sender, mut receiver) = socket.split();
|
||||
let (tx, mut rx) = mpsc::unbounded_channel();
|
||||
let event_bus = state.event_bus.clone();
|
||||
|
||||
let client = GatewayClient::new(user);
|
||||
client.on_connect().await;
|
||||
state.gateway.add_user(client);
|
||||
|
||||
// // Enregistrement du client (Connect)
|
||||
// on_connect(user_id, tx, &state).await;
|
||||
//
|
||||
// // Task pour envoyer les messages du canal mpsc vers le WebSocket
|
||||
// let mut send_task = tokio::spawn(async move {
|
||||
// while let Some(message) = rx.recv().await {
|
||||
// if sender.send(message).await.is_err() {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// // Task pour recevoir les messages du WebSocket
|
||||
// let state_clone = state.clone();
|
||||
// let mut recv_task = tokio::spawn(async move {
|
||||
// while let Some(Ok(message)) = receiver.next().await {
|
||||
// on_message(user_id, message, &state_clone).await;
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// // Attente de la fin d'une des tâches (déconnexion)
|
||||
// tokio::select! {
|
||||
// _ = (&mut send_task) => recv_task.abort(),
|
||||
// _ = (&mut recv_task) => send_task.abort(),
|
||||
// };
|
||||
//
|
||||
// // Déconnexion (Disconnect)
|
||||
// on_disconnect(user_id, &state).await;
|
||||
}
|
||||
|
||||
pub async fn on_connect(user_id: Uuid, tx: mpsc::UnboundedSender<Message>, state: &AppState) {
|
||||
tracing::info!("Client connected: {}", user_id);
|
||||
let mut clients = state
|
||||
.gateway
|
||||
.clients
|
||||
.write()
|
||||
.expect("Failed to lock clients for writing");
|
||||
clients.insert(user_id, GatewayClient { user_id, tx });
|
||||
}
|
||||
|
||||
pub async fn on_disconnect(user_id: Uuid, state: &AppState) {
|
||||
tracing::info!("Client disconnected: {}", user_id);
|
||||
let mut clients = state
|
||||
.gateway
|
||||
.clients
|
||||
.write()
|
||||
.expect("Failed to lock clients for writing");
|
||||
clients.remove(&user_id);
|
||||
}
|
||||
|
||||
pub async fn on_message(user_id: Uuid, message: Message, _state: &AppState) {
|
||||
tracing::debug!("Message received from {}: {:?}", user_id, message);
|
||||
|
||||
// Exemple d'utilisation de l'état/repositories
|
||||
// let user_opt = state.repositories.user.get_by_id(user_id).await.ok().flatten();
|
||||
|
||||
match message {
|
||||
Message::Text(text) => {
|
||||
tracing::info!("Received text from {}: {}", user_id, text);
|
||||
// Logique de dispatch ou de traitement ici
|
||||
}
|
||||
Message::Binary(_) => {
|
||||
tracing::info!("Received binary from {}", user_id);
|
||||
}
|
||||
Message::Close(_) => {
|
||||
tracing::info!("Received close from {}", user_id);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
use crate::models::user::Model as User;
|
||||
use parking_lot::RwLock;
|
||||
use std::collections::HashMap;
|
||||
use uuid::Uuid;
|
||||
|
||||
pub mod handlers;
|
||||
pub mod routes;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct GatewayManager {
|
||||
// {UserID: {connection_id: GatewayClient}}
|
||||
pub clients: RwLock<HashMap<Uuid, HashMap<Uuid, GatewayClient>>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct GatewayClient {
|
||||
user: User,
|
||||
connection_id: Uuid,
|
||||
}
|
||||
|
||||
impl GatewayManager {
|
||||
fn add_client(&self, gateway_client: GatewayClient) {
|
||||
let mut clients = self.clients.write();
|
||||
let user_id = gateway_client.user.id;
|
||||
clients
|
||||
.entry(user_id)
|
||||
.or_insert_with(HashMap::new)
|
||||
.insert(gateway_client.connection_id, gateway_client);
|
||||
}
|
||||
|
||||
fn remove_client(&self, gateway_client: GatewayClient) {
|
||||
let mut clients = self.clients.write();
|
||||
if let Some(client_list) = clients.get_mut(&gateway_client.user.id) {
|
||||
client_list.remove(&gateway_client.connection_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GatewayClient {
|
||||
pub fn new(user: User) -> Self {
|
||||
let connection_id = Uuid::new_v4();
|
||||
Self {
|
||||
user,
|
||||
connection_id,
|
||||
}
|
||||
}
|
||||
|
||||
async fn on_connect(&self) {}
|
||||
|
||||
async fn on_disconnect(&self) {}
|
||||
|
||||
async fn on_message(&self) {}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
use super::handlers;
|
||||
use crate::core::AppState;
|
||||
use axum::routing::get;
|
||||
use axum::Router;
|
||||
|
||||
pub fn router() -> Router<AppState> {
|
||||
Router::new().route("/gateway", get(handlers::ws_handler))
|
||||
}
|
||||
+3
-1
@@ -9,6 +9,7 @@ pub mod auth;
|
||||
pub mod category;
|
||||
pub mod channel;
|
||||
pub mod core;
|
||||
pub mod gateway;
|
||||
pub mod group;
|
||||
pub mod message;
|
||||
pub mod openapi;
|
||||
@@ -30,7 +31,8 @@ pub fn router() -> OxRouter {
|
||||
let api_routes = Router::new()
|
||||
.merge(secure_routes)
|
||||
.merge(auth::routes::router())
|
||||
.merge(core::routes::router());
|
||||
.merge(core::routes::router())
|
||||
.merge(gateway::routes::router());
|
||||
|
||||
Router::new()
|
||||
.nest("/api", api_routes)
|
||||
|
||||
Reference in New Issue
Block a user