Search in sources :

Example 1 with Retryer

use of com.github.rholder.retry.Retryer in project graylog2-server by Graylog2.

the class LocalKafkaMessageQueueWriter method write.

@Override
public void write(List<RawMessageEvent> entries) throws MessageQueueException {
    final AtomicLong msgBytes = new AtomicLong(0);
    final List<Journal.Entry> journalEntries = entries.stream().filter(Objects::nonNull).map(e -> new Journal.Entry(e.getMessageIdBytes(), e.getEncodedRawMessage())).peek(e -> msgBytes.addAndGet(e.getMessageBytes().length)).collect(Collectors.toList());
    try {
        writeToJournal(journalEntries);
    } catch (Exception e) {
        LOG.error("Unable to write to journal - retrying", e);
        // Use retryer with exponential back-off to avoid spamming the logs.
        try {
            writeRetryer.call(() -> {
                writeToJournal(journalEntries);
                return null;
            });
        } catch (ExecutionException | RetryException ex) {
            throw new MessageQueueException("Retryer exception", ex);
        }
    }
    metrics.writtenMessages().mark(journalEntries.size());
    metrics.writtenBytes().mark(msgBytes.get());
}
Also used : WaitStrategies(com.github.rholder.retry.WaitStrategies) Logger(org.slf4j.Logger) RawMessageEvent(org.graylog2.shared.buffers.RawMessageEvent) Retryer(com.github.rholder.retry.Retryer) RetryerBuilder(com.github.rholder.retry.RetryerBuilder) Semaphore(java.util.concurrent.Semaphore) RetryException(com.github.rholder.retry.RetryException) LoggerFactory(org.slf4j.LoggerFactory) Journal(org.graylog2.shared.journal.Journal) MessageQueueException(org.graylog2.shared.messageq.MessageQueueException) Singleton(javax.inject.Singleton) Collectors(java.util.stream.Collectors) LocalKafkaJournal(org.graylog2.shared.journal.LocalKafkaJournal) Inject(javax.inject.Inject) Objects(java.util.Objects) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) AtomicLong(java.util.concurrent.atomic.AtomicLong) List(java.util.List) MessageQueueWriter(org.graylog2.shared.messageq.MessageQueueWriter) StopStrategies(com.github.rholder.retry.StopStrategies) AbstractIdleService(com.google.common.util.concurrent.AbstractIdleService) Named(javax.inject.Named) AtomicLong(java.util.concurrent.atomic.AtomicLong) MessageQueueException(org.graylog2.shared.messageq.MessageQueueException) Journal(org.graylog2.shared.journal.Journal) LocalKafkaJournal(org.graylog2.shared.journal.LocalKafkaJournal) RetryException(com.github.rholder.retry.RetryException) MessageQueueException(org.graylog2.shared.messageq.MessageQueueException) ExecutionException(java.util.concurrent.ExecutionException)

Example 2 with Retryer

use of com.github.rholder.retry.Retryer in project gerrit by GerritCodeReview.

the class RepoSequenceTest method idCanBeRetrievedFromOtherThreadWhileWaitingToRetry.

