Skip to content

maartenvanvliet/apq

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Apq

.github/workflows/elixir.yml Hex pm Hex Docs License

Support for Automatic Persisted Queries in Absinthe. Query documents in GraphQL can be be of a significant size. Especially on mobile it may be beneficial to limit the size of the queries so fewer bytes go across the network. APQ uses a deterministic hash of the input query in a request. If the server does not know the hash the client can retry the request with the expanded query. The server can use this request to store the query in its cache.

You'll need a GraphQL client that can use APQ, such as Apollo Client.

Complete example project is available here

Installation

Since APQ is available in Hex, the package can be installed by adding apq to your list of dependencies in mix.exs:

def deps do
  [
    {:apq, "~> 2.0"}
  ]
end

Examples

Define a new module and use Apq.DocumentProvider:

defmodule ApqExample.Apq do
   use Apq.DocumentProvider,
    cache_provider: ApqExample.Cache,
    max_query_size: 16384 #default

end

If you're going to use GET requests for APQ's hashed queries, you'll need to specify a json_codec that responds to decode!/1 such as Jason or Poison:

defmodule ApqExample.Apq do
   use Apq.DocumentProvider,
    json_codec: Jason

end

In a Phoenix project, this should be set with Phoenix.json_library().

You'll need to implement a cache provider. This is up to you, the provider should implement Apq.CacheProvidr

Cachex cache provider

In this example I use Cachex.

Define a module for the cache, e.g when using Cachex:

defmodule ApqExample.Cachex.Cache do
  @behaviour Apq.CacheProvider

  def get(hash) do
    Cachex.get(:apq_cache, hash)
  end

  def put(hash, query) do
    Cachex.put(:apq_cache, hash, query)
  end
end

You'll need to start it in your supervision tree:

children = [
  worker(Cachex, [ :apq_cache, [ limit: 100 ] ]),
  #...
]

Redis cache provider

When using Redis as a cache provider you can use the Redix library.

You'll need to start a connection to Redis.

children = [
  {Redix, name: :redix}
  #...
]
defmodule ApqExample.Redix do
  @behaviour Apq.CacheProvider

  def get(hash) do
    Redix.command(:redix, ["GET", hash])
  end

  def put(hash, query) do
    Redix.command(:redix, ["SET", hash, query])
  end
end

Now we need to add the ApqExample.Apq module to the list of document providers. This goes in your router file.

match("/api",
  to: Absinthe.Plug,
  init_opts: [
    schema: ApqExample.Schema,
    json_codec: Jason,
    interface: :playground,
    document_providers: [ApqExample.Apq, Absinthe.Plug.DocumentProvider.Default]
  ]
)

This is it, if you query with a client that has support for Apq it should work with Absinthe.

Documentation

Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/apq.