Search in sources :

Example 1 with RetriesExhaustedException

use of io.pravega.common.util.RetriesExhaustedException in project pravega by pravega.

the class ScaleOperationTask method execute.

@Override
public CompletableFuture<Void> execute(final ScaleOpEvent request) {
    CompletableFuture<Void> result = new CompletableFuture<>();
    final OperationContext context = streamMetadataStore.createContext(request.getScope(), request.getStream());
    log.info("starting scale request for {}/{} segments {} to new ranges {}", request.getScope(), request.getStream(), request.getSegmentsToSeal(), request.getNewRanges());
    streamMetadataTasks.startScale(request, request.isRunOnlyIfStarted(), context, this.streamMetadataTasks.retrieveDelegationToken()).whenCompleteAsync((res, e) -> {
        if (e != null) {
            Throwable cause = Exceptions.unwrap(e);
            if (cause instanceof RetriesExhaustedException) {
                cause = cause.getCause();
            }
            log.warn("processing scale request for {}/{} segments {} failed {}", request.getScope(), request.getStream(), request.getSegmentsToSeal(), cause);
            result.completeExceptionally(cause);
        } else {
            log.info("scale request for {}/{} segments {} to new ranges {} completed successfully.", request.getScope(), request.getStream(), request.getSegmentsToSeal(), request.getNewRanges());
            result.complete(null);
        }
    }, executor);
    return result;
}
Also used : OperationContext(io.pravega.controller.store.stream.OperationContext) CompletableFuture(java.util.concurrent.CompletableFuture) RetriesExhaustedException(io.pravega.common.util.RetriesExhaustedException)

Example 2 with RetriesExhaustedException

use of io.pravega.common.util.RetriesExhaustedException in project pravega by pravega.

the class BookKeeperLog method processPendingWrites.

/**
 * Executes pending Writes to BookKeeper. This method is not thread safe and should only be invoked as part of
 * the Write Processor.
 * @return True if the no errors, false if at least one write failed.
 */
private boolean processPendingWrites() {
    long traceId = LoggerHelpers.traceEnterWithContext(log, this.traceObjectId, "processPendingWrites");
    // Clean up the write queue of all finished writes that are complete (successfully or failed for good)
    val cs = this.writes.removeFinishedWrites();
    if (cs.contains(WriteQueue.CleanupStatus.WriteFailed)) {
        // We encountered a failed write. As such, we must close immediately and not process anything else.
        // Closing will automatically cancel all pending writes.
        close();
        LoggerHelpers.traceLeave(log, this.traceObjectId, "processPendingWrites", traceId, WriteQueue.CleanupStatus.WriteFailed);
        return false;
    } else if (cs.contains(WriteQueue.CleanupStatus.QueueEmpty)) {
        // Queue is empty - nothing else to do.
        LoggerHelpers.traceLeave(log, this.traceObjectId, "processPendingWrites", traceId, WriteQueue.CleanupStatus.QueueEmpty);
        return true;
    }
    // Calculate how much estimated space there is in the current ledger.
    final long maxTotalSize = this.config.getBkLedgerMaxSize() - getWriteLedger().ledger.getLength();
    // Get the writes to execute from the queue.
    List<Write> toExecute = this.writes.getWritesToExecute(maxTotalSize);
    // appropriate, or retried).
    if (handleClosedLedgers(toExecute)) {
        // If any changes were made to the Writes in the list, re-do the search to get a more accurate list of Writes
        // to execute (since some may have changed Ledgers, more writes may not be eligible for execution).
        toExecute = this.writes.getWritesToExecute(maxTotalSize);
    }
    // Execute the writes.
    log.debug("{}: Executing {} writes.", this.traceObjectId, toExecute.size());
    for (int i = 0; i < toExecute.size(); i++) {
        Write w = toExecute.get(i);
        try {
            // Record the beginning of a new attempt.
            int attemptCount = w.beginAttempt();
            if (attemptCount > this.config.getMaxWriteAttempts()) {
                // Retried too many times.
                throw new RetriesExhaustedException(w.getFailureCause());
            }
            // Invoke the BookKeeper write.
            w.getWriteLedger().ledger.asyncAddEntry(w.data.array(), w.data.arrayOffset(), w.data.getLength(), this::addCallback, w);
        } catch (Throwable ex) {
            // Synchronous failure (or RetriesExhausted). Fail current write.
            boolean isFinal = !isRetryable(ex);
            w.fail(ex, isFinal);
            // And fail all remaining writes as well.
            for (int j = i + 1; j < toExecute.size(); j++) {
                toExecute.get(j).fail(new DurableDataLogException("Previous write failed.", ex), isFinal);
            }
            LoggerHelpers.traceLeave(log, this.traceObjectId, "processPendingWrites", traceId, i);
            return false;
        }
    }
    // After every run where we did write, check if need to trigger a rollover.
    this.rolloverProcessor.runAsync();
    LoggerHelpers.traceLeave(log, this.traceObjectId, "processPendingWrites", traceId, toExecute.size());
    return true;
}
Also used : lombok.val(lombok.val) DurableDataLogException(io.pravega.segmentstore.storage.DurableDataLogException) RetriesExhaustedException(io.pravega.common.util.RetriesExhaustedException)

