Skip to content

farm: resubscribe from the list the disconnect preserves (ibx#368) - #396

Closed
userFRM wants to merge 1 commit into
deepentropy:mainfrom
userFRM:fix/farm-reconnect-loses-subscriptions
Closed

farm: resubscribe from the list the disconnect preserves (ibx#368)#396
userFRM wants to merge 1 commit into
deepentropy:mainfrom
userFRM:fix/farm-reconnect-loses-subscriptions

Conversation

@userFRM

@userFRM userFRM commented Jul 31, 2026

Copy link
Copy Markdown

Problem

handle_disconnect clears instrument_md_reqs, and reconnect built its resubscription list from that same collection. By the time a reconnect read it the list was empty, so no L1 subscription was ever re-issued.

Every farm reconnect came back with no market data. A caller still held valid instrument ids and the client reported connected, while quotes stayed at the values zero_all_quotes left behind and never updated again. Depth recovered; L1 did not.

What this changes

The resubscription is driven by md_resub_info, which the disconnect preserves for exactly this reason — the comment above those clears says so, and the depth path beside it already works this way.

An unsubscribe issued while the farm is down still takes effect. The disconnect clears the live request list, so the cancel used to return early without dropping the resubscription record, and the reconnect brought back a subscription the caller had cancelled.

A record is replaced rather than skipped when one already exists for the slot. A slot holds one contract at a time, so keeping the earlier entry meant a slot reused during an outage had no record for its new contract, and the identity check then dropped the stale one — leaving a live subscription unrestored.

Identity is the contract, not the slot. Instrument ids are reused, so a slot freed while the farm was down and handed to another contract would otherwise have the old symbol replayed under it. Each record carries the con_id it was issued under. Zero is a valid con_id — a descriptive subscription is identified by its fields rather than a number — so those are told apart by symbol instead.

Tests

  • a_farm_reconnect_resubscribes_what_was_subscribed
  • an_unsubscribe_while_disconnected_is_not_replayed
  • a_reused_slot_records_the_contract_that_holds_it
  • a_reused_instrument_slot_does_not_replay_the_old_subscription
  • a_reused_slot_without_a_con_id_is_told_apart_by_its_symbol

Each fails by name against a compiling reversion of the production line it covers. The socket reads are bounded so a test that stops receiving fails rather than hanging, and the frame is read to its declared FIXCOMP length rather than trusting a single read.

Closes #368.

`handle_disconnect` clears `instrument_md_reqs`, and `reconnect` built its resubscription list from that same collection. By the time a reconnect read it the list was empty, so `active` was empty and no L1 subscription was ever re-issued.

Every farm reconnect came back with no market data. A caller still held valid instrument ids and the client reported connected, while quotes stayed at the values `zero_all_quotes` left behind and never updated again. Depth recovered; L1 did not.

The resubscription is driven by `md_resub_info` instead, which the disconnect preserves for exactly this reason — the comment above those clears says so, and the depth path beside it already works this way. Each entry carries the con_id it was issued under alongside the symbol, exchange, security type and the rest. Instrument slots are reused, so a slot freed while the farm was down and handed to another contract would otherwise have the old symbol replayed under it — the identity the subscription was taken for is what decides, not whether the slot is occupied.

An unsubscribe issued while the farm is down drops that record too. The disconnect clears the live request list, so the cancel used to return early without reaching it — and the reconnect resubscribed something the caller had cancelled.

A record is replaced rather than skipped when one already exists for the slot. A slot holds one contract at a time, so keeping the earlier entry meant a slot reused during an outage had no record for its new contract, and the identity check then dropped the stale one — leaving a live subscription unrestored.

The identity check tells a descriptive subscription apart by its symbol. Zero is a valid contract id — such a contract is identified by its fields, not the number — so two of them in the same reused slot both matched on the number alone and the old description was replayed under the new contract.

Closes deepentropy#368.
@userFRM

userFRM commented Aug 3, 2026

Copy link
Copy Markdown
Author

Same defect as ibx#288: the reconnect re-subscribes from a collection the disconnect has already cleared, so a farm reconnect comes back with no L1 data. ibx#294 carries the fix, driving the resubscribe off the record that survives the disconnect.

Closing this in favour of ibx#288 and ibx#294, which reached it first.

@userFRM userFRM closed this Aug 3, 2026
@userFRM
userFRM deleted the fix/farm-reconnect-loses-subscriptions branch August 4, 2026 09:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

farm: reconnect resubscribes from the collection disconnect clears, so every farm reconnect comes back with no L1 data

1 participant