Failure Handling With Listeners.
This is more a design/architecture question. Just need more input.
So, a few of the commands I am writing for my bot are getting… complicated. By that I mean, database state is being updated, which leads to server categories being updated, and channels being updated, etc…So, instead of putting all the logic in my command class, I decided to go the event emitter route and
this.container.client.emit()
route and move the server channel/category/role updating to a listener that just responds to the custom event I emitted.
Something that crosses my mind though is how to handle if one of the listeners fail for whatever reason.
Does Sapphire provide an option to automatically retry listeners if they fail? Or am I gonna need to manually handle that somehow?Solution:Jump to solution
There's retry package by sapphire which can ease your retry attempts.
But you have to manually handle the errors & retry attempts...
10 Replies
Solution
There's retry package by sapphire which can ease your retry attempts.
But you have to manually handle the errors & retry attempts
But there's sapphire client event (I think the name was listener error 🤔)
Which you can use 🤔
Also it's far easier to instead of moving it to listeners move it to wholly independent files (I.e. src/lib or src/utils) and await functions in your command.
I do that already. The challenge is there are multiple things that can go wrong, and need to be undone/rolled back if they fail. And, adding that rollback logic just makes everything more convoluted.
For example, a command runs and some data is persisted to my database. In success, a new channel is created in some category. And after that, the bot sends a message to that created channel, then as a side effect, the bot sends a message to the logging channel.
If anything fails in the subsequent steps after the data is saved to the DB, rolling back will just be way harder. I.e. the created channel would need to be deleted (which could also fail), and as a result of that, the database record that was created needs to be deleted because it saved the channel ID which now doesn’t exist. And so forth.
It’s much easier to read code when all it does is save stuff to the DB and then fire an event and let someone else handle the rest.
Well then what MRDGH said I guess
Ooh. I found the Event. What’s the retry package you are referring to?
Is it a third-party? I’m looking all over GitHub for it. lol
It's in sapphire utilities
Ah. Found it. Thank you. 🙂
Alternatively you could write a transactional function which also describes how to rollback each step
Something like
But that's probably quite hard to manage. The idea is that the first parameter is the executor and the second (variadic if you need multiple steps) rolls back. For example you could have
this could even be a method annotation for a class method with some extra work
The syntax then would roughly be
All depends on how advanced you want to get
Yeah. Thats an option. I’m not a fan of adding even more complexity though.
For now, I’ll just use the
retry()
option and just have it fail somewhat gracefully if hell breaks loose. 🙂