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:

Last Post!

zachdaniel

zachdaniel

Creator of Ash

The recent refactor of calculation loading would likely make this a relatively simple thing to support, but it would take some time/effort still.

Where Next?

Popular in Questions Top

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
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
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
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
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
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New

Other popular topics Top

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
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
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
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 31586 112
New

We're in Beta

About us Mission Statement