Isolate cached feed broadcast consumers #92

Open
goodboy wants to merge 4 commits from wkt/fix_broadcast_consumers into datad_service

4 Commits (main)

Author SHA1 Message Date
Gud Boi 4af885d90f .ib.feed: cache quote channel contexts
Replace the manual `_quote_streams` raw-channel registry with a
symbol-keyed `maybe_open_context()` resource whose lifetime extends to
the final quote consumer.

Give every `open_aio_quote_stream()` caller a lexical child from the
cached `LinkedTaskChannel` broadcaster so concurrent users receive the
same quotes and close independently.

Prompt-IO: ai/prompt-io/opencode/20260813T230744Z_ddac3553_prompt_io.md

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-08-13 19:16:28 -04:00
Gud Boi ddac3553a3 .deribit: own cached price-feed subscriptions
Give every `maybe_open_price_feed()` caller a lexical child from the
cached `LinkedTaskChannel` broadcaster instead of yielding the raw
channel to the first owner and constructing competing roots for hits.

Add a concurrent regression proving miss and hit callers receive the
same quote, close independently, and leave the retained root alive.

Prompt-IO: ai/prompt-io/opencode/20260813T225940Z_b691422b_prompt_io.md

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-08-13 19:04:19 -04:00
Gud Boi b691422b26 .data: isolate cached feed stream consumers
Keep provider root streams private to the cached `Feed` and give every
`maybe_open_feed()` caller, including the first owner, a local
subscription view with copied `Flume` descriptors.

Also,
- key cached resources by the normalized full symbol set and stream
  policy instead of only the first FQME.
- subscribe each `Feed.open_multi_stream()` provider relay and wait for
  all relays to start before yielding the merged channel.
- give each provider relay an independent send-channel clone so one
  provider EOC cannot terminate its siblings.
- document `Feed.pause()` and `Feed.resume()` as shared remote-provider
  controls rather than caller-local cursor operations.
- cover miss/hit ownership, multi-market provider mapping, relay
  fan-out, lexical teardown and cache-key separation.

Prompt-IO: ai/prompt-io/opencode/20260813T202402Z_12b0d66e_prompt_io.md

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-08-13 18:53:44 -04:00
Gud Boi 12b0d66e85 .clearing: own dark quote broadcast subscription
Give `clear_dark_triggers()` a dedicated
`MsgStream.subscribe()` handle with `raise_on_lag=False` instead
of mutating the private lag policy on whichever root or cached
child sits in `Flume.stream`.

Also,
- factor the hot quote loop into `_clear_dark_triggers()` so the
  public task owns the child receiver for its full lifetime.
- add an EMS regression proving the lag policy, child lifetime,
  and source-stream state remain isolated.

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-08-13 13:48:32 -04:00