disconnect-handler
This commit is contained in:
parent
d58aed3648
commit
531cbb4458
57
src/main.rs
57
src/main.rs
|
@ -5,19 +5,27 @@ use std::env;
|
|||
use futures::StreamExt;
|
||||
use tokio::sync::broadcast;
|
||||
use actix_web::error::{ErrorUnauthorized, ErrorInternalServerError as ServerError};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use tokio::task::JoinHandle;
|
||||
|
||||
mod data;
|
||||
|
||||
async fn sse_handler(
|
||||
#[derive(Clone)]
|
||||
struct AppState {
|
||||
tasks: Arc<Mutex<HashMap<String, JoinHandle<()>>>>,
|
||||
redis: Client,
|
||||
}
|
||||
|
||||
async fn connect_handler(
|
||||
token: web::Path<String>,
|
||||
redis: web::Data<Client>,
|
||||
state: web::Data<AppState>,
|
||||
) -> Result<HttpResponse, actix_web::Error> {
|
||||
let listener_id = data::get_auth_id(&token).await.map_err(|e| {
|
||||
eprintln!("TOKEN check failed: {}", e);
|
||||
ErrorUnauthorized("Unauthorized")
|
||||
})?;
|
||||
|
||||
let mut con = redis.get_async_connection().await.map_err(|e| {
|
||||
let mut con = state.redis.get_async_connection().await.map_err(|e| {
|
||||
eprintln!("Failed to get async connection: {}", e);
|
||||
ServerError("Internal Server Error")
|
||||
})?;
|
||||
|
@ -33,8 +41,8 @@ async fn sse_handler(
|
|||
})?;
|
||||
|
||||
let (tx, mut rx) = broadcast::channel(100);
|
||||
let _handle = tokio::spawn(async move {
|
||||
let conn = redis.get_async_connection().await.unwrap();
|
||||
let handle = tokio::spawn(async move {
|
||||
let conn = state.redis.get_async_connection().await.unwrap();
|
||||
let mut pubsub = conn.into_pubsub();
|
||||
|
||||
pubsub.subscribe("new_follower").await.unwrap();
|
||||
|
@ -57,6 +65,10 @@ async fn sse_handler(
|
|||
};
|
||||
}
|
||||
});
|
||||
state.tasks
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(format!("{}", listener_id.clone()), handle);
|
||||
|
||||
let server_event = rx.recv().await.map_err(|e| {
|
||||
eprintln!("Failed to receive server event: {}", e);
|
||||
|
@ -70,17 +82,44 @@ async fn sse_handler(
|
|||
.streaming(server_event_stream))
|
||||
}
|
||||
|
||||
|
||||
async fn disconnect_handler(
|
||||
token: web::Path<String>,
|
||||
state: web::Data<AppState>,
|
||||
) -> Result<HttpResponse, actix_web::Error> {
|
||||
let listener_id = data::get_auth_id(&token).await.map_err(|e| {
|
||||
eprintln!("TOKEN check failed: {}", e);
|
||||
ErrorUnauthorized("Unauthorized")
|
||||
})?;
|
||||
if let Some(handle) = state.tasks.lock().unwrap().remove(&format!("{}", listener_id)) {
|
||||
handle.abort();
|
||||
let mut con = state.redis.get_async_connection().await.map_err(|e| {
|
||||
eprintln!("Failed to get async connection: {}", e);
|
||||
ServerError("Internal Server Error")
|
||||
})?;
|
||||
con.srem::<&str, &i32, usize>("authors-online", &listener_id).await.map_err(|e| {
|
||||
eprintln!("Failed to remove author from online list: {}", e);
|
||||
ServerError("Internal Server Error")
|
||||
})?;
|
||||
}
|
||||
Ok(HttpResponse::Ok().finish())
|
||||
}
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
let redis_url = env::var("REDIS_URL").unwrap_or_else(|_| String::from("redis://127.0.0.1/"));
|
||||
let client = redis::Client::open(redis_url.clone()).unwrap();
|
||||
|
||||
let tasks = Arc::new(Mutex::new(HashMap::new()));
|
||||
let state = AppState {
|
||||
tasks: tasks.clone(),
|
||||
redis: client.clone(),
|
||||
};
|
||||
println!("Connecting to Redis: {}", redis_url);
|
||||
HttpServer::new(move || {
|
||||
App::new()
|
||||
.app_data(web::Data::new(client.clone()))
|
||||
.route("/connect", web::get().to(sse_handler))
|
||||
.route("/disconnect", web::get().to(sse_handler))
|
||||
.app_data(web::Data::new(state.clone()))
|
||||
.route("/connect", web::get().to(connect_handler))
|
||||
.route("/disconnect", web::get().to(disconnect_handler))
|
||||
})
|
||||
.bind("127.0.0.1:8080")?
|
||||
.run()
|
||||
|
|
Loading…
Reference in New Issue
Block a user