55 lines
1.4 KiB
Elixir
55 lines
1.4 KiB
Elixir
defprotocol Wafer.Release do
|
|
alias Wafer.Conn
|
|
|
|
@moduledoc """
|
|
A protocol for releasing connections. The opposite of `Conn`'s `acquire/1`.
|
|
|
|
## Deriving
|
|
|
|
If you're implementing your own `Conn` type that simply delegates to one of
|
|
the lower level drivers that you can derive this protocol automatically:
|
|
|
|
```elixir
|
|
defstruct MyConn do
|
|
@derive Wafer.Release
|
|
defstruct [:conn]
|
|
end
|
|
```
|
|
|
|
If your type uses a key other than `conn` for the inner connection you can specify it while deriving:
|
|
|
|
```elixir
|
|
defstruct MyConn do
|
|
@derive {Wafer.Release, key: :pin_conn}
|
|
defstruct [:pin_conn]
|
|
end
|
|
```
|
|
"""
|
|
|
|
@doc """
|
|
Release all resources associated with the connection. Usually in preparation
|
|
for shutdown.
|
|
"""
|
|
@spec release(Conn.t()) :: :ok | {:error, any}
|
|
def release(conn)
|
|
end
|
|
|
|
defimpl Wafer.Release, for: Any do
|
|
defmacro __deriving__(module, struct, options) do
|
|
key = Keyword.get(options, :key, :conn)
|
|
|
|
unless Map.has_key?(struct, key) do
|
|
raise(
|
|
"Unable to derive `Wafer.Release` for `#{module}`: key `#{inspect(key)}` not present in struct."
|
|
)
|
|
end
|
|
|
|
quote do
|
|
defimpl Wafer.Release, for: unquote(module) do
|
|
def release(%{unquote(key) => inner_conn}), do: Wafer.Release.release(inner_conn)
|
|
end
|
|
end
|
|
end
|
|
|
|
def release(unknown), do: {:error, "`Wafer.Release` not implemented for #{inspect(unknown)}"}
|
|
end
|