Skip to content

Commit 7a88aff

Browse files
authored
fix(model)!: incoming heartbeat has null data (twilight-rs#2420)
Heartbeats may contain null data. Discord documents this event as containing data, but that's only when sent to the gateway. ``` 2025-02-14T15:50:16.796316Z DEBUG twilight_gateway::shard: received heartbeat 2025-02-14T15:50:16.796359Z WARN gateway_request_members: error receiving event source=ReceiveMessageError { kind: Deserializing { event: "{\"t\":null,\"s\":null,\"op\":1,\"d\":null}" }, source: Some(Error("invalid type: null, expected u64", line: 1, column: 34)) } ```
1 parent dcadfb5 commit 7a88aff

File tree

3 files changed

+15
-20
lines changed

3 files changed

+15
-20
lines changed

twilight-cache-inmemory/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1027,7 +1027,7 @@ impl<CacheModels: CacheableModels> UpdateCache<CacheModels> for Event {
10271027
| Event::EntitlementDelete(_)
10281028
| Event::EntitlementUpdate(_)
10291029
| Event::GatewayClose(_)
1030-
| Event::GatewayHeartbeat(_)
1030+
| Event::GatewayHeartbeat
10311031
| Event::GatewayHeartbeatAck
10321032
| Event::GatewayHello(_)
10331033
| Event::GatewayInvalidateSession(_)

twilight-model/src/gateway/event/gateway.rs

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use std::{
2121
#[derive(Clone, Debug)]
2222
pub enum GatewayEvent {
2323
Dispatch(u64, DispatchEvent),
24-
Heartbeat(u64),
24+
Heartbeat,
2525
HeartbeatAck,
2626
Hello(Hello),
2727
InvalidateSession(bool),
@@ -33,7 +33,7 @@ impl TryFrom<Event> for GatewayEvent {
3333

3434
fn try_from(event: Event) -> Result<Self, Self::Error> {
3535
Ok(match event {
36-
Event::GatewayHeartbeat(v) => Self::Heartbeat(v),
36+
Event::GatewayHeartbeat => Self::Heartbeat,
3737
Event::GatewayHeartbeatAck => Self::HeartbeatAck,
3838
Event::GatewayHello(v) => Self::Hello(v),
3939
Event::GatewayInvalidateSession(v) => Self::InvalidateSession(v),
@@ -298,11 +298,9 @@ impl<'de> Visitor<'de> for GatewayEventVisitor<'_> {
298298
GatewayEvent::Dispatch(s, d)
299299
}
300300
OpCode::Heartbeat => {
301-
let seq = Self::field(&mut map, Field::D)?;
302-
303301
Self::ignore_all(&mut map)?;
304302

305-
GatewayEvent::Heartbeat(seq)
303+
GatewayEvent::Heartbeat
306304
}
307305
OpCode::HeartbeatAck => {
308306
Self::ignore_all(&mut map)?;
@@ -365,7 +363,7 @@ impl Serialize for GatewayEvent {
365363
const fn opcode(gateway_event: &GatewayEvent) -> OpCode {
366364
match gateway_event {
367365
GatewayEvent::Dispatch(_, _) => OpCode::Dispatch,
368-
GatewayEvent::Heartbeat(_) => OpCode::Heartbeat,
366+
GatewayEvent::Heartbeat => OpCode::Heartbeat,
369367
GatewayEvent::HeartbeatAck => OpCode::HeartbeatAck,
370368
GatewayEvent::Hello(_) => OpCode::Hello,
371369
GatewayEvent::InvalidateSession(_) => OpCode::InvalidSession,
@@ -391,16 +389,13 @@ impl Serialize for GatewayEvent {
391389

392390
match self {
393391
Self::Dispatch(_, _) => unreachable!("dispatch already handled"),
394-
Self::Heartbeat(sequence) => {
395-
s.serialize_field("d", &sequence)?;
396-
}
397392
Self::Hello(hello) => {
398393
s.serialize_field("d", &hello)?;
399394
}
400395
Self::InvalidateSession(invalidate) => {
401396
s.serialize_field("d", &invalidate)?;
402397
}
403-
Self::HeartbeatAck | Self::Reconnect => {
398+
Self::Heartbeat | Self::HeartbeatAck | Self::Reconnect => {
404399
s.serialize_field("d", &None::<u64>)?;
405400
}
406401
}
@@ -621,14 +616,14 @@ mod tests {
621616
"t": null,
622617
"s": null,
623618
"op": 1,
624-
"d": 123
619+
"d": null
625620
}"#;
626621

627622
let deserializer = GatewayEventDeserializer::from_json(input).unwrap();
628623
let mut json_deserializer = Deserializer::from_str(input);
629624
let event = deserializer.deserialize(&mut json_deserializer).unwrap();
630625

631-
assert!(matches!(event, GatewayEvent::Heartbeat(123)));
626+
assert!(matches!(event, GatewayEvent::Heartbeat));
632627
}
633628

634629
#[test]
@@ -781,7 +776,7 @@ mod tests {
781776
#[test]
782777
fn serialize_heartbeat() {
783778
serde_test::assert_ser_tokens(
784-
&GatewayEvent::Heartbeat(1024),
779+
&GatewayEvent::Heartbeat,
785780
&[
786781
Token::Struct {
787782
name: "GatewayEvent",
@@ -794,7 +789,7 @@ mod tests {
794789
Token::Str("op"),
795790
Token::U8(OpCode::Heartbeat as u8),
796791
Token::Str("d"),
797-
Token::U64(1024),
792+
Token::None,
798793
Token::StructEnd,
799794
],
800795
);

twilight-model/src/gateway/event/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ pub enum Event {
5959
/// Close message with an optional frame including information about the
6060
/// reason for the close.
6161
GatewayClose(Option<CloseFrame<'static>>),
62-
/// A heartbeat was sent to or received from the gateway.
63-
GatewayHeartbeat(u64),
62+
/// A heartbeat was received from the gateway.
63+
GatewayHeartbeat,
6464
/// A heartbeat acknowledgement was received from the gateway.
6565
GatewayHeartbeatAck,
6666
/// A "hello" packet was received from the gateway.
@@ -250,7 +250,7 @@ impl Event {
250250
| Event::EntitlementCreate(_)
251251
| Event::EntitlementDelete(_)
252252
| Event::EntitlementUpdate(_)
253-
| Event::GatewayHeartbeat(_)
253+
| Event::GatewayHeartbeat
254254
| Event::GatewayHeartbeatAck
255255
| Event::GatewayHello(_)
256256
| Event::GatewayInvalidateSession(_)
@@ -278,7 +278,7 @@ impl Event {
278278
Self::EntitlementDelete(_) => EventType::EntitlementDelete,
279279
Self::EntitlementUpdate(_) => EventType::EntitlementUpdate,
280280
Self::GatewayClose(_) => EventType::GatewayClose,
281-
Self::GatewayHeartbeat(_) => EventType::GatewayHeartbeat,
281+
Self::GatewayHeartbeat => EventType::GatewayHeartbeat,
282282
Self::GatewayHeartbeatAck => EventType::GatewayHeartbeatAck,
283283
Self::GatewayHello(_) => EventType::GatewayHello,
284284
Self::GatewayInvalidateSession(_) => EventType::GatewayInvalidateSession,
@@ -422,7 +422,7 @@ impl From<GatewayEvent> for Event {
422422
fn from(event: GatewayEvent) -> Self {
423423
match event {
424424
GatewayEvent::Dispatch(_, e) => Self::from(e),
425-
GatewayEvent::Heartbeat(interval) => Self::GatewayHeartbeat(interval),
425+
GatewayEvent::Heartbeat => Self::GatewayHeartbeat,
426426
GatewayEvent::HeartbeatAck => Self::GatewayHeartbeatAck,
427427
GatewayEvent::Hello(interval) => Self::GatewayHello(interval),
428428
GatewayEvent::InvalidateSession(r) => Self::GatewayInvalidateSession(r),

0 commit comments

Comments
 (0)