defmodule Fennel.Cache do
require Logger
alias Fennel.{Notifier, Operation, Telemetry}
alias Fennel.Cache.{Observer, Data, Normalizer, Denormalizer}
# Cache should be Absinthe plugin
def name(), do: __MODULE__
def current() do
# TODO: Optimize it. Save in process/registry info that it had been registered?
:ok = Observer.watch_me(Data.prefix())
name()
end
# def entity_key(client, _entity) do
# {:error, :missing}
# end
# def resolve(client, _entity, _field, _args \\ []) do
# end
# def invalidate(client, _entity, _field \\ nil, _args \\ []) do
# end
def update_operation(_client, operation, updater) do
update_operation(operation, %{}, updater)
end
def update_operation(_client, _operation, _variables, _updater) do
# Data.get_and_update(current(), build_operation_key(operation, variables))
# |> case do
# {:ignore, err} -> err
# val -> val
# end
end
def read_operation(ctx, operation) do
operation_key = build_operation_key(operation, ctx.variables)
Data.fetch(current(), operation_key)
|> case do
{:error, _err} = reply ->
Telemetry.cache(:miss, operation_key)
reply
{:ok, val} ->
Telemetry.cache(:hit, operation_key)
Denormalizer.call(ctx.client, operation, val)
end
end
def write_operation(ctx, operation, response) do
operation_key = build_operation_key(operation, ctx.variables)
{keys_values, metadata} = Normalizer.call(ctx.client, operation, operation_key, response)
Data.put(current(), keys_values)
|> case do
{:ok, true} ->
Telemetry.cache(:write, operation_key)
Notifier.updated_cache_entities(ctx, operation, {
keys_values,
metadata
})
:ok
end
end
# Updates entity partially
# def read_fragment(client, _operation, _variables) do
# end
# def write_fragment(client, _operation, _variables) do
# end
def build_operation_key(operation, variables) do
query = Operation.to_query(operation)
[query, variables]
end
end