Skip to content

Refactor Pyth Lazer to run one bulk subscription per channel - #167

Merged
hacheigriega merged 6 commits into
mainfrom
hy/pyth-bulk-refactor
Aug 20, 2026
Merged

Refactor Pyth Lazer to run one bulk subscription per channel#167
hacheigriega merged 6 commits into
mainfrom
hy/pyth-bulk-refactor

Conversation

@hacheigriega

@hacheigriega hacheigriega commented Aug 19, 2026

Copy link
Copy Markdown
Member

Motivation

Alternative approach to #165 in order to reduce number of incoming messages (frames). Cleaner approach thanks to @Thomasvdam

Explanation of Changes

We now keep at most one subscription per channel.

  • The module sends out subscription requests whenever the desired set (tracked by the subscriptions map) "grows" or gains any new IDs.
  • The module tracks the current active subscription per channel with a simple logic: It only updates the current active subscription when it receives an ack for a subscription whose ID is greater than the currently active subscription's.
  • Idle clean up only removes the ID from the desired set. For it to be actually removed from the subscription, we wait for a future request that grows the desired set.
  • Invalid IDs (not u32) cause a WebSocket Pool error. To prevent invalid symbols from getting stuck in the desired set and causing failures for all future subscriptions, we fail requests containing non-u32 IDs.
  • I noticed that the subscribe ack message returns a list of unknown feed IDs. Currently we don't do anything with it, but we could consider keeping a list of unknown IDs and returning 400 to requests containing one of those.

Testing

Added unit tests and tested locally

Related PRs and Issues

Alternative to #165

@Thomasvdam

Copy link
Copy Markdown
Member

I noticed that the subscribe ack message returns a list of invalid feed IDs. Currently we don't do anything with it, but we could consider keeping a list of invalid IDs and returning 400 to requests containing one of those.

Great find! Sounds like a nice improvement over the current behaviour that simply times out after 3 seconds :)

@Thomasvdam Thomasvdam left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Obviously I think this is cleaner, but I hope it's more than just personal preference 😂

Just a few small nitpicks, the flow looks great and the docs nicely outline how the design works and the tradeoffs/limitations in the current implementation.

Maybe in a future cleanup it's worth splitting some of the logic into Effect services to make testing a little easier, but lets not get into that now. :)

Comment thread workspace/data-proxy/src/modules/pyth-lazer/pyth-lazer.ts
Comment thread workspace/data-proxy/src/modules/pyth-lazer/pyth-lazer.ts Outdated
Comment thread workspace/data-proxy/src/modules/pyth-lazer/pyth-lazer.ts Outdated
@hacheigriega
hacheigriega force-pushed the hy/pyth-bulk-refactor branch from e02a02d to 1f5201e Compare August 20, 2026 12:51
@hacheigriega

Copy link
Copy Markdown
Member Author

Great find! Sounds like a nice improvement over the current behaviour that simply times out after 3 seconds :)

I suppose we could add an LRU cache of certain capacity, but now I am no longer sure about returning 400 to requests containing IDs that have been returned as unknown from Pyth. I thought Pyth recommends ignoreInvalidFeedIds precisely because feed IDs can become valid or invalid at any time. And of course, simply removing unknown IDs from the desired set doesn't help because next requests would just add them back.

Maybe in a future cleanup it's worth splitting some of the logic into Effect services to make testing a little easier

Ah good point, well noted!!

A numeric token that is not u32 makes the client WebSocket pool return
an invalid value error, which then blocks all future subscriptions.
@hacheigriega
hacheigriega force-pushed the hy/pyth-bulk-refactor branch from 7b5d01d to 3584526 Compare August 20, 2026 14:24
Newer Bun coerces env writes to strings.
@hacheigriega
hacheigriega force-pushed the hy/pyth-bulk-refactor branch from 4fe33ca to baf22f0 Compare August 20, 2026 15:14
@hacheigriega
hacheigriega force-pushed the hy/pyth-bulk-refactor branch from baf22f0 to 90c77da Compare August 20, 2026 15:34
Without a pre-configured feed, the module repeats a cycle of successful
connection followed by 5-second timeout indefinitely. If no feed is
provided in the config, a default one is used for
backward compatibility.
@hacheigriega
hacheigriega force-pushed the hy/pyth-bulk-refactor branch from 90c77da to 82d3367 Compare August 20, 2026 16:50
@hacheigriega
hacheigriega merged commit 82d3367 into main Aug 20, 2026
2 checks passed
@hacheigriega
hacheigriega deleted the hy/pyth-bulk-refactor branch August 20, 2026 16:55
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.

2 participants