rbino

rbino

Ash Core Team

Handling partial failures when exposing external data in a resource

Some context to avoid the XY Problem: I’m trying to expose some state which lives in an external API as a resource field.

Let’s say I have a User resource and I want to retrieve the URL for their Gravatar given their email. My understanding is that I can do this with a calculation

  calculations do
    calculate :gravatar_url, :string, User.Calculations.Gravatar
  end
defmodule MyApp.User.Calculations.Gravatar do
  use Ash.Calculation
  alias MyApp.GravatarAPI

  def calculate(users, _opts, _context) do
    Enum.map(users, fn user ->
      case GravatarAPI.fetch_url(user.email) do
        {:ok, url} -> url
        {:error, _} -> nil
      end
    end)
  end
end

The problem with this solution is that if I retrieve a list of users using, e.g., GraphQL, the current implementation just silently returns nil without letting the user know that, e.g., the API request failed for a specific user (which is something which can potentially be shown in GraphQL errors).

On the other hand, if I return {:error, :something} if anything fails a single failed API request makes the calculation fails for all the users.

Is there a way around this? Am I using the wrong Ash tool?

The other possibility I thought of is using a resource with no data layer instead of a calculation. n that case, if I call both Simple.set_data and Ash.Query.add_error does the whole query fails (so nothing gets exposed from GraphQL) or is the partial data shown alongside the error?

Most Liked

zachdaniel

zachdaniel

Creator of Ash

This is a good question :). While I think there is something we could do in the future to make this more seamless, if you have a calculation that can partially fail, the best way to do it is to use an embedded type for the return type.

calculate :gravatar_url, :map, User.Calculations.Gravatar do
  constraints fields:  [
    success: [
      type: :boolean,
      allow_nil?: false
    ],
    url: [
      type: :string,
    ]
  ]  
end
zachdaniel

zachdaniel

Creator of Ash

Yeah…honestly this is probably something that we should add as a feature of calculations, so that calculations should be allowed to fail. Fail-able calculations would have something like field: %Ash.CalculationResult{result: "result", errors: []}. Then AshGraphql could use that :slight_smile:

Where Next?

Popular in Questions Top

Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
chrisalley
ExUnit now has describe blocks which is a welcome addition coming from RSpec. In the docs, it states that nested hierarchies of describe ...
New
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
JulienCorb
I am trying to implement my new.html.eex file to create new posts on my website. new.html.eex: <h1>Create Post</h1> <%= ...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" => #BSON.ObjectId<58eb1a7a9ad169198c3dXXXX>, "email" => ...
New

Other popular topics Top

Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
josevalim
Hi everyone, One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 36128 110
New
komlanvi
Hi everyone, I was playing with phoenix liveView but I run into an issue. I have a form and want to validate each input text when the te...
New
Qqwy
Update: How to use the Blogs & Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3271 126479 1222
New

We're in Beta

About us Mission Statement