persistent_term.ex (3295B)
1 if Code.ensure_loaded?(:persistent_term) do 2 defmodule Absinthe.Schema.PersistentTerm do 3 @moduledoc """ 4 Experimental: Persistent Term based Schema Backend 5 6 By default, Absinthe schemas are stored in a generated module. If your schema 7 is called `MyAppWeb.Schema`, Absinthe creates a `MyAppWeb.Schema.Compiled` 8 module containing the structs and other data that Absinthe needs at runtime 9 to execute GraphQL operations against that schema. 10 11 OTP introduced the `:persistent_term` module to provide many of the same 12 performance benefits of using compiled modules, without the downsides associated 13 with manipulating complex structures at compile time. 14 15 This module is an experimental effort at using the `:persistent_term` module 16 as an Absinthe schema backend. This module has been tested against against 17 the entire Absinthe test suite and shown to perform perhaps even better 18 than the compiled module. 19 20 To use: 21 22 In your schema module: 23 ``` 24 use Absinthe.Schema 25 @schema_provider Absinthe.Schema.PersistentTerm 26 ``` 27 28 In your application's supervision tree, prior to anywhere where you'd use 29 the schema: 30 ``` 31 {Absinthe.Schema, MyAppWeb.Schema} 32 ``` 33 34 where MyAppWeb.Schema is the name of your schema. 35 """ 36 37 @behaviour Absinthe.Schema.Provider 38 39 def pipeline(pipeline) do 40 Enum.map(pipeline, fn 41 Absinthe.Phase.Schema.InlineFunctions -> 42 {Absinthe.Phase.Schema.InlineFunctions, inline_always: true} 43 44 {Absinthe.Phase.Schema.Compile, options} -> 45 {Absinthe.Phase.Schema.PopulatePersistentTerm, options} 46 47 phase -> 48 phase 49 end) 50 end 51 52 def __absinthe_type__(schema_mod, name) do 53 schema_mod 54 |> get() 55 |> Map.fetch!(:__absinthe_type__) 56 |> Map.get(name) 57 end 58 59 def __absinthe_directive__(schema_mod, name) do 60 schema_mod 61 |> get() 62 |> Map.fetch!(:__absinthe_directive__) 63 |> Map.get(name) 64 end 65 66 def __absinthe_types__(schema_mod) do 67 schema_mod 68 |> get() 69 |> Map.fetch!(:__absinthe_types__) 70 |> Map.fetch!(:referenced) 71 end 72 73 def __absinthe_types__(schema_mod, group) do 74 schema_mod 75 |> get() 76 |> Map.fetch!(:__absinthe_types__) 77 |> Map.fetch!(group) 78 end 79 80 def __absinthe_directives__(schema_mod) do 81 schema_mod 82 |> get() 83 |> Map.fetch!(:__absinthe_directives__) 84 end 85 86 def __absinthe_interface_implementors__(schema_mod) do 87 schema_mod 88 |> get() 89 |> Map.fetch!(:__absinthe_interface_implementors__) 90 end 91 92 @dialyzer {:nowarn_function, [get: 1]} 93 defp get(schema) do 94 :persistent_term.get({__MODULE__, schema}) 95 end 96 end 97 else 98 defmodule Absinthe.Schema.PersistentTerm do 99 @moduledoc false 100 101 @error "Can't be used without OTP >= 21.2" 102 103 def pipeline(_), do: raise(@error) 104 105 def __absinthe_type__(_, _), do: raise(@error) 106 def __absinthe_directive__(_, _), do: raise(@error) 107 def __absinthe_types__(_), do: raise(@error) 108 def __absinthe_types__(_, _), do: raise(@error) 109 def __absinthe_directives__(_), do: raise(@error) 110 def __absinthe_interface_implementors__(_), do: raise(@error) 111 def __absinthe_prototype_schema__(), do: raise(@error) 112 end 113 end