Predefine Plugins

Learn about built-in plugins, their types and use.

Built-in Plugins

A plugin in Absinthe is any module that implements the Absinthe.Plugin behaviour. It is not uncommon for a plugin module to implement the Absinthe.Middleware behavior because the two behaviors work together. The middleware callbacks handle changes that need to happen to each field, while the plugin callbacks operate at the document level. We’ll start by looking at two simple plugins built into Absinthe itself. These will help us get the hang of how plugins work, and each has use cases where they’re the perfect tool for the job.

Async

A step in the direction of efficient execution would be to run each field concurrently. It doesn’t get rid of the N+1 query. However, it does mean that by doing all the N at the same time, we can improve our response time. While obviously not the optimal solution for SQL-based data, async execution is useful when dealing with external APIs. Async is one of the simplest plugins. Let’s give it a look as a way to get acquainted with it. Let’s head back to our category_for_item/3 resolver function and make it async. To do this, we’ll use a helper built into Absinthe—async/1, which we’ll import from the Absinthe.Resolution.Helpers module:

Press + to interact
import Absinthe.Resolution.Helpers, only: [async: 1]
# «Rest of file»
def category_for_item(menu_item, _, _) do
async(fn ->
query = Ecto.assoc(menu_item, :category)
{:ok, PlateSlate.Repo.one(query)}
end) |> IO.inspect
end

The change to the resolution function is very small. We wrap the body of the function in an 0-arity anonymous function and then pass that to async/1. This is very much like we would do with Task.async. We’ve added an IO.inspect after our async call, and if we run a query, we’ll see a return value we’ve never seen before:

Steps ...