cronokirby / alchemy

A discord library for Elixir
MIT License
152 stars 34 forks source link

Runtime loading of cogs #95

Open khionu opened 4 years ago

khionu commented 4 years ago

Atm, I don't see a way to start a Cog at runtime. I would like to be able to unload a cog, then load a replacement as needed. Main reasons for this are hotfixes and inconsequential updates that shouldn't necessitate a redeploy.

cronokirby commented 4 years ago

Calling https://hexdocs.pm/discord_alchemy/0.6.0/Alchemy.Cogs.html#unload/1, then reloading the module in iex, and then calling use Cog again should work, iirc.

khionu commented 4 years ago

But that would restart the whole bot, would it not?

cronokirby commented 4 years ago

You just need to reload the Cog module, I was a bit unclear. You can do that while keeping the rest of the bot running.

khionu commented 4 years ago

Huh, nice! I would suggest making it a little more clear in the docs that Cogs load themselves into the Client on module load.

cronokirby commented 4 years ago

Yeah use is a bit magical in general: https://elixir-lang.org/getting-started/alias-require-and-import.html#use But basically it runs code defined in the Cog module you've created. And by using Cogs.def and the other macro, you're defining what code is going to be in that startup function. Then when you call use Cog, it uses that startup function to register all the command handlers you've defined in that Cog.

Strictly speaking, if you don't change the arity of any of your Cog functions / command handlers, or add new handlers you don't even need to call Cogs.unload, since the function references will be valid, and elixir's hot reloading mechanism will mean that the functions will point to the new ones as soon as the module is reloaded.

use Cog is needed whenever you've introduced new commands, and need to register those as well. You usually want to call Cogs.unload prior to this, to make sure you don't have stale references to functions that don't exist anymore though.

TLDR reloading the Cog module in the repl, calling Cogs.unload and then running use Cog will always work.

The docs could use a section explaining how to hot reload things, it definitely isn't super clear atm...

khionu commented 4 years ago

That makes everything clear, thank you!