gen_stage icon indicating copy to clipboard operation
gen_stage copied to clipboard

Fix FIFO ordering for queued sync_info messages

Open acco opened this issue 5 months ago • 0 comments

Problem

Addresses #315

The GenStage.Buffer module was returning permanent events in LIFO instead of FIFO order when multiple permanent events were stored at the same wheel position.

Reproduction

alias GenStage.Buffer

# Create a buffer and store some temporary events
buffer = Buffer.new(10)
{buffer, _excess, _perms} = Buffer.store_temporary(buffer, [:temp1, :temp2], :first)

# Store multiple permanent events at the same position
{:ok, buffer} = Buffer.store_permanent_unless_empty(buffer, :perm_first)
{:ok, buffer} = Buffer.store_permanent_unless_empty(buffer, :perm_second)
{:ok, buffer} = Buffer.store_permanent_unless_empty(buffer, :perm_third)

# Take events - notice the permanent events are in wrong order
{:ok, _buffer, _remaining, temps, perms} = Buffer.take_count_or_until_permanent(buffer, 5)

IO.inspect(temps)  # [:temp1, :temp2] ✓ Correct FIFO order
IO.inspect(perms)  # [:perm_third, :perm_second, :perm_first] ❌ Wrong! Should be FIFO

Before fix: [:perm_third, :perm_second, :perm_first] (LIFO - wrong)
After fix: [:perm_first, :perm_second, :perm_third] (FIFO - correct)

Root Cause

In pop_and_increment_wheel/1, permanent events were stored using [new_perm | existing_list], but when retrieved the list wasn't reversed to restore FIFO order.

Solution

Added :lists.reverse(perms) in pop_and_increment_wheel/1 before returning permanent events, ensuring they're returned in the same order they were stored.

acco avatar Jun 30 '25 03:06 acco