Bill Bejeck created KAFKA-21253:
-----------------------------------

             Summary: Failed transaction abort in 
RecordCollectorImpl.closeDirty() skips clearing changelog offsets, so a revived 
task can checkpoint a stale offset
                 Key: KAFKA-21253
                 URL: https://issues.apache.org/jira/browse/KAFKA-21253
             Project: Kafka
          Issue Type: Bug
          Components: streams
    Affects Versions: 4.2.2, 4.3.1, 4.1.2, 4.0.0, 3.9.2, 3.8.1, 4.4.0
            Reporter: Bill Bejeck
            Assignee: Bill Bejeck
             Fix For: 4.5.0, 4.4.1


With exactly-once enabled, a commitTransaction() call that times out 
(max.block.ms) leaves the producer with a pending commit that was never 
acknowledged. Any later abortTransaction() on that producer throws 
IllegalStateException: "Cannot attempt operation abortTransaction because the 
previous call to commitTransaction timed out and must be retried".

RecordCollectorImpl.closeDirty() calls streamsProducer.abortTransaction() 
before close(). StreamsProducer.abortTransaction() doesn't catch 
IllegalStateException, so the exception escapes closeDirty(). As a result, 
close() is skipped and the collector's offsets map is not cleared. 
StreamTask.close() swallows the exception in 
TaskManager.executeAndMaybeSwallow(), which logs only at DEBUG and doesn't 
include the exception.

A task revived after the dirty close reuses the same record collector. It 
restores its wiped store from the start of the changelog, while 
recordCollector.offsets() still holds the last changelog offset written before 
the failure. If the task is closed clean before restoration finishes, that 
stale offset is written to the checkpoint. On the next initialization, 
restoration starts from that checkpoint and skips the missing records, which 
leaves the store empty or incomplete.

Trigger path:
1. A commit TimeoutException raises TaskCorruptedException.
2. TaskManager.handleCorruption() commits the open transaction before closing 
the corrupted tasks.
3. If that EndTxn times out and the commit contains no task offsets, the 
timeout is logged but not rethrown.
4. closeDirtyAndRevive() then calls closeDirty() on a producer that still has 
the pending commit.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to