class TransactionIdTracker {

    public void awaitUpToDate( long oldestAcceptableTxId, Duration timeout ) throws TransactionFailureException
    {
        if ( oldestAcceptableTxId <= BASE_TX_ID )
        {
            return;
        }

        if ( !databaseAvailabilityGuard.isAvailable() )
        {
            throw new TransactionFailureException( Status.General.DatabaseUnavailable, "Database unavailable" );
        }

        try
        {
            // await for the last closed transaction id to to have at least the expected value
            // it has to be "last closed" and not "last committed" becase all transactions before the expected one should also be committed
            transactionIdStore().awaitClosedTransactionId( oldestAcceptableTxId, timeout.toMillis() );
        }
        catch ( InterruptedException | TimeoutException e )
        {
            if ( e instanceof InterruptedException )
            {
                Thread.currentThread().interrupt();
            }

            throw new TransactionFailureException( Status.Transaction.InstanceStateChanged, e,
                    "Database not up to the requested version: %d. Latest database version is %d", oldestAcceptableTxId,
                    transactionIdStore().getLastClosedTransactionId() );
        }
    }

    public  TransactionIdTracker( Supplier<TransactionIdStore> transactionIdStoreSupplier, AvailabilityGuard databaseAvailabilityGuard );

}