ZucchiniZe
New to elixir, having trouble with interfacing with a shaky external API
I’m trying to build a website that imports data from an external API that is unbearably slow as well as being quite unreliable. Right now while piecing it together I have everything (somewhat) working with a manual invocation of the functions in IEx and then fixing the inevitable errors that happen.
The API that I’m querying has a hard limit on the amount of resources you can get per request so I’ve solved that by using Enum.map and Task.async + Task.await to get the responses and then am using an ecto multi to handle the bulk insertion of the entities. But since the entities are interlinked from the API as well as in my database schema. I need a consistent way to not fail or automatically fix the errors of when a linked resource doesn’t exist.
I’m also going to try and have this on some sort of cron job or repeating background job to go through and refresh the data from the external API.
Is there some sort of way to implement an automatic retry for failed requests and some sort of thing that reacts to missing data and requests it from the API?
Most Liked
stefanchrobot
If I got that correctly, your app uses an external API to fetch data, transforms that into your own format, saves that in DB and then exposes that through your own API. The problem is that the external API is really unreliable. As a consequence, you don’t really have an option to implement it via hot calls.
So what I’m suggesting is that you “clone” the external database. You have options here:
- dump the responses from the API straight into the DB: the advantage here is that you can easily change your own JSON schema (add more attributes, etc.), since the external data sits in your DB
- store the transformed entities in the DB: the advantage here is speed (negligible)
- do both
Seems like the problem that you need to solve here is to decide what data and when to pull it from the external API.
As to what:
- can you store everything locally? what’s the estimated data set? can you afford this?
- does your application need all the data?
As to when:
- does the external API has web hooks or any other notification mechanism?
- does the external API has an incremental endpoint (i.e. give me what changed since timestamp)?
- if you need to poll for data, what’s the acceptable timespan? how is this affected by quota?
Depending on the answers, the whole thing might event turn infeasible (I hope not!).
I’d implement this export as a worker that runs continuously in the background under it’s own supervision tree. As to how organize this - it really depends on the structure of the data and what the external API gives you. But my first approach would be a process that has a queue of messages, where each message represents a resource to be fetched. For each message, a task is spawned to fetch the data. If it fails, the message is resent to try again. Some additional process would also periodically request fetching of all resources.
outlog
you can do retries with tesla
https://github.com/teamon/tesla
the missing data part, sounds domain specific so I think you would have to roll your own, maybe against a changeset, and if it’s invalid you load in the missing data from the api..
for the cron part you can use quantum GitHub - c-rack/quantum-elixir: Cron-like job scheduler for Elixir · GitHub
stefanchrobot
I would consider making a mirror of the external system, i.e. dump the data (JSON, XML, whatnot) into your database as is; put that into a worker and handle external API failures there.. Then add a separate worker that would transform and upload the data to the destination. This might make for a cleaner design and better performance.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








