Restart(Source|Flow|Sink): Configurable stream restart deadline (#29591)
This commit is contained in:
parent
4cc3c58a08
commit
a4acf23d05
22 changed files with 727 additions and 347 deletions
|
|
@ -6,22 +6,31 @@ Wrap the given @apidoc[Flow] with a @apidoc[Flow] that will restart it when it f
|
|||
|
||||
## Signature
|
||||
|
||||
@apidoc[RestartFlow.onFailuresWithBackoff](RestartFlow$) { scala="#onFailuresWithBackoff[In,Out](minBackoff:scala.concurrent.duration.FiniteDuration,maxBackoff:scala.concurrent.duration.FiniteDuration,randomFactor:Double,maxRestarts:Int)(flowFactory:()=>akka.stream.scaladsl.Flow[In,Out,_]):akka.stream.scaladsl.Flow[In,Out,akka.NotUsed]" java="#onFailuresWithBackoff(java.time.Duration,java.time.Duration,double,int,akka.japi.function.Creator)" }
|
||||
@apidoc[RestartFlow.onFailuresWithBackoff](RestartFlow$) { scala="#onFailuresWithBackoff[In,Out](settings:akka.stream.RestartSettings)(flowFactory:()=>akka.stream.scaladsl.Flow[In,Out,_]):akka.stream.scaladsl.Flow[In,Out,akka.NotUsed]" java="#onFailuresWithBackoff(akka.stream.RestartSettings,akka.japi.function.Creator)" }
|
||||
|
||||
|
||||
## Description
|
||||
|
||||
This @apidoc[Flow] will not emit any failure
|
||||
The failures by the wrapped @apidoc[Flow] will be handled by
|
||||
restarting the wrapping @apidoc[Flow] as long as maxRestarts is not reached.
|
||||
Any termination signals sent to this @apidoc[Flow] however will terminate the wrapped @apidoc[Flow], if it's
|
||||
Wrap the given @apidoc[Flow] with a @apidoc[Flow] that will restart it when it fails using exponential backoff.
|
||||
The backoff resets back to `minBackoff` if there hasn't been a restart within `maxRestartsWithin` (which defaults to `minBackoff` if max restarts).
|
||||
|
||||
This @apidoc[Flow] will not emit any failure as long as maxRestarts is not reached.
|
||||
The failure of the wrapped @apidoc[Flow] will be handled by restarting it.
|
||||
However, any termination signals sent to this @apidoc[Flow] will terminate the wrapped @apidoc[Flow], if it's
|
||||
running, and then the @apidoc[Flow] will be allowed to terminate without being restarted.
|
||||
|
||||
The restart process is inherently lossy, since there is no coordination between cancelling and the sending of
|
||||
messages. A termination signal from either end of the wrapped @apidoc[Flow] will cause the other end to be terminated,
|
||||
and any in transit messages will be lost. During backoff, this @apidoc[Flow] will backpressure.
|
||||
|
||||
This uses the same exponential backoff algorithm as @apidoc[Backoff$].
|
||||
This uses the same exponential backoff algorithm as @apidoc[BackoffOpts$].
|
||||
|
||||
See also:
|
||||
|
||||
* @ref:[RestartSource.withBackoff](../RestartSource/withBackoff.md)
|
||||
* @ref:[RestartSource.onFailuresWithBackoff](../RestartSource/onFailuresWithBackoff.md)
|
||||
* @ref:[RestartFlow.withBackoff](../RestartFlow/withBackoff.md)
|
||||
* @ref:[RestartSink.withBackoff](../RestartSink/withBackoff.md)
|
||||
|
||||
## Reactive Streams semantics
|
||||
|
||||
|
|
@ -31,4 +40,6 @@ This uses the same exponential backoff algorithm as @apidoc[Backoff$].
|
|||
|
||||
**backpressures** during backoff and when the wrapped flow backpressures
|
||||
|
||||
**completes** when the wrapped flow completes or `maxRestarts` are reached within the given time limit
|
||||
|
||||
@@@
|
||||
|
|
|
|||
|
|
@ -6,20 +6,30 @@ Wrap the given @apidoc[Flow] with a @apidoc[Flow] that will restart it when it f
|
|||
|
||||
## Signature
|
||||
|
||||
@apidoc[RestartFlow.withBackoff](RestartFlow$) { scala="#withBackoff[In,Out](minBackoff:scala.concurrent.duration.FiniteDuration,maxBackoff:scala.concurrent.duration.FiniteDuration,randomFactor:Double)(flowFactory:()=>akka.stream.scaladsl.Flow[In,Out,_]):akka.stream.scaladsl.Flow[In,Out,akka.NotUsed]" java="#withBackoff(java.time.Duration,java.time.Duration,double,int,akka.japi.function.Creator)" }
|
||||
@apidoc[RestartFlow.withBackoff](RestartFlow$) { scala="#withBackoff[In,Out](settings:akka.stream.RestartSettings)(flowFactory:()=>akka.stream.scaladsl.Flow[In,Out,_]):akka.stream.scaladsl.Flow[In,Out,akka.NotUsed]" java="#withBackoff(akka.stream.RestartSettings,akka.japi.function.Creator)" }
|
||||
|
||||
## Description
|
||||
|
||||
The resulting @apidoc[Flow] will not cancel, complete or emit a failure, until the opposite end of it has been cancelled or
|
||||
completed. Any termination by the @apidoc[Flow] before that time will be handled by restarting it. Any termination
|
||||
signals sent to this @apidoc[Flow] however will terminate the wrapped @apidoc[Flow], if it's running, and then the @apidoc[Flow]
|
||||
will be allowed to terminate without being restarted.
|
||||
Wrap the given @apidoc[Flow] with a @apidoc[Flow] that will restart it when it completes or fails using exponential backoff.
|
||||
The backoff resets back to `minBackoff` if there hasn't been a restart within `maxRestartsWithin` (which defaults to `minBackoff`).
|
||||
|
||||
This @apidoc[Flow] will not cancel, complete or emit a failure, until the opposite end of it has been cancelled or
|
||||
completed. Any termination by the @apidoc[Flow] before that time will be handled by restarting it as long as maxRestarts
|
||||
is not reached. Any termination signals sent to this @apidoc[Flow] however will terminate the wrapped @apidoc[Flow], if it's
|
||||
running, and then the @apidoc[Flow] will be allowed to terminate without being restarted.
|
||||
|
||||
The restart process is inherently lossy, since there is no coordination between cancelling and the sending of
|
||||
messages. A termination signal from either end of the wrapped @apidoc[Flow] will cause the other end to be terminated,
|
||||
and any in transit messages will be lost. During backoff, this @apidoc[Flow] will backpressure.
|
||||
|
||||
This uses the same exponential backoff algorithm as @apidoc[Backoff$].
|
||||
This uses the same exponential backoff algorithm as @apidoc[BackoffOpts$].
|
||||
|
||||
See also:
|
||||
|
||||
* @ref:[RestartSource.withBackoff](../RestartSource/withBackoff.md)
|
||||
* @ref:[RestartSource.onFailuresWithBackoff](../RestartSource/onFailuresWithBackoff.md)
|
||||
* @ref:[RestartFlow.onFailuresWithBackoff](../RestartFlow/onFailuresWithBackoff.md)
|
||||
* @ref:[RestartSink.withBackoff](../RestartSink/withBackoff.md)
|
||||
|
||||
## Reactive Streams semantics
|
||||
|
||||
|
|
@ -29,6 +39,6 @@ This uses the same exponential backoff algorithm as @apidoc[Backoff$].
|
|||
|
||||
**backpressures** during backoff and when the wrapped flow backpressures
|
||||
|
||||
**completes** when the wrapped flow completes
|
||||
**completes** when `maxRestarts` are reached within the given time limit
|
||||
|
||||
@@@
|
||||
|
|
|
|||
|
|
@ -6,19 +6,38 @@ Wrap the given @apidoc[Sink] with a @apidoc[Sink] that will restart it when it f
|
|||
|
||||
## Signature
|
||||
|
||||
@apidoc[RestartSink.withBackoff](RestartSink$) { scala="#withBackoff[T](minBackoff:scala.concurrent.duration.FiniteDuration,maxBackoff:scala.concurrent.duration.FiniteDuration,randomFactor:Double,maxRestarts:Int)(sinkFactory:()=>akka.stream.scaladsl.Sink[T,_]):akka.stream.scaladsl.Sink[T,akka.NotUsed]" java="#withBackoff(java.time.Duration,java.time.Duration,double,int,akka.japi.function.Creator)" }
|
||||
|
||||
@apidoc[RestartSink.withBackoff](RestartSink$) { scala="#withBackoff[T](settings:akka.stream.RestartSettings)(sinkFactory:()=>akka.stream.scaladsl.Sink[T,_]):akka.stream.scaladsl.Sink[T,akka.NotUsed]" java="#withBackoff(akka.stream.RestartSettings,akka.japi.function.Creator)" }
|
||||
|
||||
## Description
|
||||
|
||||
This @apidoc[Sink] will never cancel, since cancellation by the wrapped @apidoc[Sink] is always handled by restarting it.
|
||||
The wrapped @apidoc[Sink] can however be completed by feeding a completion or error into this @apidoc[Sink]. When that
|
||||
happens, the @apidoc[Sink], if currently running, will terminate and will not be restarted. This can be triggered
|
||||
simply by the upstream completing, or externally by introducing a @apidoc[KillSwitch] right before this @apidoc[Sink] in the
|
||||
graph.
|
||||
Wrap the given @apidoc[Sink] with a @apidoc[Sink] that will restart it when it completes or fails using exponential backoff.
|
||||
The backoff resets back to `minBackoff` if there hasn't been a restart within `maxRestartsWithin` (which defaults to `minBackoff`).
|
||||
|
||||
This @apidoc[Sink] will not cancel as long as maxRestarts is not reached, since cancellation by the wrapped @apidoc[Sink]
|
||||
is handled by restarting it. The wrapped @apidoc[Sink] can however be completed by feeding a completion or error into
|
||||
this @apidoc[Sink]. When that happens, the @apidoc[Sink], if currently running, will terminate and will not be restarted.
|
||||
This can be triggered simply by the upstream completing, or externally by introducing a @ref[KillSwitch](../../stream-dynamic.md#controlling-stream-completion-with-killswitch) right
|
||||
before this @apidoc[Sink] in the graph.
|
||||
|
||||
The restart process is inherently lossy, since there is no coordination between cancelling and the sending of
|
||||
messages. When the wrapped @apidoc[Sink] does cancel, this @apidoc[Sink] will backpressure, however any elements already
|
||||
sent may have been lost.
|
||||
|
||||
This uses the same exponential backoff algorithm as @apidoc[Backoff$].
|
||||
This uses the same exponential backoff algorithm as @apidoc[BackoffOpts$].
|
||||
|
||||
See also:
|
||||
|
||||
* @ref:[RestartSource.withBackoff](../RestartSource/withBackoff.md)
|
||||
* @ref:[RestartSource.onFailuresWithBackoff](../RestartSource/onFailuresWithBackoff.md)
|
||||
* @ref:[RestartFlow.onFailuresWithBackoff](../RestartFlow/onFailuresWithBackoff.md)
|
||||
* @ref:[RestartFlow.withBackoff](../RestartFlow/withBackoff.md)
|
||||
|
||||
## Reactive Streams semantics
|
||||
|
||||
@@@div { .callout }
|
||||
|
||||
**backpressures** during backoff and when the wrapped sink backpressures
|
||||
|
||||
**completes** when upstream completes or when `maxRestarts` are reached within the given time limit
|
||||
|
||||
@@@
|
||||
|
|
|
|||
|
|
@ -1,26 +1,29 @@
|
|||
# RestartSource.onFailuresWithBackoff
|
||||
|
||||
Wrap the given @apidoc[Source] with a @apidoc[Source] that will restart it when it fails using an exponential backoff.
|
||||
Wrap the given @apidoc[Source] with a @apidoc[Source] that will restart it when it fails using an exponential backoff. Notice that this @apidoc[Source] will not restart on completion of the wrapped flow.
|
||||
|
||||
@ref[Error handling](../index.md#error-handling)
|
||||
|
||||
## Signature
|
||||
|
||||
@apidoc[RestartSource.onFailuresWithBackoff](RestartSource$) { scala="#onFailuresWithBackoff[T](minBackoff:scala.concurrent.duration.FiniteDuration,maxBackoff:scala.concurrent.duration.FiniteDuration,randomFactor:Double)(sourceFactory:()=>akka.stream.scaladsl.Source[T,_]):akka.stream.scaladsl.Source[T,akka.NotUsed]" java="#onFailuresWithBackoff(java.time.Duration,java.time.Duration,double,int,akka.japi.function.Creator)" }
|
||||
@apidoc[RestartSource.onFailuresWithBackoff](RestartSource$) { scala="#onFailuresWithBackoff[T](settings:akka.stream.RestartSettings)(sourceFactory:()=>akka.stream.scaladsl.Source[T,_]):akka.stream.scaladsl.Source[T,akka.NotUsed]" java="#onFailuresWithBackoff(akka.stream.RestartSettings,akka.japi.function.Creator)" }
|
||||
|
||||
## Description
|
||||
|
||||
Wraps the given @apidoc[Source] with a @apidoc[Source] that will restart it when it fails using an exponential backoff.
|
||||
The backoff resets back to `minBackoff` if there hasn't been a failure within `minBackoff`.
|
||||
Wraps the given @apidoc[Source] with a @apidoc[Source] that will restart it when it fails using exponential backoff.
|
||||
The backoff resets back to `minBackoff` if there hasn't been a restart within `maxRestartsWithin` (which defaults to `minBackoff`).
|
||||
|
||||
This @apidoc[Source] will never emit a failure, since the failure of the wrapped @apidoc[Source] is always handled by
|
||||
restarting. The wrapped @apidoc[Source] can be completed by completing this @apidoc[Source].
|
||||
When that happens, the wrapped @apidoc[Source], if currently running will be cancelled, and it will not be restarted.
|
||||
This can be triggered by the downstream cancelling, or externally by introducing a @ref[KillSwitch](../../stream-dynamic.md#controlling-stream-completion-with-killswitch) right
|
||||
after this @apidoc[Source] in the graph.
|
||||
This @apidoc[Source] will not emit a failure as long as maxRestarts is not reached.
|
||||
The failure of the wrapped @apidoc[Source] is handled by restarting it.
|
||||
However, the wrapped @apidoc[Source] can be cancelled by cancelling this @apidoc[Source].
|
||||
When that happens, the wrapped @apidoc[Source], if currently running will, be cancelled and not restarted.
|
||||
This can be triggered by the downstream cancelling, or externally by introducing a @ref[KillSwitch](../../stream-dynamic.md#controlling-stream-completion-with-killswitch) right after this @apidoc[Source] in the graph.
|
||||
|
||||
This uses the same exponential backoff algorithm as @apidoc[BackoffOpts$].
|
||||
|
||||
See also:
|
||||
|
||||
* @ref:[RestartSource.withBackoff](../RestartSource/withBackoff.md)
|
||||
* @ref:[RestartFlow.onFailuresWithBackoff](../RestartFlow/onFailuresWithBackoff.md)
|
||||
* @ref:[RestartFlow.withBackoff](../RestartFlow/withBackoff.md)
|
||||
* @ref:[RestartSink.withBackoff](../RestartSink/withBackoff.md)
|
||||
|
|
@ -61,4 +64,10 @@ Java
|
|||
|
||||
**emits** when the wrapped source emits
|
||||
|
||||
**backpressures** during backoff and when downstream backpressures
|
||||
|
||||
**completes** when the wrapped source completes or `maxRestarts` are reached within the given time limit
|
||||
|
||||
**cancels** when downstream cancels
|
||||
|
||||
@@@
|
||||
|
|
|
|||
|
|
@ -1,22 +1,33 @@
|
|||
# RestartSource.withBackoff
|
||||
|
||||
Wrap the given @apidoc[Source] with a @apidoc[Source] that will restart it when it fails or complete using an exponential backoff.
|
||||
Wrap the given @apidoc[Source] with a @apidoc[Source] that will restart it when it fails or completes using an exponential backoff.
|
||||
|
||||
@ref[Error handling](../index.md#error-handling)
|
||||
|
||||
## Signature
|
||||
|
||||
@apidoc[RestartSource.withBackoff](RestartSource$) { scala="#withBackoff[T](minBackoff:scala.concurrent.duration.FiniteDuration,maxBackoff:scala.concurrent.duration.FiniteDuration,randomFactor:Double,maxRestarts:Int)(sourceFactory:()=>akka.stream.scaladsl.Source[T,_]):akka.stream.scaladsl.Source[T,akka.NotUsed]" java="#withBackoff(java.time.Duration,java.time.Duration,double,int,akka.japi.function.Creator)" }
|
||||
@apidoc[RestartSource.withBackoff](RestartSource$) { scala="#withBackoff[T](settings:akka.stream.RestartSettings)(sourceFactory:()=>akka.stream.scaladsl.Source[T,_]):akka.stream.scaladsl.Source[T,akka.NotUsed]" java="#withBackoff(akka.stream.RestartSettings,akka.japi.function.Creator)" }
|
||||
|
||||
## Description
|
||||
|
||||
This @apidoc[Flow] will never emit a complete or failure, since the completion or failure of the wrapped @apidoc[Source]
|
||||
is always handled by restarting it. The wrapped @apidoc[Source] can however be cancelled by cancelling this @apidoc[Source].
|
||||
When that happens, the wrapped @apidoc[Source], if currently running will be cancelled, and it will not be restarted.
|
||||
This can be triggered simply by the downstream cancelling, or externally by introducing a @apidoc[KillSwitch] right
|
||||
Wrap the given @apidoc[Source] with a @apidoc[Source] that will restart it when it completes or fails using exponential backoff.
|
||||
The backoff resets back to `minBackoff` if there hasn't been a restart within `maxRestartsWithin` (which defaults to `minBackoff`).
|
||||
|
||||
This @apidoc[Source] will not emit a complete or fail as long as maxRestarts is not reached, since the completion
|
||||
or failure of the wrapped @apidoc[Source] is handled by restarting it. The wrapped @apidoc[Source] can however be cancelled
|
||||
by cancelling this @apidoc[Source]. When that happens, the wrapped @apidoc[Source], if currently running, will be cancelled,
|
||||
and it will not be restarted.
|
||||
This can be triggered simply by the downstream cancelling, or externally by introducing a @ref[KillSwitch](../../stream-dynamic.md#controlling-stream-completion-with-killswitch) right
|
||||
after this @apidoc[Source] in the graph.
|
||||
|
||||
This uses the same exponential backoff algorithm as @apidoc[Backoff$].
|
||||
This uses the same exponential backoff algorithm as @apidoc[BackoffOpts$].
|
||||
|
||||
See also:
|
||||
|
||||
* @ref:[RestartSource.onFailuresWithBackoff](../RestartSource/onFailuresWithBackoff.md)
|
||||
* @ref:[RestartFlow.onFailuresWithBackoff](../RestartFlow/onFailuresWithBackoff.md)
|
||||
* @ref:[RestartFlow.withBackoff](../RestartFlow/withBackoff.md)
|
||||
* @ref:[RestartSink.withBackoff](../RestartSink/withBackoff.md)
|
||||
|
||||
## Reactive Streams semantics
|
||||
|
||||
|
|
@ -24,6 +35,10 @@ This uses the same exponential backoff algorithm as @apidoc[Backoff$].
|
|||
|
||||
**emits** when the wrapped source emits
|
||||
|
||||
**completes** when the wrapped source completes
|
||||
**backpressures** during backoff and when downstream backpressures
|
||||
|
||||
**completes** when `maxRestarts` are reached within the given time limit
|
||||
|
||||
**cancels** when downstream cancels
|
||||
|
||||
@@@
|
||||
|
|
|
|||
|
|
@ -344,9 +344,9 @@ For more background see the @ref[Error Handling in Streams](../stream-error.md)
|
|||
|
||||
| |Operator|Description|
|
||||
|--|--|--|
|
||||
|RestartSource|<a name="onfailureswithbackoff"></a>@ref[onFailuresWithBackoff](RestartSource/onFailuresWithBackoff.md)|Wrap the given @apidoc[Source] with a @apidoc[Source] that will restart it when it fails using an exponential backoff.|
|
||||
|RestartSource|<a name="onfailureswithbackoff"></a>@ref[onFailuresWithBackoff](RestartSource/onFailuresWithBackoff.md)|Wrap the given @apidoc[Source] with a @apidoc[Source] that will restart it when it fails using an exponential backoff. Notice that this @apidoc[Source] will not restart on completion of the wrapped flow.|
|
||||
|RestartFlow|<a name="onfailureswithbackoff"></a>@ref[onFailuresWithBackoff](RestartFlow/onFailuresWithBackoff.md)|Wrap the given @apidoc[Flow] with a @apidoc[Flow] that will restart it when it fails using an exponential backoff. Notice that this @apidoc[Flow] will not restart on completion of the wrapped flow.|
|
||||
|RestartSource|<a name="withbackoff"></a>@ref[withBackoff](RestartSource/withBackoff.md)|Wrap the given @apidoc[Source] with a @apidoc[Source] that will restart it when it fails or complete using an exponential backoff.|
|
||||
|RestartSource|<a name="withbackoff"></a>@ref[withBackoff](RestartSource/withBackoff.md)|Wrap the given @apidoc[Source] with a @apidoc[Source] that will restart it when it fails or completes using an exponential backoff.|
|
||||
|RestartFlow|<a name="withbackoff"></a>@ref[withBackoff](RestartFlow/withBackoff.md)|Wrap the given @apidoc[Flow] with a @apidoc[Flow] that will restart it when it fails or complete using an exponential backoff.|
|
||||
|RestartSink|<a name="withbackoff"></a>@ref[withBackoff](RestartSink/withBackoff.md)|Wrap the given @apidoc[Sink] with a @apidoc[Sink] that will restart it when it fails or complete using an exponential backoff.|
|
||||
|RetryFlow|<a name="withbackoff"></a>@ref[withBackoff](RetryFlow/withBackoff.md)|Wrap the given @apidoc[Flow] and retry individual elements in that stream with an exponential backoff. A decider function tests every emitted element and can return a new element to be sent to the wrapped flow for another try.|
|
||||
|
|
|
|||
|
|
@ -114,6 +114,15 @@ when a WebSocket connection fails due to the HTTP server it's running on going d
|
|||
By using an exponential backoff, we avoid going into a tight reconnect loop, which both gives the HTTP server some time
|
||||
to recover, and it avoids using needless resources on the client side.
|
||||
|
||||
The various restart shapes mentioned all expect an `akka.stream.RestartSettings` which configures the restart behaviour.
|
||||
Configurable parameters are:
|
||||
|
||||
* `minBackoff` is the initial duration until the underlying stream is restarted
|
||||
* `maxBackoff` caps the exponential backoff
|
||||
* `randomFactor` allows addition of a random delay following backoff calculation
|
||||
* `maxRestarts` caps the total number of restarts
|
||||
* `maxRestartsWithin` sets a timeframe during which restarts are counted towards the same total for `maxRestarts`
|
||||
|
||||
The following snippet shows how to create a backoff supervisor using @scala[`akka.stream.scaladsl.RestartSource`]
|
||||
@java[`akka.stream.javadsl.RestartSource`] which will supervise the given `Source`. The `Source` in this case is a
|
||||
stream of Server Sent Events, produced by akka-http. If the stream fails or completes at any point, the request will
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import akka.actor.ActorSystem;
|
|||
import akka.stream.KillSwitch;
|
||||
import akka.stream.KillSwitches;
|
||||
import akka.stream.Materializer;
|
||||
import akka.stream.RestartSettings;
|
||||
import akka.stream.javadsl.Keep;
|
||||
import akka.stream.javadsl.RestartSource;
|
||||
import akka.stream.javadsl.Sink;
|
||||
|
|
@ -61,12 +62,18 @@ public class RestartDocTest {
|
|||
|
||||
public void recoverWithBackoffSource() {
|
||||
// #restart-with-backoff-source
|
||||
RestartSettings settings =
|
||||
RestartSettings.create(
|
||||
Duration.ofSeconds(3), // min backoff
|
||||
Duration.ofSeconds(30), // max backoff
|
||||
0.2 // adds 20% "noise" to vary the intervals slightly
|
||||
)
|
||||
.withMaxRestarts(
|
||||
20, Duration.ofMinutes(5)); // limits the amount of restarts to 20 within 5 minutes
|
||||
|
||||
Source<ServerSentEvent, NotUsed> eventStream =
|
||||
RestartSource.withBackoff(
|
||||
Duration.ofSeconds(3), // min backoff
|
||||
Duration.ofSeconds(30), // max backoff
|
||||
0.2, // adds 20% "noise" to vary the intervals slightly
|
||||
20, // limits the amount of restarts to 20
|
||||
settings,
|
||||
() ->
|
||||
// Create a source from a future of a source
|
||||
Source.completionStageSource(
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import akka.NotUsed;
|
|||
import akka.actor.Cancellable;
|
||||
import akka.japi.Creator;
|
||||
import akka.stream.KillSwitches;
|
||||
import akka.stream.RestartSettings;
|
||||
import akka.stream.UniqueKillSwitch;
|
||||
import akka.stream.javadsl.Keep;
|
||||
import akka.stream.javadsl.RestartSource;
|
||||
|
|
@ -34,7 +35,8 @@ public class Restart {
|
|||
}));
|
||||
Source<Creator<Integer>, NotUsed> forever =
|
||||
RestartSource.onFailuresWithBackoff(
|
||||
Duration.ofSeconds(1), Duration.ofSeconds(10), 0.1, () -> flakySource);
|
||||
RestartSettings.create(Duration.ofSeconds(1), Duration.ofSeconds(10), 0.1),
|
||||
() -> flakySource);
|
||||
forever.runWith(
|
||||
Sink.foreach((Creator<Integer> nr) -> system.log().info("{}", nr.create())), system);
|
||||
// logs
|
||||
|
|
@ -99,7 +101,8 @@ public class Restart {
|
|||
}));
|
||||
UniqueKillSwitch stopRestarting =
|
||||
RestartSource.onFailuresWithBackoff(
|
||||
Duration.ofSeconds(1), Duration.ofSeconds(10), 0.1, () -> flakySource)
|
||||
RestartSettings.create(Duration.ofSeconds(1), Duration.ofSeconds(10), 0.1),
|
||||
() -> flakySource)
|
||||
.viaMat(KillSwitches.single(), Keep.right())
|
||||
.toMat(Sink.foreach(nr -> System.out.println("nr " + nr.create())), Keep.left())
|
||||
.run(system);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
package docs.stream
|
||||
|
||||
import akka.NotUsed
|
||||
import akka.stream.KillSwitches
|
||||
import akka.stream.{ KillSwitches, RestartSettings }
|
||||
import akka.stream.scaladsl._
|
||||
import akka.testkit.AkkaSpec
|
||||
import docs.CompileOnlySpec
|
||||
|
|
@ -34,12 +34,13 @@ class RestartDocSpec extends AkkaSpec with CompileOnlySpec {
|
|||
"demonstrate a restart with backoff source" in compileOnlySpec {
|
||||
|
||||
//#restart-with-backoff-source
|
||||
val restartSource = RestartSource.withBackoff(
|
||||
val settings = RestartSettings(
|
||||
minBackoff = 3.seconds,
|
||||
maxBackoff = 30.seconds,
|
||||
randomFactor = 0.2, // adds 20% "noise" to vary the intervals slightly
|
||||
maxRestarts = 20 // limits the amount of restarts to 20
|
||||
) { () =>
|
||||
randomFactor = 0.2 // adds 20% "noise" to vary the intervals slightly
|
||||
).withMaxRestarts(20, 5.minutes) // limits the amount of restarts to 20 within 5 minutes
|
||||
|
||||
val restartSource = RestartSource.withBackoff(settings) { () =>
|
||||
// Create a source from a future of a source
|
||||
Source.futureSource {
|
||||
// Make a single request with akka-http
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@ package docs.stream.operators.source
|
|||
|
||||
import akka.NotUsed
|
||||
import akka.actor.ActorSystem
|
||||
import akka.stream.KillSwitches
|
||||
import akka.stream.UniqueKillSwitch
|
||||
import akka.stream.{ KillSwitches, RestartSettings, UniqueKillSwitch }
|
||||
import akka.stream.scaladsl.Keep
|
||||
import akka.stream.scaladsl.RestartSource
|
||||
import akka.stream.scaladsl.Sink
|
||||
|
|
@ -31,7 +30,8 @@ object Restart extends App {
|
|||
val flakySource: Source[() => Int, NotUsed] =
|
||||
Source(List(() => 1, () => 2, () => 3, () => throw CantConnectToDatabase("darn")))
|
||||
val forever =
|
||||
RestartSource.onFailuresWithBackoff(minBackoff = 1.second, maxBackoff = 10.seconds, 0.1)(() => flakySource)
|
||||
RestartSource.onFailuresWithBackoff(
|
||||
RestartSettings(minBackoff = 1.second, maxBackoff = 10.seconds, randomFactor = 0.1))(() => flakySource)
|
||||
forever.runWith(Sink.foreach(nr => system.log.info("{}", nr())))
|
||||
// logs
|
||||
//[INFO] [12/10/2019 13:51:58.300] [default-akka.test.stream-dispatcher-7] [akka.actor.ActorSystemImpl(default)] 1
|
||||
|
|
@ -56,7 +56,7 @@ object Restart extends App {
|
|||
|
||||
//#restart-failure-inner-complete
|
||||
val finiteSource = Source.tick(1.second, 1.second, "tick").take(3)
|
||||
val forever = RestartSource.onFailuresWithBackoff(1.second, 10.seconds, 0.1)(() => finiteSource)
|
||||
val forever = RestartSource.onFailuresWithBackoff(RestartSettings(1.second, 10.seconds, 0.1))(() => finiteSource)
|
||||
forever.runWith(Sink.foreach(println))
|
||||
// prints
|
||||
// tick
|
||||
|
|
@ -71,7 +71,7 @@ object Restart extends App {
|
|||
Source(List(() => 1, () => 2, () => 3, () => throw CantConnectToDatabase("darn")))
|
||||
val stopRestarting: UniqueKillSwitch =
|
||||
RestartSource
|
||||
.onFailuresWithBackoff(1.second, 10.seconds, 0.1)(() => flakySource)
|
||||
.onFailuresWithBackoff(RestartSettings(1.second, 10.seconds, 0.1))(() => flakySource)
|
||||
.viaMat(KillSwitches.single)(Keep.right)
|
||||
.toMat(Sink.foreach(nr => println(s"Nr ${nr()}")))(Keep.left)
|
||||
.run()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue