Skip to content
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

Change from many create_*_application_command requests to a single bulk_overwrite_*_application_commands request #34

Merged

Conversation

kshannoninnes
Copy link
Contributor

@kshannoninnes kshannoninnes commented Apr 15, 2024

Problem

Nosedrum currently makes one request to Nostrum.Api.create_{guild, global}_application_command for each command being "added". This would be fine if Nosedrum's default storage "Dispatcher" had a way of keeping track of commands while the bot is not running (eg. a database or some other external storage). As it stands, if a bot has to restart it loses all links to the Discord commands. While Discord still maintains the existing commands, the only way to re-link them to the command modules is by re-registering them.

Proposed Solution

Discord (and Nostrum) provide an alternative endpoint to avoid running into rate limits when re-registering commands. By using the bulk_overwrite_*_application_command endpoints we're able to link the existing commands on Discord's side with the modules on our application's side, without running into the 200 per guild daily rate limit applied to the create endpoint.

Essentially it's resorting to a sort of builder pattern. We add all the commands to Nosedrum's command map before calling update_discord/2 which makes a single call to bulk_overwrite_*_application_command.

This Is A Breaking Change

The change from add_command actually sending commands to Discord to simply queueing them up until update_discord/2 is called means that any command registration in existing applications needs to be updated to call update_discord/2 once they have added all their commands.

I'm unaware of how other bot developers implement their command registration when using Nosedrum, so it may also be necessary for bots to perform this add/update step on startup.

Upsides

  • I believe re-adding commands on bot startup is a cleaner solution than storing a text file with command and module names on the file system
  • This minimizes the requests sent to discord for a new bot who's registering their commands for the first time
  • This makes it possible for bots with greater than 200 commands to register their commands initially

Downsides

  • If someone doesn't re-add all commands when calling update_discord/2 they will be deleted, as per Nostrum and Discord documentation.
  • Bots will need to be updated to adjust to this breaking change
  • This is a more complex solution than just storing command names and module names in a file and reading them into the storage on startup

@kshannoninnes
Copy link
Contributor Author

kshannoninnes commented Apr 15, 2024

I'm quite new to contributing to open source, so any and all comments are welcome.

One potential point I can see being brought up is rather than making it a breaking change, it could be more feasible to add it as an alternative registration flow alongside the existing add_command flow. (Edit: I've now implemented this change in a separate branch which I will merge into this one if this is something desirable)

Kalon Shannon-Innes and others added 2 commits April 15, 2024 14:45
@kshannoninnes
Copy link
Contributor Author

Made the queue command flow optional and turned this into a non-breaking change by restoring the add_command functionality.

@jchristgit
Copy link
Owner

Thank you very much for the PR!
I will be busy the coming 1-2 weeks so it may take some time for me to get back to you. From a quick glance this looks great!

@jchristgit jchristgit self-assigned this Apr 19, 2024
@jchristgit jchristgit self-requested a review April 19, 2024 11:39
@jchristgit jchristgit added enhancement New feature or request component:invokers Issues related to command invoker behaviour & implementations labels Apr 19, 2024
Kalon Shannon-Innes and others added 2 commits April 19, 2024 21:48
@kshannoninnes
Copy link
Contributor Author

kshannoninnes commented Apr 19, 2024

Fixed the lint errors and renamed the callback atoms. I think that should fix the failed lint workflow.

No rush, just didn't want it forgotten. Now I know it's been looked at, feel free to take your time!

Copy link
Owner

@jchristgit jchristgit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much!

I have some suggestions for a few small documentation improvements. Otherwise this looks good to me!

@@ -92,13 +92,27 @@ defmodule Nosedrum.Storage do
## Return value
Returns `:ok` if successful, and `{:error, reason}` otherwise.
"""
@callback add_command(
@callback queue_command(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should update the documentation for this to read that it adds the command to the internal dispatch storage, but does not yet send it to Discord, and also that process_queued_commands should be used once all desired commands have been added.

Copy link
Contributor Author

@kshannoninnes kshannoninnes Apr 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be happy to. I'm new to contributing to open source, and relatively new to elixir compared to you guys, so if there's any steps other than just updating the doc comments, let me know.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, just updating the doc comment would be enough 🙂

@doc """
Add a new command under the given name or application command path.

If the command already exists, it will be overwritten.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we document here that when many commands are being registered, it is recommended to use queue_command and process_queue_commands instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, good idea.

lib/nosedrum/storage/dispatcher.ex Outdated Show resolved Hide resolved
@kshannoninnes kshannoninnes force-pushed the feature/bulk-register-commands branch from bb7146f to 1aaf165 Compare April 27, 2024 18:00
@kshannoninnes
Copy link
Contributor Author

I think that's everything commented on, should be good to go a final round against the linter lol

Copy link
Owner

@jchristgit jchristgit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you very much!

@jchristgit jchristgit merged commit a6db8c6 into jchristgit:master Apr 27, 2024
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component:invokers Issues related to command invoker behaviour & implementations enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants