View Source OneAndDone.Plug (One and Done v0.1.1)
Easy to use plug for idempoent requests.
getting-started
Getting started
Add
:one_and_done
to your list of dependencies inmix.exs
:def deps do [ {:one_and_done, "~> 0.1.1"} ] end
Add the plug to your router:
pipeline :api do plug OneAndDone.Plug, # Required: must conform to OneAndDone.Cache (Nebulex.Cache works fine) cache: MyApp.Cache, # Optional: How long to keep entries, defaults to 86_400 (24 hours) ttl: 86_400, # Optional: Which methods to cache, defaults to ["POST", "PUT"] # Used by the default idempotency_key_fn to quickly determine if the request # can be cached. If you override idempotency_key_fn, consider checking the # request method in your implementation for better performance. # `supported_methods` is available in the opts passed to the idempotency_key_fn. supported_methods: ["POST", "PUT"], # Optional: Function reference to generate the idempotency key for a given request. # By default, uses the value of the "Idempotency-Key" header. # Must return a binary or nil. If nil is returned, the request will not be cached. # Default function implementation: # # fn conn, opts -> # Opts is the same as the opts passed to the plug # if Enum.any?(opts.supported_methods, &(&1 == conn.method)) do # conn # |> Plug.Conn.get_req_header("idempotency-key") # Request headers are always downcased # |> List.first() # else # nil # end # end idempotency_key_fn: &OneAndDone.Plug.idempotency_key_from_conn/2, # Optional: Function reference to generate the cache key for a given request. # Given the conn & idempotency key (returned from idempotency_key_fn), this function # should return a term that will be used as the cache key. # By default, it returns a tuple of the module name and the idempotency key. # Default function implementation: fn _conn, idempotency_key -> {__MODULE__, idempotency_key} cache_key_fn: &OneAndDone.Plug.build_cache_key/2 end
That's it! POST and PUT requests will now be cached by default for 24 hours.
telemetry
Telemetry
To monitor the performance of the OneAndDone plug, you can hook into OneAndDone.Telemetry
.
For a complete list of events, see OneAndDone.Telemetry.events/0
.
example
Example
# In your application.ex
# ...
:telemetry.attach_many(
"one-and-done",
OneAndDone.Telemetry.events(),
&MyApp.Telemetry.handle_event/4,
nil
)
# ...
# In your telemetry module:
defmodule MyApp.Telemetry do
require Logger
def handle_event([:one_and_done, :request, :stop], measurements, _metadata, _config) do
duration = System.convert_time_unit(measurements.duration, :native, :millisecond)
Logger.info("Running one_and_done took #{duration}ms")
:ok
end
# Catch-all for unhandled events
def handle_event(_, _, _, _) do
:ok
end
end