Repository navigation
|
Hi! Is there a recommended way to implement throttling for WebSocket listeners? This is an important feature for handling high-frequency WS data. Should throttling support multiple modes, such as:
This would allow us to skip intermediate updates for state-based data while ensuring that no messages are lost for event-based data. Is this model supported, and what would be the recommended way to implement it? |
Replies: 4 comments 5 replies
|
Not built in, as of It's a small wrapper round import type { ListenerInstance, ExtractListenerResponseType } from "@hyper-fetch/sockets";
export const listenEvery = <L extends ListenerInstance>(
listener: L,
ms: number,
onFlush: (messages: ExtractListenerResponseType<L>[]) => void,
) => {
let buffer: ExtractListenerResponseType<L>[] = [];
let timer: ReturnType<typeof setTimeout> | undefined;
const stop = listener.listen(({ data }) => {
buffer.push(data);
timer ??= setTimeout(() => {
const messages = buffer;
buffer = [];
timer = undefined;
onFlush(messages);
}, ms);
});
return () => {
clearTimeout(timer);
stop();
};
};
// batching - every message, grouped per 100ms
listenEvery(onTrade, 100, (trades) => handleTrades(trades));
// latest/ sampling - just the last one per 100ms
listenEvery(onPrice, 100, (prices) => setPrice(prices.at(-1)!));Its a trailing throttle, so the first message waits up to |
|
@prc5, hi, do you have any suggestions about it? |
|
I will solve this directly in the listener 👍🏻 |
|
Done ✅ #147 It's a // sampling - first message immediately, then the newest one per interval
const onPrice = socket.createListener<Price>()({
topic: "prices",
delivery: { strategy: "latest", interval: 16 },
});
// batching - everything from the window as one array, nothing dropped
const onTrade = socket.createListener<Trade>()({
topic: "trades",
delivery: { strategy: "batch", interval: 100, maxSize: 500 },
});
onTrade.listen(({ data }) => {}); // data: Trade[] - inferred
// anything else - custom strategy
delivery: createDeliveryStrategy<Tick, Summary>(({ deliver }) => ({ push, dispose }))
// change at runtime, returns a clone like setOptions
onPrice.setDelivery({ strategy: "latest", interval: 1000 });It runs inside the listener, right before your callback, so Guides for sockets and React are in the PR too. Ships with the next sockets/react release, would love to hear how it works for your streams. |
@present-g @NotAFlightRisk
Done ✅ #147
It's a
deliveryoption on the listener, almost exactly as you sketched it (top-level instead of insideoptions, sinceoptionsis adapter-specific):