Fixes #9810

/claim #9810

πŸ› Problem

The ZStream.buffer(1) method was incorrectly buffering 2 elements instead of 1, due to the asynchronous nature of the underlying queue implementation. This occurred because the queue allowed concurrent offer and take operations, leading to a race condition where 2 elements could be buffered simultaneously.

πŸ”§ Solution

Implemented a special case for buffer(1) that uses a synchronous approach:

  1. Added bufferOne method: A dedicated implementation for capacity=1 that uses Semaphore(1) to ensure only one element can be buffered at any time
  2. Created runIntoQueueElementsSynchronous: A synchronous version of queue operations that wraps all queue interactions with semaphore permits
  3. Maintained backward compatibility: All other buffer capacities (>1) continue using the existing optimized implementation

πŸ§ͺ Tests Added

Created comprehensive test suite in BufferOneSpec.scala:

  • βœ… Verifies buffer(1) only buffers exactly 1 element using TestClock
  • βœ… Compares behavior between buffer(1) and buffer(2)
  • βœ… Ensures normal flow continues working correctly

πŸ“Š Performance Impact

  • Zero impact on existing code - only buffer(1) uses the new implementation
  • Thread-safe using ZIO’s Semaphore primitive
  • Resource efficient with proper scoped forking

🎯 Key Changes

streams/shared/src/main/scala/zio/stream/ZStream.scala:

  • Added special case detection for capacity == 1
  • Implemented bufferOne method with semaphore-controlled synchronization
  • Added runIntoQueueElementsSynchronous for synchronized queue operations
  • Comprehensive English comments explaining the fix

streams-tests/shared/src/test/scala/zio/stream/BufferOneSpec.scala:

  • Complete test suite with 3 test cases
  • Uses TestClock for precise timing control
  • Validates exact buffering behavior

βœ… Validation

  • All existing tests pass
  • New tests pass (3/3)
  • Code formatted with scalafmt
  • No breaking changes
  • Follows ZIO coding conventions

🎬 Demo Video

VIDEO PR.zip

The fix ensures that ZStream.buffer(1) behaves correctly as documented, buffering exactly 1 element instead of 2, while maintaining full compatibility with existing code.

Claim

Total prize pool $250
Total paid $0
Status Pending
Submitted July 03, 2025
Last updated July 03, 2025

Contributors

JO

JoΓ£o Luccas

@jucalast

100%

Sponsors

ZI

ZIO

@ZIO

$250