mirror of
https://codeberg.org/JasterV/chat-rooms-actix.git
synced 2026-04-26 18:10:04 +00:00
add heartbeat to websocket session
This commit is contained in:
parent
90771c7c26
commit
f636422043
3 changed files with 43 additions and 6 deletions
|
|
@ -1,18 +1,22 @@
|
||||||
use crate::messages::{
|
|
||||||
chat_server::{ClientMessage, Connect, CreateRoom, Disconnect, JoinRoom, Leave},
|
|
||||||
chat_session::Message,
|
|
||||||
};
|
|
||||||
use crate::{
|
use crate::{
|
||||||
actors::chat_server::ChatServer,
|
actors::chat_server::ChatServer,
|
||||||
|
constants::CLIENT_TIMEOUT,
|
||||||
models::{
|
models::{
|
||||||
commands::Command,
|
commands::Command,
|
||||||
ws::{MessageType, WsMessage},
|
ws::{MessageType, WsMessage},
|
||||||
RoomId, SessionId,
|
RoomId, SessionId,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use crate::{
|
||||||
|
constants::HEARTBEAT_INTERVAL,
|
||||||
|
messages::{
|
||||||
|
chat_server::{ClientMessage, Connect, CreateRoom, Disconnect, JoinRoom, Leave},
|
||||||
|
chat_session::Message,
|
||||||
|
},
|
||||||
|
};
|
||||||
use actix::{
|
use actix::{
|
||||||
fut, ActorContext, ActorFuture, ContextFutureSpawner, Handler, Running, StreamHandler,
|
clock::Instant, fut, ActorContext, ActorFuture, ContextFutureSpawner, Handler, Running,
|
||||||
WrapFuture,
|
StreamHandler, WrapFuture,
|
||||||
};
|
};
|
||||||
use actix::{Actor, Addr, AsyncContext};
|
use actix::{Actor, Addr, AsyncContext};
|
||||||
use actix_web_actors::ws::{self, WebsocketContext};
|
use actix_web_actors::ws::{self, WebsocketContext};
|
||||||
|
|
@ -23,6 +27,7 @@ pub struct WsChatSession {
|
||||||
pub id: SessionId,
|
pub id: SessionId,
|
||||||
pub room: Option<RoomId>,
|
pub room: Option<RoomId>,
|
||||||
pub addr: Addr<ChatServer>,
|
pub addr: Addr<ChatServer>,
|
||||||
|
pub hb: Instant,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WsChatSession {
|
impl WsChatSession {
|
||||||
|
|
@ -30,10 +35,27 @@ impl WsChatSession {
|
||||||
WsChatSession {
|
WsChatSession {
|
||||||
id: Uuid::new_v4(),
|
id: Uuid::new_v4(),
|
||||||
room: None,
|
room: None,
|
||||||
|
hb: Instant::now(),
|
||||||
addr,
|
addr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn hb(&self, ctx: &mut WebsocketContext<Self>) {
|
||||||
|
ctx.run_interval(HEARTBEAT_INTERVAL, |act, ctx| {
|
||||||
|
if Instant::now().duration_since(act.hb) > CLIENT_TIMEOUT {
|
||||||
|
// heartbeat timed out
|
||||||
|
println!("Websocket Client heartbeat failed, disconnecting!");
|
||||||
|
// notify chat server
|
||||||
|
act.addr.do_send(Disconnect { session: act.id });
|
||||||
|
// stop actor
|
||||||
|
ctx.stop();
|
||||||
|
// don't try to send a ping
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ctx.ping(b"");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
pub fn handle_msg(&self, msg: WsMessage, ctx: &mut WebsocketContext<Self>) {
|
pub fn handle_msg(&self, msg: WsMessage, ctx: &mut WebsocketContext<Self>) {
|
||||||
let data = msg.data.unwrap_or("".into());
|
let data = msg.data.unwrap_or("".into());
|
||||||
match msg.ty {
|
match msg.ty {
|
||||||
|
|
@ -157,6 +179,7 @@ impl Actor for WsChatSession {
|
||||||
type Context = WebsocketContext<Self>;
|
type Context = WebsocketContext<Self>;
|
||||||
|
|
||||||
fn started(&mut self, ctx: &mut Self::Context) {
|
fn started(&mut self, ctx: &mut Self::Context) {
|
||||||
|
self.hb(ctx);
|
||||||
let addr = ctx.address();
|
let addr = ctx.address();
|
||||||
self.addr
|
self.addr
|
||||||
.send(Connect {
|
.send(Connect {
|
||||||
|
|
@ -207,6 +230,13 @@ impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for WsChatSession {
|
||||||
Ok(content) => self.handle_msg(content, ctx),
|
Ok(content) => self.handle_msg(content, ctx),
|
||||||
Err(err) => ctx.text(WsMessage::err(err.to_string())),
|
Err(err) => ctx.text(WsMessage::err(err.to_string())),
|
||||||
},
|
},
|
||||||
|
ws::Message::Ping(msg) => {
|
||||||
|
self.hb = Instant::now();
|
||||||
|
ctx.pong(&msg);
|
||||||
|
}
|
||||||
|
ws::Message::Pong(_) => {
|
||||||
|
self.hb = Instant::now();
|
||||||
|
}
|
||||||
ws::Message::Close(reason) => {
|
ws::Message::Close(reason) => {
|
||||||
ctx.close(reason);
|
ctx.close(reason);
|
||||||
ctx.stop();
|
ctx.stop();
|
||||||
|
|
|
||||||
6
src/constants.rs
Normal file
6
src/constants.rs
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
/// How often heartbeat pings are sent
|
||||||
|
pub const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(5);
|
||||||
|
/// How long before lack of client response causes a timeout
|
||||||
|
pub const CLIENT_TIMEOUT: Duration = Duration::from_secs(10);
|
||||||
|
|
@ -3,6 +3,7 @@ mod messages;
|
||||||
mod models;
|
mod models;
|
||||||
mod routes;
|
mod routes;
|
||||||
mod server;
|
mod server;
|
||||||
|
mod constants;
|
||||||
|
|
||||||
use crate::{actors::chat_server::ChatServer, models::AppState, server::init};
|
use crate::{actors::chat_server::ChatServer, models::AppState, server::init};
|
||||||
use actix::Actor;
|
use actix::Actor;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue