com.pushtechnology.diffusion.client.features.RecoverableUpdateStream Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2023 DiffusionData Ltd., All Rights Reserved.
*
* Use is subject to licence terms.
*
* NOTICE: All information contained herein is, and remains the
* property of DiffusionData. The intellectual and technical
* concepts contained herein are proprietary to DiffusionData and
* may be covered by U.S. and Foreign Patents, patents in process, and
* are protected by trade secret or copyright law.
*******************************************************************************/
package com.pushtechnology.diffusion.client.features;
import java.util.concurrent.CompletableFuture;
import com.pushtechnology.diffusion.client.session.retry.RetryStrategy;
/**
* An extension to {@link UpdateStream} that includes recovery functionality.
*
*
* A recoverable update stream wraps an {@link UpdateStream}, tracking topic
* updates and associated {@link CompletableFuture}s.
*
* In the event that a {@link RecoverableUpdateStream} returns a {@link CompletableFuture}
* that completes exceptionally, calling {@link #isRecoverable()}
* returns {@code true} recovery is possible.
*
* Call {@link #recover()} to re-establish the update stream and re-play
* incomplete topic updates before resuming.
*
*
* Construct a RecoverableUpdateStream using
* {@link UpdateStream.Builder#build(String, Class, RetryStrategy)}
*
*
* Example feature use
* This example demonstrates use of a RecoverableUpdateStream to update topic
* my/topic
with 1000 unique values, after which it checks for
* failure in any of them. If any topic updates complete exceptionally and the
* exception is recoverable, the code recovers - reestablishing an UpdateStream
* and delivering the failed topic updates.
*
*
*
* final TopicSpecification topicSpec =
* Diffusion.newTopicSpecification(TopicType.STRING);
*
* final RecoverableUpdateStream<String> updateStream =
* session.feature(TopicUpdate.class)
* .newUpdateStreamBuilder()
* .specification(topicSpec)
* .build("my/topic",
* String.class,
* new RetryStrategy(1_000, 10));
*
* final CompletableFuture[] cfs = IntStream
* .range(0, 1000)
* .mapToObj(i -> updateStream.set("Value of " + i))
* .toArray(CompletableFuture[]::new);
*
* try {
* allOf(cfs).get();
* }
* catch(CancellationException | ExecutionException | InterruptedException ex ) {
* if (updateStream.isRecoverable()) {
* updateStream.recover();
* }
* else {
* LOG.error("Cannot recover", ex);
* }
* }
*
*
*
* @param type of the value
* @author DiffusionData Limited
* @since 6.10
*/
public interface RecoverableUpdateStream extends UpdateStream {
/**
* Check if recovery is possible following an exceptionally completed future returned from
* {@link RecoverableUpdateStream}.
* Must be used prior to calling {@link #recover()}.
*
* @return true if recovery is possible.
*/
boolean isRecoverable();
/**
* Reestablish the inner recovery stream. Deliver pending topic updates.
*
* If recoverable exceptions occur during recovery then pause and retry,
* where the pause duration and the maximum number of retries is governed by
* the {@link RetryStrategy} supplied to builder function
* {@link UpdateStream.Builder#build(String, Class, RetryStrategy)}.
*
* If non-recoverable errors occur during recovery then recovery is aborted.
*
* If recovery fails for any reason then further recovery attempts will fail.
*
* @throws UpdateStreamRetryLimitException if recovery is not possible with
* the limits of the retry strategy.
*/
void recover() throws UpdateStreamRetryLimitException;
}