@Test
public void idCanBeRetrievedFromOtherThreadWhileWaitingToRetry() throws Exception {
    // Seed existing ref value.
    writeBlob("id", "1");
    // Let the first update of the sequence fail with LOCK_FAILURE, so that the update is retried.
    CountDownLatch lockFailure = new CountDownLatch(1);
    CountDownLatch parallelSuccessfulSequenceGeneration = new CountDownLatch(1);
    AtomicBoolean doneBgUpdate = new AtomicBoolean(false);
    Runnable bgUpdate = () -> {
        if (!doneBgUpdate.getAndSet(true)) {
            writeBlob("id", "1234");
        }
    };
    BlockStrategy blockStrategy = t -> {
        // Keep blocking until we verified that another thread can retrieve a sequence number
        // while we are blocking here.
        lockFailure.countDown();
        parallelSuccessfulSequenceGeneration.await();
    };
    // Use batch size = 1 to make each call go to NoteDb.
    RepoSequence s = newSequence("id", 1, 1, bgUpdate, RepoSequence.retryerBuilder().withBlockStrategy(blockStrategy).build());
    assertThat(doneBgUpdate.get()).isFalse();
    // Start a thread to get a sequence number. This thread needs to update the sequence in NoteDb,
    // but due to the background update (see bgUpdate) the first attempt to update NoteDb fails
    // with LOCK_FAILURE. RepoSequence uses a retryer to retry the NoteDb update on LOCK_FAILURE,
    // but our block strategy ensures that this retry only happens after isBlocking was set to
    // false.
    Future<?> future = Executors.newFixedThreadPool(1).submit(() -> {
        // The background update sets the next available sequence number to 1234. Then the
        // test thread retrieves one sequence number, so that the next available sequence
        // number for this thread is 1235.
        expect.that(s.next()).isEqualTo(1235);
    });
    // Wait until the LOCK_FAILURE has happened and the block strategy was entered.
    lockFailure.await();
    // Verify that the background update was done now.
    assertThat(doneBgUpdate.get()).isTrue();
    // Verify that we can retrieve a sequence number while the other thread is blocked. If the
    // s.next() call hangs it means that the RepoSequence.counterLock was not released before the
    // background thread started to block for retry. In this case the test would time out.
    assertThat(s.next()).isEqualTo(1234);
    // Stop blocking the retry of the background thread (and verify that it was still blocked).
    parallelSuccessfulSequenceGeneration.countDown();
    // Wait until the background thread is done.
    future.get();
    // Two successful acquire calls (because batch size == 1).
    assertThat(s.acquireCount).isEqualTo(2);
}
Also used : ObjectInserter(org.eclipse.jgit.lib.ObjectInserter) OBJ_BLOB(org.eclipse.jgit.lib.Constants.OBJ_BLOB) IncorrectObjectTypeException(org.eclipse.jgit.errors.IncorrectObjectTypeException) Retryer(com.github.rholder.retry.Retryer) RetryerBuilder(com.github.rholder.retry.RetryerBuilder) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) BlockStrategy(com.github.rholder.retry.BlockStrategy) RevWalk(org.eclipse.jgit.revwalk.RevWalk) Future(java.util.concurrent.Future) ImmutableList(com.google.common.collect.ImmutableList) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Runnables(com.google.common.util.concurrent.Runnables) RefNames(com.google.gerrit.entities.RefNames) Before(org.junit.Before) Expect(com.google.common.truth.Expect) TestRepository(org.eclipse.jgit.junit.TestRepository) Truth.assertWithMessage(com.google.common.truth.Truth.assertWithMessage) UTF_8(java.nio.charset.StandardCharsets.UTF_8) StorageException(com.google.gerrit.exceptions.StorageException) RefUpdate(org.eclipse.jgit.lib.RefUpdate) IOException(java.io.IOException) Test(org.junit.Test) Truth.assertThat(com.google.common.truth.Truth.assertThat) Executors(java.util.concurrent.Executors) ObjectId(org.eclipse.jgit.lib.ObjectId) CountDownLatch(java.util.concurrent.CountDownLatch) Rule(org.junit.Rule) StopStrategies(com.github.rholder.retry.StopStrategies) Project(com.google.gerrit.entities.Project) InMemoryRepositoryManager(com.google.gerrit.testing.InMemoryRepositoryManager) GerritJUnit.assertThrows(com.google.gerrit.testing.GerritJUnit.assertThrows) GitReferenceUpdated(com.google.gerrit.server.extensions.events.GitReferenceUpdated) Repository(org.eclipse.jgit.lib.Repository) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) CountDownLatch(java.util.concurrent.CountDownLatch) BlockStrategy(com.github.rholder.retry.BlockStrategy) Test(org.junit.Test)

Aggregations

Retryer (com.github.rholder.retry.Retryer)2 RetryerBuilder (com.github.rholder.retry.RetryerBuilder)2 StopStrategies (com.github.rholder.retry.StopStrategies)2 BlockStrategy (com.github.rholder.retry.BlockStrategy)1 RetryException (com.github.rholder.retry.RetryException)1 WaitStrategies (com.github.rholder.retry.WaitStrategies)1 ImmutableList (com.google.common.collect.ImmutableList)1 Expect (com.google.common.truth.Expect)1 Truth.assertThat (com.google.common.truth.Truth.assertThat)1 Truth.assertWithMessage (com.google.common.truth.Truth.assertWithMessage)1 AbstractIdleService (com.google.common.util.concurrent.AbstractIdleService)1 Runnables (com.google.common.util.concurrent.Runnables)1 Project (com.google.gerrit.entities.Project)1 RefNames (com.google.gerrit.entities.RefNames)1 StorageException (com.google.gerrit.exceptions.StorageException)1 GitReferenceUpdated (com.google.gerrit.server.extensions.events.GitReferenceUpdated)1 GerritJUnit.assertThrows (com.google.gerrit.testing.GerritJUnit.assertThrows)1 InMemoryRepositoryManager (com.google.gerrit.testing.InMemoryRepositoryManager)1 IOException (java.io.IOException)1 UTF_8 (java.nio.charset.StandardCharsets.UTF_8)1