This venue's process tree — internal.
The limiter is configured from what capabilities/0 declares
The declaration is not decoration beside the mechanism; it is the mechanism's configuration, so the two cannot drift.
Webull is the venue whose REST budget is the binding constraint in the family — the prior adapter measured 118 ms per call across 342 symbols — so the ceiling here matters more than on venues with room to spare.
Production and UAT run side by side, with separate everything
A consumer trading live while testing against UAT is running two of this venue at once. Every default name derives from the environment so the two neither collide nor share a rate-limit bucket — the second of which is the dangerous one: UAT traffic metering against the production budget would surface as a throttle on a real order, with nothing pointing back at the cause.
A :name of your own is enough to run two of the same environment under different
credentials: the feed, the limiter and the ledger are named <name>.Feed,
<name>.RateLimiter and <name>.Ledger, and a facade call given the same name: addresses
them. Explicit :feed / :limiter / :ledger still win.
The ledger: a restarted feed picks up where it was
Feed keeps what it was asked to do (wanted symbols, subscribers, replay options) in its own
state, which a crash empties. DpExchange.Webull.Ledger is started before it, outlives it, and
is written on every accepted change; a restarted feed reads it back (see Feed).
Summary
Functions
Returns a specification to start this module under a supervisor.
This venue's feed process, named the way limiter_name/1 names the limiter.
The process holding what the feed was asked to do, named the way limiter_name/1 is.
The limiter this venue meters against: :limiter if given, else <name>.RateLimiter for a
tree started with its own :name, else the environment's default.
The limits this venue's DefaultRateLimiter is started with, for the environment opts
resolves to.
This tree's registered name, environment-derived.
Functions
Returns a specification to start this module under a supervisor.
See Supervisor.
This venue's feed process, named the way limiter_name/1 names the limiter.
The process holding what the feed was asked to do, named the way limiter_name/1 is.
The limiter this venue meters against: :limiter if given, else <name>.RateLimiter for a
tree started with its own :name, else the environment's default.
@spec limits(keyword()) :: %{ required(atom()) => %{ limit: pos_integer(), per_ms: pos_integer(), burst: pos_integer() } }
The limits this venue's DefaultRateLimiter is started with, for the environment opts
resolves to.
Public for the same reason limiter_name/1 and feed_name/1 are: it is a derivation a
reader has to be able to check, and the figure it produces gates every REST call this
package makes. Not part of the facade — DpExchange.Webull is the boundary.
@spec start_link(keyword()) :: Supervisor.on_start()
This tree's registered name, environment-derived.