Heartbeats bypass the rate limits for gateway
This commit is contained in:
parent
5db9a3551f
commit
d6defbc6b2
@ -67,7 +67,8 @@ class WebSocketClosure(Exception):
|
|||||||
EventListener = namedtuple('EventListener', 'predicate event result future')
|
EventListener = namedtuple('EventListener', 'predicate event result future')
|
||||||
|
|
||||||
class GatewayRatelimiter:
|
class GatewayRatelimiter:
|
||||||
def __init__(self, count=120, per=60.0):
|
def __init__(self, count=110, per=60.0):
|
||||||
|
# The default is 110 to give room for at least 10 heartbeats per minute
|
||||||
self.max = count
|
self.max = count
|
||||||
self.remaining = count
|
self.remaining = count
|
||||||
self.window = 0.0
|
self.window = 0.0
|
||||||
@ -128,7 +129,7 @@ class KeepAliveHandler(threading.Thread):
|
|||||||
|
|
||||||
data = self.get_payload()
|
data = self.get_payload()
|
||||||
log.debug(self.msg, self.shard_id, data['d'])
|
log.debug(self.msg, self.shard_id, data['d'])
|
||||||
coro = self.ws.send_as_json(data)
|
coro = self.ws.send_heartbeat(data)
|
||||||
f = asyncio.run_coroutine_threadsafe(coro, loop=self.ws.loop)
|
f = asyncio.run_coroutine_threadsafe(coro, loop=self.ws.loop)
|
||||||
try:
|
try:
|
||||||
# block until sending is complete
|
# block until sending is complete
|
||||||
@ -560,7 +561,7 @@ class DiscordWebSocket:
|
|||||||
async def send(self, data):
|
async def send(self, data):
|
||||||
delay = self._rate_limiter.get_delay()
|
delay = self._rate_limiter.get_delay()
|
||||||
if delay:
|
if delay:
|
||||||
log.warning('WebSocket is ratelimited, waiting %.2f seconds', delay)
|
log.warning('WebSocket in shard ID %s is ratelimited, waiting %.2f seconds', self.shard_id, delay)
|
||||||
await asyncio.sleep(delay)
|
await asyncio.sleep(delay)
|
||||||
|
|
||||||
self._dispatch('socket_raw_send', data)
|
self._dispatch('socket_raw_send', data)
|
||||||
@ -573,6 +574,14 @@ class DiscordWebSocket:
|
|||||||
if not self._can_handle_close():
|
if not self._can_handle_close():
|
||||||
raise ConnectionClosed(self.socket, shard_id=self.shard_id) from exc
|
raise ConnectionClosed(self.socket, shard_id=self.shard_id) from exc
|
||||||
|
|
||||||
|
async def send_heartbeat(self, data):
|
||||||
|
# This bypasses the rate limit handling code since it has a higher priority
|
||||||
|
try:
|
||||||
|
await self.socket.send_str(utils.to_json(data))
|
||||||
|
except RuntimeError as exc:
|
||||||
|
if not self._can_handle_close():
|
||||||
|
raise ConnectionClosed(self.socket, shard_id=self.shard_id) from exc
|
||||||
|
|
||||||
async def change_presence(self, *, activity=None, status=None, afk=False, since=0.0):
|
async def change_presence(self, *, activity=None, status=None, afk=False, since=0.0):
|
||||||
if activity is not None:
|
if activity is not None:
|
||||||
if not isinstance(activity, BaseActivity):
|
if not isinstance(activity, BaseActivity):
|
||||||
@ -700,6 +709,8 @@ class DiscordVoiceWebSocket:
|
|||||||
log.debug('Sending voice websocket frame: %s.', data)
|
log.debug('Sending voice websocket frame: %s.', data)
|
||||||
await self.ws.send_str(utils.to_json(data))
|
await self.ws.send_str(utils.to_json(data))
|
||||||
|
|
||||||
|
send_heartbeat = send_as_json
|
||||||
|
|
||||||
async def resume(self):
|
async def resume(self):
|
||||||
state = self._connection
|
state = self._connection
|
||||||
payload = {
|
payload = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user