zf18634362654 opened a new issue, #7742:
URL: https://github.com/apache/hop/issues/7742

   ### Apache Hop version?
   
   2.18.1
   
   ### Java version?
   
   21
   
   ### Operating system
   
   Windows
   
   ### What happened?
   
   In the BlockingBatchingRowSet.setDone() method, the call to super.setDone() 
is placed before the final batch of data is enqueued. Under multi‑threaded 
execution, this can cause a race condition: a downstream consumer may see the 
done flag as true before the last data items are actually pushed into the 
getArray queue, leading to premature termination and data loss.
   
   We discovered this issue during our stress testing – when the upstream 
transform finishes and the downstream hasn't consumed all rows yet, the 
downstream block might incorrectly think the stream is already complete and 
stop reading.
   
   Steps to Reproduce
   Set up a pipeline that uses BlockingBatchingRowSet with a high level of 
concurrency (multiple upstream producers and downstream consumers).
   
   Let the upstream producer finish exactly while the downstream consumer is 
still processing the last few batches.
   
   In some runs, the downstream consumer will stop early and the final rows are 
never processed.
   
   Expected Behavior
   All rows should be safely delivered to downstream consumers before the 
BlockingBatchingRowSet is marked as done. The done flag should only be set 
after the last batch has been enqueued.
   
   Actual Behavior
   The done flag is set immediately when super.setDone() is called, even if the 
final buffer hasn't been offered to the queue. This can cause downstream 
consumers to exit early.
   
   Proposed Fix
   Change the order of operations inside setDone(): first enqueue the final 
batch (if any), then clear the putArray, and only after that call 
super.setDone().
   
   Current code:
   
   text
   public void setDone() {
       super.setDone();
       if (putIndex > 0 && putIndex < size && inputBuffer != null) {
           inputBuffer[putIndex] = null; // signal the end of buffer
           for (int i = putIndex + 1; i < size; i++) {
               inputBuffer[i] = null;
           }
           getArray.offer(inputBuffer);
       }
       putArray.clear();
   }
   Suggested fix (ensure data is enqueued before marking done):
   
   text
   public void setDone() {
       // 1. Enqueue the last batch first
       if (putIndex > 0 && putIndex < size && inputBuffer != null) {
           inputBuffer[putIndex] = null; // signal the end of buffer
           for (int i = putIndex + 1; i < size; i++) {
               inputBuffer[i] = null;
           }
           getArray.offer(inputBuffer);
       }
       putArray.clear();
       // 2. Mark as done only after the last batch is available to consumers
       super.setDone();
   }
   Additional Note
   We would like to thank the Apache Hop community for this great tool. We have 
many ETL ideas that we’ve derived from our experience with other industrial ETL 
tools (e.g., those used in applied materials), and we would be happy to share 
our thoughts and collaborate further. Feel free to reach out if you’d like to 
discuss more.
   
   Looking forward to your feedback!
   
   
   
   ### Issue Priority
   
   Priority: 0
   
   ### Issue Component
   
   Component: Transforms


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to