feat(pyth-lazer): coalesce feeds into one bulk subscription#143
feat(pyth-lazer): coalesce feeds into one bulk subscription#143jaspersagent wants to merge 2 commits into
Conversation
Per-feed subscriptions made the upstream send one WS frame per feed per channel tick (~3300 frames/s at production scale), saturating the single event loop and inflating both request latency tails and price staleness. New feeds still get an immediate individual subscription for fast first price, but a periodic compaction pass folds every delivering subscription into one bulk subscription make-before-break and drops idle feeds, cutting the standing frame rate to one frame per tick. Feeds that never deliver are never absorbed, so a single entitlement-failing feed cannot poison the bulk subscription.
Address audit of the bulk-subscription change. The compaction interval and make-before-break overlap move from process env to per-module config (bulkCompactInterval, bulkOverlap) so they validate and tune like the other module knobs. Compaction now unsubscribes an individual subscription that was re-created during the overlap window instead of orphaning it, with a test covering the expire-and-re-request race. The reverse symbol lookup iterates the map directly instead of copying it, and subscription ids carry a SubscriptionId type with consistent individual-subscription naming.
| return; | ||
| } | ||
| sendSubscribe(newBulkSubscriptionId, [...newFeedIds]); | ||
| yield* Effect.sleep(config.bulkOverlap); |
There was a problem hiding this comment.
Not sure a sleep is the best approach here.
| // Bulk-subscribe bookkeeping: which subscription ids are individual | ||
| // subscriptions, which feeds the current bulk subscription carries, and | ||
| // which feeds have delivered at least one update. Feeds that never | ||
| // deliver (e.g. entitlement failures) are never absorbed into the bulk |
There was a problem hiding this comment.
What are entitlement failures?
| if ( | ||
| current.value !== newBulkSubscriptionId && | ||
| individualSubscriptionIds.has(current.value) | ||
| ) { |
There was a problem hiding this comment.
Woundn't the first condition here always hold since we never assign newBulkSubscriptionId to the feeds during compaction?
| const carriedOver = new Set<PriceFeedId>(); | ||
| let droppedFromBulk = 0; | ||
| for (const feedId of bulkFeedIds) { | ||
| if (MutableHashMap.has(subscriptions, feedId)) { |
There was a problem hiding this comment.
Technically, this check might not enough because a feed that's been cleaned up due to idleness could be re-subscribed. Under this scenario, we would be carrying over the feed without checking deliveredFeedIds.
There was a problem hiding this comment.
I suppose we could just assume that a feed that has been included in a bulk has been delivered at least once. Or I think we can just add a subscription ID check?
for (const feedId of bulkFeedIds) {
const subId = MutableHashMap.get(subscriptions, feedId);
if (Option.isNone(subId)) {
// Feed has been cleaned up due to idleness
droppedFromBulk++;
} else if (subId.value === bulkSubscriptionId) {
// Carry over
carriedOver.add(feedId);
} else {
// Feed is back on an individual subscription through re-subscribe
// Do not carry over and let it be handled as an absorbable case.
droppedFromBulk++;
}
}
Per-feed Pyth Lazer subscriptions make the upstream send one WS frame per feed per channel tick, which saturates the single event loop: request latency tails and price staleness both balloon, and the congestion spills onto unrelated routes that share the proxy process.