3 slots were filling after one click.
That was the bug.
The dashboard had a Generate action, but the implementation treated that action like a request to satisfy the scheduler’s queue target. The queue wanted three articles, so one click could fill all three available slots. The system was behaving consistently with its queue logic and inconsistently with the user’s intent.
When I click Generate once, I expect one article. Not a batch. Not a queue refill disguised as a button response. One click should produce one visible unit of work.
The fix was small, but the distinction matters.
I added a limit parameter to the backfill operation. The dashboard route now passes a limit of 1, so an interactive Generate request fills a single slot. The stepper also renders one row, matching the work initiated by that click.
The scheduler keeps its existing behavior. On its automatic cadence, it still refills the queue until all three slots are occupied.
That separation is the real change. The dashboard action and the scheduler both use queue backfill logic, but they represent different intents. The dashboard responds to an explicit user action. The scheduler maintains background capacity. Sharing an implementation does not mean they should share the same operating policy.
There is a tradeoff here. Adding a parameter creates another behavior that callers must choose correctly. A default can also hide intent if every caller silently inherits it. But forcing the dashboard through the scheduler’s refill policy was worse. It made a simple action surprising and made the interface report more work than the user requested.
The clean contract is straightforward: interactive generation is bounded by the request, while scheduled generation is bounded by queue capacity.
I would do one thing differently. I would define those two contracts before wiring the dashboard route to backfill. The original mistake came from treating queue fullness as the universal goal. It was only the scheduler’s goal. The button’s goal was much narrower.
A shared function should provide the mechanism. The caller should provide the intent.
Top comments (0)