New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Roadmap: re-think the Client#ready
event
#9300
Milestone
Comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
As brought up internally as of recent, we should potentially re-evaluate how
Client#ready
works for TSR.For the uneducated on Discord gateway intricacies, here's the connection flow:
HELLO
event, which is also when we start sending heartbeatsIDENTIFY
payload of our own, which tells Discord who we are (we pass in our bot token and some shard information)READY
payload, which includes some initial state like the current client userGUILD_CREATE
payloads to be able to lazily populate cache(s)Rather unintuitively, current mainlib only fires
Client#ready
once step 5 is done - or potentially after a timeout in the event some of our guilds aren't coming through (which makes us assume it's unavailable/in an outage).I have 2 key issues with this:
My proposed solution is as follows:
Client#ready
reflect Discord's actualREADY
eventSo, let's look at the different configuration cases and how this would behave in each one:
if
statement becomes completely redundant, more on this laterPartialGuild
with just an id andunavailable: false
!cached
would only be true with cache disabled or if the user was sweeping their guild cache, but I'd say it's better than to encourage users to assertcached!
, considering at any point a change in their caching config could make that assertion completely invalid, and they'd have no compile-time help in tracking that down.await client.guilds.fetch(message.guildId);
just makes an HTTP call toGET /guilds/:id
as expectedisPartial()
in our code example yields true, this means we got this event before the guild came through inGUILD_CREATE
. IME, and technically speaking, I actually doubt this case can really occur, but Discord never documents it as such, so I do strongly believe that it's correct to assume we could be getting other events as theGUILD_CREATE
s come throughREADY
payload, we construct & cache aPartialGuild
as alwayscached.isPartial()
is true, so we runawait client.guilds.fetch(message.guildId);
which just makes an HTTP call toGET /guilds/:id
Alternatively for the third case, albeit much more jank-sounding:
PartialGuild
could have some sort ofpending
property that we set totrue
only if the guild is included inREADY
'sguilds
PartialGuild#fetch
picks up on this internally and and simply waits for the appropriateGUILD_CREATE
event. The client will store a timestamp for when we gotREADY
, so this will only be waiting fortimeout - timestamp
before throwing an error about the guild being unavailable - much like howGET /guilds/:id
would've yielded an error, and subsequently setthis.unavailable
totrue
.Yes, my example is heavily reliant on rather hypothetical API design that most certainly has drawbacks for various other reasons, what I'm trying to get across here is that our handling of the gateway connection flow (and to an extent our structure design around
Guild
) should hit those following core ideas:READY
handling, no moreGUILD_CREATE
timeout madness.Other concerns such as type-safety and handling of partial data are a bit out of scope for what I wanted to get across here, but how we solve those could heavily constrain how we approach this issue.
The text was updated successfully, but these errors were encountered: