Skip to content
This repository has been archived by the owner on Dec 26, 2022. It is now read-only.

Commit

Permalink
馃悰 gateway no longer starts multiple instances (#354)
Browse files Browse the repository at this point in the history
* 馃悰 gateway no longer starts multiple instances

* 馃悰 gateway now relogs correctly after invalid session

* 馃帹 small code cleanup

* 鈾伙笍 shorten logging message

* 馃悰 close socket on invalid session

* 馃帹 add bool to GatewayDispatch typehint
  • Loading branch information
Lunarmagpie committed Jan 8, 2022
1 parent 9ba47f3 commit 515d4a8
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 18 deletions.
4 changes: 2 additions & 2 deletions pincer/core/dispatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ class GatewayDispatch:
def __init__(
self,
op: int,
data: Optional[Union[int, Dict[str, Any]]] = None,
data: Optional[Union[int, bool, Dict[str, Any]]] = None,
seq: Optional[int] = None,
name: Optional[str] = None
):
self.op: int = op
self.data: Optional[Union[int, Dict[str, Any]]] = data
self.data: Optional[Union[int, bool, Dict[str, Any]]] = data
self.seq: Optional[int] = seq
self.event_name: Optional[str] = name

Expand Down
36 changes: 20 additions & 16 deletions pincer/core/gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ def __init__(
}

# 4000 and 4009 are not included. The client will reconnect when receiving
# either.
# either. Code 4000 is also used for internal disconnects that will lead to a
# reconnect.
self.__close_codes: Dict[int, GatewayError] = {
4001: GatewayError("Invalid opcode was sent"),
4002: GatewayError("Invalid payload was sent."),
Expand Down Expand Up @@ -140,7 +141,7 @@ def __init__(

# The gateway can be disconnected from Discord. This variable stores if the
# gateway should send a hello or reconnect.
self.__should_reconnect: bool = False
self.__should_resume: bool = False

# The sequence number for the last received payload. This is used reconnecting.
self.__sequence_number: int = 0
Expand Down Expand Up @@ -258,8 +259,8 @@ async def event_loop(self):
"%s Disconnected from Gateway due without any errors. Reconnecting.",
self.shard_key
)
self.__should_reconnect = True
await self.start_loop()
# ensure_future prevents a stack overflow
ensure_future(self.start_loop())

async def handle_data(self, data: Dict[Any]):
"""|coro|
Expand Down Expand Up @@ -310,19 +311,25 @@ async def handle_reconnect(self, payload: GatewayDispatch):
self.shard_key
)

self.__should_resume = True
await self.__socket.close()
self.__should_reconnect = True
await self.start_loop()

async def handle_invalid_session(self, payload: GatewayDispatch):
"""|coro|
Opcode 9 - Invalid connection
Attempt to relog. This is probably because the session was already invalidated
when we tried to reconnect.
"""
_log.debug("%s Invalid session, attempting to relog...", self.shard_key)
self.__should_reconnect = False
await self.start_loop()

_log.debug(
"%s Invalid session, attempting to %s...",
self.shard_key,
"reconnect" if payload.data else "relog"
)

self.__should_resume = payload.data
self.stop_heartbeat()
await self.__socket.close()

async def identify_and_handle_hello(self, payload: GatewayDispatch):
"""|coro|
Expand All @@ -334,7 +341,7 @@ async def identify_and_handle_hello(self, payload: GatewayDispatch):
Successful reconnects are handled in the `resumed` middleware.
"""
if self.__should_reconnect:
if self.__should_resume:
_log.debug("%s Resuming connection with Discord", self.shard_key)

await self.send(str(GatewayDispatch(
Expand Down Expand Up @@ -363,8 +370,6 @@ async def identify_and_handle_hello(self, payload: GatewayDispatch):
))
self.__heartbeat_interval = payload.data["heartbeat_interval"]

# This process should already be forked to the background so there is no need to
# `ensure_future()` here.
self.start_heartbeat()

async def handle_heartbeat(self, payload: GatewayDispatch):
Expand Down Expand Up @@ -452,14 +457,13 @@ async def __heartbeat_loop(self):
# Close code is specified to be anything that is not 1000 in the docs.
_log.debug(
"%s %s ack not received. Attempting to reconnect."
" Closing socket with close code 1001. \U0001f480",
" Closing socket with close code 4000. \U0001f480",
datetime.now(),
self.shard_key
)
await self.__socket.close(code=1001)
self.__should_reconnect = True
await self.__socket.close(code=4000)
self.__should_resume = True
# A new loop is started in the background while this one is stopped.
ensure_future(self.start_loop())
self.stop_heartbeat()
return

Expand Down

0 comments on commit 515d4a8

Please sign in to comment.