Maximize concurrency when chunking on AutoSharded clients
This commit is contained in:
		| @@ -347,6 +347,7 @@ class ConnectionState: | |||||||
|         try: |         try: | ||||||
|             # only real bots wait for GUILD_CREATE streaming |             # only real bots wait for GUILD_CREATE streaming | ||||||
|             if self.is_bot: |             if self.is_bot: | ||||||
|  |                 states = [] | ||||||
|                 while True: |                 while True: | ||||||
|                     # this snippet of code is basically waiting N seconds |                     # this snippet of code is basically waiting N seconds | ||||||
|                     # until the last GUILD_CREATE was sent |                     # until the last GUILD_CREATE was sent | ||||||
| @@ -355,12 +356,21 @@ class ConnectionState: | |||||||
|                     except asyncio.TimeoutError: |                     except asyncio.TimeoutError: | ||||||
|                         break |                         break | ||||||
|                     else: |                     else: | ||||||
|                         try: |  | ||||||
|                         if self._fetch_offline: |                         if self._fetch_offline: | ||||||
|                                 await asyncio.wait_for(self.chunk_guild(guild), timeout=60.0) |                             future = await self.chunk_guild(guild, wait=False) | ||||||
|  |                             states.append((guild, future)) | ||||||
|  |                         else: | ||||||
|  |                             if guild.unavailable is False: | ||||||
|  |                                 self.dispatch('guild_available', guild) | ||||||
|  |                             else: | ||||||
|  |                                 self.dispatch('guild_join', guild) | ||||||
|  |  | ||||||
|  |                 for guild, future in states: | ||||||
|  |                     try: | ||||||
|  |                         await asyncio.wait_for(future, timeout=5.0) | ||||||
|                     except asyncio.TimeoutError: |                     except asyncio.TimeoutError: | ||||||
|                             log.info('Timed out waiting for chunks while launching ready event.') |                         log.warning('Shard ID %s timed out waiting for chunks for guild_id %s.', guild.shard_id, guild.id) | ||||||
|                         finally: |  | ||||||
|                     if guild.unavailable is False: |                     if guild.unavailable is False: | ||||||
|                         self.dispatch('guild_available', guild) |                         self.dispatch('guild_available', guild) | ||||||
|                     else: |                     else: | ||||||
| @@ -733,12 +743,14 @@ class ConnectionState: | |||||||
|  |  | ||||||
|         return self._add_guild_from_data(data) |         return self._add_guild_from_data(data) | ||||||
|  |  | ||||||
|     async def chunk_guild(self, guild): |     async def chunk_guild(self, guild, *, wait=True): | ||||||
|         future = self.loop.create_future() |         future = self.loop.create_future() | ||||||
|         request = ChunkRequest(guild.id, future) |         request = ChunkRequest(guild.id, future) | ||||||
|         self._chunk_requests.append(request) |         self._chunk_requests.append(request) | ||||||
|         await self.chunker(guild.id, nonce=request.nonce) |         await self.chunker(guild.id, nonce=request.nonce) | ||||||
|  |         if wait: | ||||||
|             await request.future |             await request.future | ||||||
|  |         return request.future | ||||||
|  |  | ||||||
|     async def _chunk_and_dispatch(self, guild, unavailable): |     async def _chunk_and_dispatch(self, guild, unavailable): | ||||||
|         try: |         try: | ||||||
| @@ -1041,20 +1053,32 @@ class AutoShardedConnectionState(ConnectionState): | |||||||
|             except asyncio.TimeoutError: |             except asyncio.TimeoutError: | ||||||
|                 break |                 break | ||||||
|             else: |             else: | ||||||
|                 try: |  | ||||||
|                 if self._fetch_offline: |                 if self._fetch_offline: | ||||||
|                         await asyncio.wait_for(self.chunk_guild(guild), timeout=60.0) |                     # Chunk the guild in the background while we wait for GUILD_CREATE streaming | ||||||
|  |                     future = asyncio.ensure_future(self.chunk_guild(guild)) | ||||||
|  |                 else: | ||||||
|  |                     future = self.loop.create_future() | ||||||
|  |                     future.set_result(True) | ||||||
|  |  | ||||||
|  |                 processed.append((guild, future)) | ||||||
|  |  | ||||||
|  |         guilds = sorted(processed, key=lambda g: g[0].shard_id) | ||||||
|  |         for shard_id, info in itertools.groupby(guilds, key=lambda g: g[0].shard_id): | ||||||
|  |             children, futures = zip(*info) | ||||||
|  |             # 110 reqs/minute w/ 1 req/guild plus some buffer | ||||||
|  |             timeout = 61 * (len(children) / 110) | ||||||
|  |             try: | ||||||
|  |                 await utils.sane_wait_for(futures, timeout=timeout) | ||||||
|             except asyncio.TimeoutError: |             except asyncio.TimeoutError: | ||||||
|                     log.info('Timed out waiting for chunks while launching ready event.') |                 log.warning('Shard ID %s failed to wait for chunks (timeout=%.2f) for %d guilds', self.shard_id, | ||||||
|                 finally: |                                                                                                   timeout, | ||||||
|                     processed.append(guild) |                                                                                                   len(guilds)) | ||||||
|  |             for guild in children: | ||||||
|                 if guild.unavailable is False: |                 if guild.unavailable is False: | ||||||
|                     self.dispatch('guild_available', guild) |                     self.dispatch('guild_available', guild) | ||||||
|                 else: |                 else: | ||||||
|                     self.dispatch('guild_join', guild) |                     self.dispatch('guild_join', guild) | ||||||
|  |  | ||||||
|         guilds = sorted(processed, key=lambda g: g.shard_id) |  | ||||||
|         for shard_id, _ in itertools.groupby(guilds, key=lambda g: g.shard_id): |  | ||||||
|             self.dispatch('shard_ready', shard_id) |             self.dispatch('shard_ready', shard_id) | ||||||
|  |  | ||||||
|         # remove the state |         # remove the state | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user