Packages
raxx
1.0.0-rc.3
1.1.0
1.0.1
1.0.0
1.0.0-rc.3
1.0.0-rc.2
retired
1.0.0-rc.1
retired
1.0.0-rc.0
retired
0.18.1
0.18.0
0.17.6
0.17.5
0.17.4
0.17.3
0.17.2
0.17.1
0.17.0
0.16.1
0.16.0
retired
0.15.11
0.15.10
0.15.9
0.15.8
0.15.7
0.15.6
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.14
0.14.13
0.14.12
0.14.11
0.14.10
0.14.9
0.14.8
0.14.7
0.14.6
0.14.5
0.14.4
0.14.3
0.14.2
0.14.1
0.14.0
0.13.0
0.12.3
0.12.2
0.12.1
0.12.0
0.11.1
0.11.0
0.10.5
0.10.4
0.10.3
0.10.2
0.10.1
0.10.0
0.9.0
0.8.2
0.8.1
0.8.0
0.7.1
0.7.0
0.6.0
0.5.2
0.5.1
0.5.0
0.4.3
0.4.2
0.4.1
0.4.0
0.3.0
0.2.0
0.1.0
0.0.1
Interface for HTTP webservers, frameworks and clients.
Current section
Files
Jump to
Current section
Files
lib/raxx/context.ex
defmodule Raxx.Context do
@type section_name :: term()
@typedoc """
An opaque type for the context snapshot data.
"""
@opaque snapshot :: map()
@moduledoc """
`Raxx.Context` is a mechanism for simple sharing of state/information between
`Raxx.Middleware`s and `Raxx.Server`s.
It is designed to be flexible and to enable different middlewares to operate
on it without conflicts. Each separate functionality using the context
can be in a different "section", containing arbitrary data.
Context is implicitly shared using the process dictionary and persists for the
duration of a single request/response cycle. If you want to pass the context
to a different process, you need to take its snapshot, pass it explicitly and
"restore" it in the other process. See `Raxx.Context.get_snapshot/0` and
`Raxx.Context.restore_snapshot/1` for details.
"""
@doc """
Sets the value of a context section.
Returns the previous value of the section or `nil` if one was
not set.
"""
@spec set(section_name, term) :: term | nil
def set(section_name, value) do
Process.put(tag(section_name), value)
end
@doc """
Deletes the section from the context.
Returns the previous value of the section or `nil` if one was
not set.
"""
@spec delete(section_name) :: term | nil
def delete(section_name) do
Process.delete(tag(section_name))
end
@doc """
Retrieves the value of the context section.
If the section wasn't set yet, it will return `nil`.
"""
@spec retrieve(section_name, default :: term) :: term
def retrieve(section_name, default \\ nil) do
Process.get(tag(section_name), default)
end
@doc """
Restores a previously created context snapshot.
It will restore the implicit state of the context for the current
process to what it was when the snapshot was created using
`Raxx.Context.get_snapshot/0`. The current context values won't
be persisted in any way.
"""
@spec restore_snapshot(snapshot()) :: :ok
def restore_snapshot(context) when is_map(context) do
new_context_tuples =
context
|> Enum.map(fn {k, v} -> {tag(k), v} end)
current_context_keys =
Process.get_keys()
|> Enum.filter(&tagged_key?/1)
new_keys = Enum.map(new_context_tuples, fn {k, _v} -> k end)
keys_to_remove = current_context_keys -- new_keys
Enum.each(keys_to_remove, &Process.delete/1)
Enum.each(new_context_tuples, fn {k, v} -> Process.put(k, v) end)
end
@doc """
Creates a snapshot of the current process' context.
The returned context data can be passed between processes and restored
using `Raxx.Context.restore_snapshot/1`
"""
@spec get_snapshot() :: snapshot()
def get_snapshot() do
Process.get()
|> Enum.filter(fn {k, _v} -> tagged_key?(k) end)
|> Enum.map(fn {k, v} -> {strip_tag(k), v} end)
|> Map.new()
end
defp tagged_key?({__MODULE__, _}) do
true
end
defp tagged_key?(_) do
false
end
defp strip_tag({__MODULE__, key}) do
key
end
defp tag(key) do
{__MODULE__, key}
end
end