@@ -192,7 +192,8 @@ impl ChannelAdapter for DiscordAdapter {
192192 info ! ( "Discord gateway connected" ) ;
193193
194194 let ( mut ws_tx, mut ws_rx) = ws_stream. split ( ) ;
195- let mut _heartbeat_interval: Option < u64 > = None ;
195+ let mut heartbeat_tick = tokio:: time:: interval ( Duration :: from_millis ( 45_000 ) ) ;
196+ heartbeat_tick. reset ( ) ;
196197
197198 // Inner message loop — returns true if we should reconnect
198199 let should_reconnect = ' inner: loop {
@@ -206,6 +207,21 @@ impl ChannelAdapter for DiscordAdapter {
206207 }
207208 continue ;
208209 }
210+ _ = heartbeat_tick. tick( ) => {
211+ let seq = * sequence. read( ) . await ;
212+ let hb = serde_json:: json!( { "op" : opcode:: HEARTBEAT , "d" : seq } ) ;
213+ if let Err ( e) = ws_tx
214+ . send( tokio_tungstenite:: tungstenite:: Message :: Text (
215+ serde_json:: to_string( & hb) . unwrap( ) ,
216+ ) )
217+ . await
218+ {
219+ error!( "Discord: failed to send heartbeat: {e}" ) ;
220+ break ' inner true ;
221+ }
222+ debug!( "Discord heartbeat sent" ) ;
223+ continue ;
224+ }
209225 } ;
210226
211227 let msg = match msg {
@@ -248,7 +264,9 @@ impl ChannelAdapter for DiscordAdapter {
248264 opcode:: HELLO => {
249265 let interval =
250266 payload[ "d" ] [ "heartbeat_interval" ] . as_u64 ( ) . unwrap_or ( 45000 ) ;
251- _heartbeat_interval = Some ( interval) ;
267+ heartbeat_tick =
268+ tokio:: time:: interval ( Duration :: from_millis ( interval) ) ;
269+ heartbeat_tick. reset ( ) ;
252270 debug ! ( "Discord HELLO: heartbeat_interval={interval}ms" ) ;
253271
254272 // Try RESUME if we have a session, otherwise IDENTIFY
0 commit comments