Sorry for the bad title, but my understanding of GenServer is still weak.
Basically, I want to make a call to an external API after a user is created (typical Pow user), e.g. after create user, make a POST request to an external API to create/update a resource. This is asynchronous and could fail. Is sending an event to a GenServer’s
handle_info after the user is created which then makes a request to the API an appropriate use of GenServer? It will also be used to wait for a response in case of fail cases and make attempts again to try the request (up to a max number).
Also, if I have another external API to call, is it better to have another GenServer set up per
API provider, or would having a generic GenServer to interface with all external APIs the way to go?
You could use a Task with a Task Supervisor to do it, it is simpler than a GenServer and great for one-off tasks, for more complex behaviours you could use a GenServer, but I always look for the simplest tool that can do the work reliably.
The second option from Three Simple Patterns for Retrying Jobs in Elixir - DockYard has an example of doing a task with retry using it.
Thanks @thomas.fortes for the link, this is exactly what I wanted to know!
Even for “more complex behaviours” you should consider using a dedicated Task/queue manager, e.g. something like Oban.
Could you please explain why it is generally better to use tasks over Genserver?
Genservers have a lot of heavy machinery associated with them and they are designed for robust event driven responsiveness and “doing the right thing” with message-passing distribution and concurrency. Tasks are designed for linear, one-shot work and have no built-in mechanism to handle messages. They also come with extra features to help testability that genserver doesn’t have out of the box.
It’s certainly possible to run linear work in a genserver (often erlang folks do this) but elixir gives you task, so you should use that