AniUI Academy

A buffer that batches then flushes

hardData Structures+350 XPPractice

Firing a request for every click, keystroke or log line floods the network. The standard fix is a buffer with two triggers: flush as soon as enough items pile up, and flush anyway once the oldest item has waited long enough.

Implement a BatchBuffer class. new BatchBuffer(onFlush, options) takes a callback and an options object { size, waitMs }, defaulting to size 10 and waitMs 100. add(item) appends an item to the pending batch and returns the number of items pending afterwards. If adding brings the pending count up to size, flush immediately and synchronously, before add returns — so add returns 0 in that case. Otherwise, if this item is the first of a new batch, start a timer for waitMs milliseconds; adds after that must not restart the timer, so the batch is sent waitMs after its first item rather than after its last. flushNow() sends whatever is pending straight away and returns how many items it sent; when nothing is pending it does not call the callback and returns 0. pending() returns how many items are waiting.

Flushing means calling onFlush(items) once with a plain array of the pending items in the order they were added, then clearing the pending list and cancelling any timer. The callback is never called with an empty array.

Examples

const sent = [];
const b = new BatchBuffer((items) => sent.push(items), { size: 3, waitMs: 1000 });
b.add(1); b.add(2);
b.add(3);    // triggers a sync flush
sent;        // [[1, 2, 3]]
b.pending(); // 0

Reaching the batch size flushes inside the add call.

const sent = [];
const b = new BatchBuffer((items) => sent.push(items), { size: 10, waitMs: 20 });
b.add("a"); b.add("b");
// 20ms later: sent === [["a", "b"]]

An unfilled batch flushes waitMs after its first item.

What it has to do

  • Reaching size items flushes synchronously inside the add call.
  • A batch that never fills is flushed waitMs after its first item.
  • Later adds do not restart the timer.
  • flushNow() returns the number sent and does nothing when nothing is pending.
  • onFlush receives the items in the order they were added, and is never called with an empty array.

Notes

  • The 'wait from first item' rule is what gives latency guarantees. If each add restarted the timer, a steady stream of events would hold a batch open forever.
  • Only start a timer when there is not one already. That single conditional is the whole difference between first-item-wait and last-item-wait semantics.
  • Always clear the timer inside flushNow(), otherwise a flush-by-size will still fire a redundant timer flush later with nothing in the buffer.

Stuck? The javascript course covers everything this challenge needs.

Try it yourself
Loading playground...
5 tests · +350 XP

Discussion

Sign in to post
Sign in to join the conversation.Sign in

No comments yet. Be the first to say something.