Example 3 with RetriesExhaustedException

use of io.pravega.common.util.RetriesExhaustedException in project pravega by pravega.

the class ControllerImplTest method testKeepAlive.

@Test
public void testKeepAlive() throws IOException, ExecutionException, InterruptedException {
    // Verify that keep-alive timeout less than permissible by the server results in a failure.
    NettyChannelBuilder builder = NettyChannelBuilder.forAddress("localhost", serverPort).keepAliveTime(10, TimeUnit.SECONDS);
    if (testSecure) {
        builder = builder.sslContext(GrpcSslContexts.forClient().trustManager(new File("../config/cert.pem")).build());
    } else {
        builder = builder.usePlaintext(true);
    }
    final ControllerImpl controller = new ControllerImpl(builder, ControllerImplConfig.builder().clientConfig(ClientConfig.builder().trustStore("../config/cert.pem").controllerURI(URI.create((testSecure ? "tls://" : "tcp://") + "localhost:" + serverPort)).build()).retryAttempts(1).build(), this.executor);
    CompletableFuture<Boolean> createStreamStatus = controller.createStream(StreamConfiguration.builder().streamName("streamdelayed").scope("scope1").scalingPolicy(ScalingPolicy.fixed(1)).build());
    AssertExtensions.assertThrows("Should throw RetriesExhaustedException", createStreamStatus, throwable -> throwable instanceof RetriesExhaustedException);
    // Verify that the same RPC with permissible keepalive time succeeds.
    int serverPort2 = TestUtils.getAvailableListenPort();
    NettyServerBuilder testServerBuilder = NettyServerBuilder.forPort(serverPort2).addService(testServerImpl).permitKeepAliveTime(5, TimeUnit.SECONDS);
    if (testSecure) {
        testServerBuilder = testServerBuilder.useTransportSecurity(new File("../config/cert.pem"), new File("../config/key.pem"));
    }
    Server testServer = testServerBuilder.build().start();
    builder = NettyChannelBuilder.forAddress("localhost", serverPort2).keepAliveTime(10, TimeUnit.SECONDS);
    if (testSecure) {
        builder = builder.sslContext(GrpcSslContexts.forClient().trustManager(new File("../config/cert.pem")).build());
    } else {
        builder = builder.usePlaintext(true);
    }
    final ControllerImpl controller1 = new ControllerImpl(builder, ControllerImplConfig.builder().clientConfig(ClientConfig.builder().trustStore("../config/cert.pem").controllerURI(URI.create((testSecure ? "tls://" : "tcp://") + "localhost:" + serverPort)).build()).retryAttempts(1).build(), this.executor);
    createStreamStatus = controller1.createStream(StreamConfiguration.builder().streamName("streamdelayed").scope("scope1").scalingPolicy(ScalingPolicy.fixed(1)).build());
    assertTrue(createStreamStatus.get());
    testServer.shutdownNow();
}
Also used : NettyServerBuilder(io.grpc.netty.NettyServerBuilder) RetriesExhaustedException(io.pravega.common.util.RetriesExhaustedException) Server(io.grpc.Server) NettyChannelBuilder(io.grpc.netty.NettyChannelBuilder) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) File(java.io.File) Test(org.junit.Test)

Example 4 with RetriesExhaustedException

use of io.pravega.common.util.RetriesExhaustedException in project pravega by pravega.

the class SequentialAsyncProcessorTests method testRunAsyncErrors.

/**
 * Tests the runAsync() method with execution errors.
 */
