Browse Source

Rewrite RESUME logic to be more in line with what is requested.

Apparently we should always try to RESUME first and if we get
INVALIDATE_SESSION then we should IDENTIFY instead. This is the
preferred way to do RESUMEs.
pull/468/merge
Rapptz 8 years ago
parent
commit
dc486980f8
  1. 11
      discord/client.py
  2. 19
      discord/gateway.py
  3. 7
      discord/shard.py

11
discord/client.py

@ -361,17 +361,12 @@ class Client:
while not self.is_closed(): while not self.is_closed():
try: try:
yield from self.ws.poll_event() yield from self.ws.poll_event()
except (ReconnectWebSocket, ResumeWebSocket) as e: except ResumeWebSocket as e:
resume = type(e) is ResumeWebSocket log.info('Got a request to RESUME the websocket.')
log.info('Got ' + type(e).__name__)
if not resume:
self._ready.clear()
self.ws = yield from DiscordWebSocket.from_client(self, shard_id=self.shard_id, self.ws = yield from DiscordWebSocket.from_client(self, shard_id=self.shard_id,
session=self.ws.session_id, session=self.ws.session_id,
sequence=self.ws.sequence, sequence=self.ws.sequence,
resume=resume) resume=True)
except ConnectionClosed as e: except ConnectionClosed as e:
yield from self.close() yield from self.close()
if e.code != 1000: if e.code != 1000:

19
discord/gateway.py

@ -41,15 +41,9 @@ import struct
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
__all__ = [ 'ReconnectWebSocket', 'DiscordWebSocket', __all__ = [ 'DiscordWebSocket', 'KeepAliveHandler', 'VoiceKeepAliveHandler',
'KeepAliveHandler', 'VoiceKeepAliveHandler',
'DiscordVoiceWebSocket', 'ResumeWebSocket' ] 'DiscordVoiceWebSocket', 'ResumeWebSocket' ]
class ReconnectWebSocket(Exception):
"""Signals to handle the RECONNECT opcode."""
def __init__(self, shard_id):
self.shard_id = shard_id
class ResumeWebSocket(Exception): class ResumeWebSocket(Exception):
"""Signals to initialise via RESUME opcode instead of IDENTIFY.""" """Signals to initialise via RESUME opcode instead of IDENTIFY."""
def __init__(self, shard_id): def __init__(self, shard_id):
@ -128,8 +122,8 @@ class DiscordWebSocket(websockets.client.WebSocketClientProtocol):
REQUEST_MEMBERS REQUEST_MEMBERS
Send only. Asks for the full member list of a guild. Send only. Asks for the full member list of a guild.
INVALIDATE_SESSION INVALIDATE_SESSION
Receive only. Tells the client to invalidate the session and IDENTIFY Receive only. Tells the client to optionally invalidate the session
again. and IDENTIFY again.
HELLO HELLO
Receive only. Tells the client the heartbeat interval. Receive only. Tells the client the heartbeat interval.
HEARTBEAT_ACK HEARTBEAT_ACK
@ -306,7 +300,7 @@ class DiscordWebSocket(websockets.client.WebSocketClientProtocol):
# internal exception signalling to reconnect. # internal exception signalling to reconnect.
log.info('Received RECONNECT opcode.') log.info('Received RECONNECT opcode.')
yield from self.close() yield from self.close()
raise ReconnectWebSocket(self.shard_id) raise ResumeWebSocket(self.shard_id)
if op == self.HEARTBEAT_ACK: if op == self.HEARTBEAT_ACK:
return # disable noisy logging for now return # disable noisy logging for now
@ -323,12 +317,13 @@ class DiscordWebSocket(websockets.client.WebSocketClientProtocol):
return return
if op == self.INVALIDATE_SESSION: if op == self.INVALIDATE_SESSION:
self.sequence = None
self.session_id = None
if data == True: if data == True:
yield from self.close() yield from self.close()
raise ResumeWebSocket(self.shard_id) raise ResumeWebSocket(self.shard_id)
self.sequence = None
self.session_id = None
log.info('Shard ID %s has either failed a RESUME request or needed to invalidate its session.' % self.shard_id)
yield from self.identify() yield from self.identify()
return return

7
discord/shard.py

@ -54,10 +54,9 @@ class Shard:
def poll(self): def poll(self):
try: try:
yield from self.ws.poll_event() yield from self.ws.poll_event()
except (ReconnectWebSocket, ResumeWebSocket) as e: except ResumeWebSocket as e:
resume = type(e) is ResumeWebSocket log.info('Got a request to RESUME the websocket.')
log.info('Got ' + type(e).__name__) self.ws = yield from DiscordWebSocket.from_client(self._client, resume=True,
self.ws = yield from DiscordWebSocket.from_client(self._client, resume=resume,
shard_id=self.id, shard_id=self.id,
session=self.ws.session_id, session=self.ws.session_id,
sequence=self.ws.sequence) sequence=self.ws.sequence)

Loading…
Cancel
Save