sezaru
Add "hooks" to read actions to run extra code similar to change after_transaction
This post actually have 2 questions that are kinda related one to another.
Here is what I’m trying to solve, I have some read action in my resource that, when called by our GraphQL API, should also do a :telemetry call to bump our view count metric.
My current solution was to create a manual Absynthe object that calls the read action directly and execute the telemetry as-well:
defmodule Marketplace.Markets.Property.GraphQL do
@moduledoc false
alias Marketplace.Markets.Property
use Absinthe.Schema.Notation
object :markets_property_queries do
field :get_valid_property, :property do
arg :id, non_null(:id)
resolve fn _, %{id: id}, %{context: %{actor: actor}} ->
case Property.get_valid(%{id: id}, actor: actor) do
{:ok, property} ->
execute(property, actor)
{:error, %Ash.Error.Forbidden{}} ->
{:error, :forbidden}
{:error, _} ->
{:error, :not_found}
end
end
end
end
defp execute(%{id: property_id} = property, %{id: actor_id} = _actor) do
:telemetry.execute([:property, :view], %{}, %{
property_id: property_id,
user_id: actor_id
})
{:ok, property}
end
defp execute(%{id: property_id} = property, _actor) do
:telemetry.execute([:property, :view], %{}, %{
property_id: property_id,
user_id: nil
})
{:ok, property}
end
end
This works, but it is very verbose and sits outside the resource.
It also has a problem when the GraphQL user requests to load some other reference inside the resource, it will just fail since the action itself doesn’t load that resource by default.
So, my first question is, can I move this telemetry call inside the action somehow? If it was a create, update, destroy action, I would just simply create a change with after_transaction and put the telemetry there, but this is a read action, so I’m not sure if there is anything “similar” to use for this.
My second question is, assuming the first one is possible, does AshGraphQL add some metadata to the context or somewhere else so I can know that the actions was actually called by my GraphQL API and not by calling the action directly? I just want to trigger the telemetry call when the action is called via my GraphQL API.
Marked As Solved
zachdaniel
Hey! So to answer your specific question:
read :... do
prepare fn query, _ ->
query
|> Ash.Query.before_action(...)
|> Ash.Query.after_action(...)
end
end
You can use preparations and the hooks available to queries to do this.
However, to solve for this general kind of thing, we already broadcast telemetry hooks. You could do something like this when your application starts up.
:telemetry.attach(
"some_id",
[:ash, :your_api_short_name, :read],
&emit_your_events_when_you_see_a_matching_event/4
)
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









