Refuses a facade option the call does not read.
A misspelled limt: or sinse: that is silently ignored returns a plausible answer to a
different question than the caller asked: the "nearby substitute where there should be an
error" this family exists to avoid. Every facade function that takes a keyword opts calls
check/2 at the boundary, before anything is sent and before an internal key (:limiter
and the like) is added, so a stray key is a caller error.
Where it sits in the check order
Positional arguments first (subscriber, symbols, symbol, range), then the options, then
credentials. An option error is decided before anything is sent, so it is a plain
{:error, _}, never :order_unconfirmed. A function that answers
Venue.not_supported() keeps doing so whatever the options: the endpoint's absence is the
more useful answer.
What is allowed
transport_options/0 is the shared vocabulary, not a list every call accepts. A call that
sends an HTTP request allows transport_options() -- not_read plus the keys it reads
itself, where not_read names each shared key that call cannot honour (no sandbox:
:environment; no URL override: :base_url), and every key it allows reaches
Core.HttpClient or the seam that reads it. A call that sends no request (the feed and
local reads) allows its own keys plus :credentials only. :credentials is exempt because
a consumer hands one credential set to every call, and one a call does not need changes no
answer. A nil-valued key is still a key: a forwarded limt: nil is refused too, because a
caller who typed the key meant something by it.
The earlier rule, "every call allows every transport key", rested on a claim that every
venue forwards them all. Measured in tick AK, it was false in three: environment: :sandbox
sent Robinhood orders to production, Schwab ignored base_url: while sending a live token,
and max_body_bytes: bounded nothing on two venues' REST calls.
What it answers
:ok{:error, {:unknown_option, key}}- the first key (in the caller's order) not allowed{:error, {:invalid_options, opts}}-optsis not a keyword list. Any:credentialsentry ofoptsis replaced by:redactedin the tuple, since the error is logged.
Summary
Functions
Checks opts against the keys allowed.
The shared transport keys, whatever the venue: their names and meanings.
Functions
@spec check(term(), [atom()]) :: :ok | {:error, {:unknown_option, atom()} | {:invalid_options, term()}}
Checks opts against the keys allowed.
Answers :ok, {:error, {:unknown_option, key}} for the first key not in allowed (a
key holding nil counts), or {:error, {:invalid_options, opts}} when opts is not a
keyword list.
Examples
iex> DpExchange.Core.Options.check([limit: 5], [:limit])
:ok
iex> DpExchange.Core.Options.check([limt: 5], [:limit])
{:error, {:unknown_option, :limt}}
iex> DpExchange.Core.Options.check([limt: nil], [:limit])
{:error, {:unknown_option, :limt}}
iex> DpExchange.Core.Options.check(%{limit: 5}, [:limit])
{:error, {:invalid_options, %{limit: 5}}}
@spec transport_options() :: [atom()]
The shared transport keys, whatever the venue: their names and meanings.
Credentials, the environment and base URL, the Req test seams (:plug, :adapter,
:req_adapter), and the limiter, timeout and retry knobs Core.HttpClient reads. A call
that sends a request checks opts against (transport_options() -- not_read) ++ own_keys;
a call that sends none against [:credentials | own_keys] (see the moduledoc).