ZucchiniZe

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

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:

  1. 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
  2. store the transformed entities in the DB: the advantage here is speed (negligible)
  3. 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

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

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.

Where Next?

Popular in Questions Top

sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
Tee
can someone please explain to me how Enum.reduce works with maps
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New
earth10
Hi, I’m just starting to build a side-project with Elixir and Phoenix and doing some basic test with Elixir alone. What strikes me is th...
New
LegitStack
I’m trying to make a websocket server in Phoenix or raw Elixir. I heard about gun, I think I could use cowboy, but since I’m not that sma...
New
RisingFromAshes
I’ve read in another post that it may be possible with a router helper - but I couldn’t find an appropriate one, and tbh, I’m still just ...
New
marick
I had some trouble figuring out how to make many-to-many associations work. Once I got it working, I wrote a blog post. Because I’m a nov...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

Other popular topics Top

malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
Nvim
Anybody knows a comprehensive comparison of Django and Phoenix, thanks for the help. Where are they similar? Where do they differ the m...
New
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
klo
Got a question about when to concat vs. prepending items to list then reversing to achieve appending. So i know lists boil down to [1 | ...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New

We're in Beta

About us Mission Statement