DpExchange.Webull.Socket (DpExchangeWebull v0.1.1)

Copy Markdown View Source

The MQTT-over-WebSocket connection — internal, never named above the facade.

websockex carries the frames; MqttPacket provides the framing; QuoteProto decodes the payloads. None of those three names can appear in anything a consumer receives.

The buffer is the point

A WebSocket frame is not an MQTT packet. One frame may carry several packets, or half of one, and the broker is under no obligation to align them. So every inbound frame is appended to a buffer and the buffer is drained packet by packet until it returns :incomplete.

Assuming frame boundaries are packet boundaries loses every packet after the first coalesced frame — quietly, because the socket stays up and the first message parses fine.

A :malformed_length means the stream can no longer be resynchronised. The buffer is dropped and a notice raised rather than retaining bytes that can never parse: keeping them would leave a live socket delivering nothing, which is the failure mode this family ranks worst.

Keep-alive

The venue's CONNECT carries a keep-alive interval, and MQTT requires the client to send something within it. PINGREQ goes out at half that interval — early enough that one lost ping is not a disconnect.

What it does not do

It does not subscribe. Subscriptions on this venue are HTTP calls, made by Feed with the same session_id this connection registered as its MQTT client id. The socket's only job is to connect, stay connected, and turn payloads into Core.Types.Quote.

Summary

Functions

start_link(opts)

@spec start_link(keyword()) :: {:ok, pid()} | {:error, term()}