@Test(timeout = TIMEOUT_MILLIS)
public void testRunAsyncErrors() throws Exception {
    final int expectedCount = 2;
    val count = new AtomicInteger();
    val finished = new CompletableFuture<Void>();
    val retry = Retry.withExpBackoff(1, 2, expectedCount).retryWhen(t -> {
        if (count.get() >= expectedCount) {
            finished.complete(null);
        }
        return Exceptions.unwrap(t) instanceof IntentionalException;
    }).throwingOn(Exception.class);
    val error = new CompletableFuture<Throwable>();
    val p = new SequentialAsyncProcessor(() -> {
        count.incrementAndGet();
        throw new IntentionalException();
    }, retry, error::complete, executorService());
    // Invoke it once.
    p.runAsync();
    finished.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
    val finalException = Exceptions.unwrap(error.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS));
    Assert.assertEquals("Unexpected number of final invocations.", expectedCount, count.get());
    Assert.assertTrue("Unexpected final error callback.", finalException instanceof RetriesExhaustedException && Exceptions.unwrap(finalException.getCause()) instanceof IntentionalException);
}
Also used : lombok.val(lombok.val) Retry(io.pravega.common.util.Retry) Semaphore(java.util.concurrent.Semaphore) Exceptions(io.pravega.common.Exceptions) IntentionalException(io.pravega.test.common.IntentionalException) lombok.val(lombok.val) CompletableFuture(java.util.concurrent.CompletableFuture) Test(org.junit.Test) AtomicReference(java.util.concurrent.atomic.AtomicReference) RetriesExhaustedException(io.pravega.common.util.RetriesExhaustedException) TimeUnit(java.util.concurrent.TimeUnit) Rule(org.junit.Rule) ThreadPooledTestSuite(io.pravega.test.common.ThreadPooledTestSuite) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Timeout(org.junit.rules.Timeout) Assert(org.junit.Assert) CompletableFuture(java.util.concurrent.CompletableFuture) RetriesExhaustedException(io.pravega.common.util.RetriesExhaustedException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) IntentionalException(io.pravega.test.common.IntentionalException) Test(org.junit.Test)

Example 5 with RetriesExhaustedException

use of io.pravega.common.util.RetriesExhaustedException in project pravega by pravega.

the class BookKeeperLogTests method testAutoCloseOnBookieFailure.

/**
 * Tests the ability to auto-close upon a permanent write failure caused by BookKeeper.
 *
 * @throws Exception If one got thrown.
 */
@Test
public void testAutoCloseOnBookieFailure() throws Exception {
    try (DurableDataLog log = createDurableDataLog()) {
        log.initialize(TIMEOUT);
        try {
            // Suspend a bookie (this will trigger write errors).
            stopFirstBookie();
            // First write should fail. Either a DataLogNotAvailableException (insufficient bookies) or
            // WriteFailureException (general unable to write) should be thrown.
            AssertExtensions.assertThrows("First write did not fail with the appropriate exception.", () -> log.append(new ByteArraySegment(getWriteData()), TIMEOUT), ex -> ex instanceof RetriesExhaustedException && (ex.getCause() instanceof DataLogNotAvailableException || isLedgerClosedException(ex.getCause())) || ex instanceof ObjectClosedException || ex instanceof CancellationException);
            // Subsequent writes should be rejected since the BookKeeperLog is now closed.
            AssertExtensions.assertThrows("Second write did not fail with the appropriate exception.", () -> log.append(new ByteArraySegment(getWriteData()), TIMEOUT), ex -> ex instanceof ObjectClosedException || ex instanceof CancellationException);
        } finally {
            // Don't forget to resume the bookie.
            restartFirstBookie();
        }
    }
}
Also used : DurableDataLog(io.pravega.segmentstore.storage.DurableDataLog) DataLogNotAvailableException(io.pravega.segmentstore.storage.DataLogNotAvailableException) ByteArraySegment(io.pravega.common.util.ByteArraySegment) RetriesExhaustedException(io.pravega.common.util.RetriesExhaustedException) CancellationException(java.util.concurrent.CancellationException) ObjectClosedException(io.pravega.common.ObjectClosedException) Test(org.junit.Test)

Aggregations

RetriesExhaustedException (io.pravega.common.util.RetriesExhaustedException)9 Test (org.junit.Test)6 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)4 lombok.val (lombok.val)4 CompletableFuture (java.util.concurrent.CompletableFuture)3 ByteArraySegment (io.pravega.common.util.ByteArraySegment)2 RetryableException (io.pravega.controller.retryable.RetryableException)2 DurableDataLog (io.pravega.segmentstore.storage.DurableDataLog)2 DurableDataLogException (io.pravega.segmentstore.storage.DurableDataLogException)2 CancellationException (java.util.concurrent.CancellationException)2 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)2 Server (io.grpc.Server)1 NettyChannelBuilder (io.grpc.netty.NettyChannelBuilder)1 NettyServerBuilder (io.grpc.netty.NettyServerBuilder)1 Exceptions (io.pravega.common.Exceptions)1 ObjectClosedException (io.pravega.common.ObjectClosedException)1 Retry (io.pravega.common.util.Retry)1 OperationContext (io.pravega.controller.store.stream.OperationContext)1 DataLogNotAvailableException (io.pravega.segmentstore.storage.DataLogNotAvailableException)1 DataLogWriterNotPrimaryException (io.pravega.segmentstore.storage.DataLogWriterNotPrimaryException)1