Ritika Reddy created KAFKA-21181:
------------------------------------

             Summary: Transaction coordinator could return INVALID_TXN_STATE 
from stale cache after losing __transaction_state leadership
                 Key: KAFKA-21181
                 URL: https://issues.apache.org/jira/browse/KAFKA-21181
             Project: Kafka
          Issue Type: Bug
    Affects Versions: 4.3.0, 4.2.0
            Reporter: Ritika Reddy
            Assignee: Ritika Reddy
             Fix For: 4.3.0, 4.2.0


When a broker loses leadership of a __transaction_state partition, its 
TransactionStateManager keeps the partition's cache entry until 
TransactionCoordinator.onResignation runs. In 
BrokerMetadataPublisher.onMetadataUpdate, that happens after 
replicaManager.applyDelta and after the group coordinator update. So there's a 
window in which the broker is already a follower for the partition but still 
answers coordinator requests from its old cache.

TransactionStateManager.getAndMaybeAddTransactionState (trunk lines 400-421) 
only checks loadingPartitions and transactionMetadataCache; it never checks 
that the broker still leads the partition. Answers that require a log write are 
safe, because the acks=-1 append fails with NOT_LEADER_OR_FOLLOWER, which is 
mapped to NOT_COORDINATOR. Answers decided purely from the cache are not.

With TV2 this surfaces as a fatal error for the producer:
1. Transaction N commits on coordinator A. The cache on A holds COMPLETE_COMMIT 
at epoch E, and the client now has epoch E.
2. Leadership of the __transaction_state partition moves to broker B. B loads 
the partition, and the partition leaders' implicit AddPartitionsToTxn for 
transaction N+1 go to B, which moves the transaction to ONGOING.
3. The client hasn't had any reason to rediscover the coordinator: under TV2 
its first coordinator request in the transaction is EndTxn. So it sends 
EndTxn(COMMIT, E) to A.
4. A is already a follower but hasn't resigned yet. It answers from the cache: 
COMPLETE_COMMIT + COMMIT at the current epoch is not a retry, so it returns 
INVALID_TXN_STATE without writing to the log:
TransactionalId: <id>'s state is COMPLETE_COMMIT, but received transaction 
marker result to send: COMMIT
5. The producer treats INVALID_TXN_STATE as fatal. The transaction on B stays 
ONGOING until it times out.

The correct response is NOT_COORDINATOR, which would make the client rediscover 
B and commit. We've seen gaps of several seconds between the broker becoming 
follower and resigning, and in one case ~37 s, with no broker pause involved.

Other cache-only answers are exposed the same way, for example PRODUCER_FENCED 
/ INVALID_PRODUCER_ID_MAPPING, the verify-only AddPartitionsToTxn path, and the 
"partitions already added" shortcut.



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

Reply via email to