public boolean hasLateTransaction(long currentTimeMs) {
        long lastTimestamp = oldestTxnLastTimestamp;
        return lastTimestamp > 0 && (currentTimeMs - lastTimestamp) > maxTransactionTimeoutMs + ProducerStateManager.LATE_TRANSACTION_BUFFER_MS;
    }
@Test
    public void testHasLateTransaction() {
        long producerId1 = 39L;
        short epoch1 = 2;
        long producerId2 = 57L;
        short epoch2 = 9;

        // Start two transactions with a delay between them
        appendClientEntry(stateManager, producerId1, epoch1, defaultSequence, 100, true);
        assertFalse(stateManager.hasLateTransaction(time.milliseconds()));

        time.sleep(500);
        appendClientEntry(stateManager, producerId2, epoch2, defaultSequence, 150, true);
        assertFalse(stateManager.hasLateTransaction(time.milliseconds()));

        // Only the first transaction is late
        time.sleep(lateTransactionTimeoutMs - 500 + 1);
        assertTrue(stateManager.hasLateTransaction(time.milliseconds()));

        // Both transactions are now late
        time.sleep(500);
        assertTrue(stateManager.hasLateTransaction(time.milliseconds()));

        // Finish the first transaction
        appendEndTxnMarker(stateManager, producerId1, epoch1, ControlRecordType.COMMIT, 200);
        assertTrue(stateManager.hasLateTransaction(time.milliseconds()));

        // Now finish the second transaction
        appendEndTxnMarker(stateManager, producerId2, epoch2, ControlRecordType.COMMIT, 250);
        assertFalse(stateManager.hasLateTransaction(time.milliseconds()));
    }