DpExchange.Gemini.Feed (DpExchangeGemini v0.1.1)

Copy Markdown View Source

This venue's subscription lifecycle — internal. The facade's subscribe/2, unsubscribe/2, update_symbols/2, coverage/1 and subscribe_notices/1 are served from here.

Coverage is observed, never intended

A symbol enters the coverage map when a payload for it arrives, never when it is subscribed. That exists because a venue once reported 325 symbols subscribed and confirmed while 174 were delivering; reporting the subscription would have said 325.

A subscribed symbol that has delivered nothing is simply absent, which the facade documents as :not_covered.

Sharding: the host shards this venue nine ways, and this package does not

gemini/feed.ex in the host opens nine sockets, ten pairs each, because the endpoint it uses stopped accepting subscriptions past roughly that count. That is a real measured property — of the old endpoint.

This package speaks wss://ws.gemini.com, where subscription is a single subscribe frame carrying a list of streams, and there is no documented per-connection limit. So there is no shard arithmetic here, and that is a claim with a hole in it worth naming: it has been exercised with a handful of symbols, not with 346. If a limit exists on the new endpoint it will be found by the first consumer to subscribe broadly, and the fix belongs here, in this package, where the measurement will live.

Carrying the host's nine-way split across on the assumption that the new endpoint shares the old one's limit would be worse — nine connections where one may do, justified by a measurement of a different API.

Summary

Functions

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

coverage(feed)

@spec coverage(GenServer.server()) :: %{
  required(String.t()) => :stream | :internal_poll | :not_covered
}

start_link(opts)

@spec start_link(keyword()) :: GenServer.on_start()

subscribe(feed, symbols, opts)

@spec subscribe(GenServer.server(), [String.t()], keyword()) :: :ok | {:error, term()}

subscribe_notices(feed, opts)

@spec subscribe_notices(
  GenServer.server(),
  keyword()
) :: :ok

unsubscribe(feed, symbols)

@spec unsubscribe(GenServer.server(), [String.t()]) :: :ok | {:error, term()}

update_symbols(feed, symbols)

@spec update_symbols(GenServer.server(), [String.t()]) :: :ok | {:error, term()}