Skip to content

feat(storage): report aborted transactions to consumers in postgres - #716

Open
OrHayat wants to merge 5 commits into
nisshi-io:mainfrom
OrHayat:txn/pg-b-aborted-transactions
Open

feat(storage): report aborted transactions to consumers in postgres#716
OrHayat wants to merge 5 commits into
nisshi-io:mainfrom
OrHayat:txn/pg-b-aborted-transactions

Conversation

@OrHayat

@OrHayat OrHayat commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

aborted_transactions was a stub returning an empty list, so a read_committed consumer was never told which offset ranges were aborted and client libraries delivered aborted data as if committed.
The first commit implements it: find each producer's abort markers, compute each aborted range's first offset, and wire the result into the Fetch response, kept cheap by a small partial index over control-batch records.

  1. A retried TxnOffsetCommit hit the staging tables' unique constraints and failed the whole request. Kafka requires the latest staged offset to win within the transaction.
  2. An offsets-only transaction (sendOffsetsToTransaction with nothing produced) never reset the transaction state, so EndTxn silently dropped its staged offsets and leaked them into the producer's next transaction.
  3. AddOffsetsToTxn now begins the transaction the same way AddPartitionsToTxn does, which also lets the timeout sweep cover offsets-only transactions.
  4. TxnOffsetCommit validated nothing before staging: a sweep-fenced producer's stale epoch, staging into an already-finalized transaction, and a nonexistent topic or partition were all acked as success. Validation now runs before any insert and returns ProducerFenced, InvalidTxnState and UnknownTopicOrPartition respectively.
  5. Two debug views joined producer_epoch on itself, matching rows by coincidence of id sequences.

@OrHayat OrHayat changed the title Txn/pg b aborted transactions feat(storage): report aborted transactions to consumers in postgres Aug 12, 2026
@OrHayat
OrHayat force-pushed the txn/pg-b-aborted-transactions branch from 221825e to e4914ff Compare August 24, 2026 12:00
Replace the pg aborted_transactions stub with a real query: collect abort
control markers in [offset, last_stable_offset) and return the aborted
producer ranges, wired into the Fetch response so read_committed consumers
can filter aborted data instead of reading it as committed.
A retried or repeated TxnOffsetCommit for the same transaction and
consumer group violated the staging tables' unique constraints and
failed the whole request; Kafka requires the latest staged offset for a
partition to win within the transaction.
…oTxn

txn_add_offsets was a no-op, so a transaction that only commits consumer
offsets kept its txn_detail row's previous terminal status: EndTxn's
guard treated the commit as already finalized and silently dropped the
staged offsets, and the timeout sweep could never expire the
transaction.
- check the producer identity against its full epoch history, so a
  sweep-fenced zombie's stale epoch gets ProducerFenced instead of
  staging rows no finalization will ever clean up
- reject staging into a transaction that is not in BEGIN with
  InvalidTxnState: a delayed duplicate after EndTxn otherwise leaves
  rows the producer's next transaction applies as its own
- report UnknownTopicOrPartition when the staged topic or partition
  does not exist instead of acking success while staging nothing
- validation now runs before any insert, so rejected requests leave no
  partial staging state
v_txn_consumer_offset_tp and v_txn_produce_offset joined producer_epoch
on pe.producer = pe.id, matching rows by coincidence of id sequences
instead of by producer.
@OrHayat
OrHayat force-pushed the txn/pg-b-aborted-transactions branch from e4914ff to 3406086 Compare August 31, 2026 16:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant