From 8f35fdc4b584cc78159e66551038027ea1639122 Mon Sep 17 00:00:00 2001 From: Marc Piechura Date: Thu, 6 Oct 2016 13:46:02 +0200 Subject: [PATCH] Stream update 2.4.8 (#2333) * Update Streams to 2.4.8 * Fix log messages * Fix failure message --- .../CoreAPISpec.ApproveStreams.approved.txt | 1216 ++++++++++++++++- .../Actor/ActorPublisherSpec.cs | 27 +- .../Akka.Streams.Tests.csproj | 1 + .../Akka.Streams.Tests/Dsl/FlowGroupBySpec.cs | 36 + .../Akka.Streams.Tests/Dsl/FlowScanSpec.cs | 22 + .../Akka.Streams.Tests/Dsl/LazySinkSpec.cs | 242 ++++ .../Implementation/Fusing/InterpreterSpec.cs | 25 +- .../Fusing/InterpreterSupervisionSpec.cs | 4 +- .../Fusing/LifecycleInterpreterSpec.cs | 2 +- src/core/Akka.Streams/ActorMaterializer.cs | 27 +- .../Akka.Streams/Actors/ActorPublisher.cs | 16 +- src/core/Akka.Streams/Attributes.cs | 2 +- src/core/Akka.Streams/CodeGen/Dsl/ZipWith.cs | 74 +- src/core/Akka.Streams/CodeGen/Dsl/ZipWith.tt | 9 +- .../Akka.Streams/Dsl/Internal/GraphImpl.cs | 18 +- .../Dsl/Internal/InternalFlowOperations.cs | 8 +- src/core/Akka.Streams/Dsl/Sink.cs | 14 +- src/core/Akka.Streams/Dsl/Source.cs | 2 +- .../Implementation/ActorMaterializerImpl.cs | 80 +- .../Implementation/ActorProcessor.cs | 4 +- .../Implementation/ActorPublisher.cs | 4 +- src/core/Akka.Streams/Implementation/FanIn.cs | 6 +- .../Akka.Streams/Implementation/FanOut.cs | 6 +- .../Fusing/ActorGraphInterpreter.cs | 23 +- .../Implementation/Fusing/GraphStages.cs | 28 +- .../Akka.Streams/Implementation/Fusing/Ops.cs | 532 +++++--- .../Implementation/Fusing/StreamOfStreams.cs | 10 +- .../Akka.Streams/Implementation/IO/IOSinks.cs | 4 +- .../Implementation/IO/IOSources.cs | 4 +- .../IO/OutputStreamSourceStage.cs | 2 +- .../Implementation/IO/TcpStages.cs | 2 +- .../Akka.Streams/Implementation/Modules.cs | 28 +- .../ReactiveStreamsCompliance.cs | 4 +- src/core/Akka.Streams/Implementation/Sinks.cs | 323 ++++- .../Akka.Streams/Implementation/Sources.cs | 8 +- .../Implementation/Stages/Stages.cs | 80 +- .../Implementation/StreamLayout.cs | 14 +- .../Akka.Streams/Implementation/Throttle.cs | 5 +- .../Akka.Streams/Implementation/Timers.cs | 37 +- .../Akka.Streams/Implementation/Transfer.cs | 8 +- .../Akka.Streams/Implementation/Unfold.cs | 10 +- .../Implementation/UntypedPublisher.cs | 2 +- .../Implementation/UntypedSubscriber.cs | 2 +- src/core/Akka.Streams/Stage/GraphStage.cs | 3 +- 44 files changed, 2473 insertions(+), 501 deletions(-) create mode 100644 src/core/Akka.Streams.Tests/Dsl/LazySinkSpec.cs diff --git a/src/core/Akka.API.Tests/CoreAPISpec.ApproveStreams.approved.txt b/src/core/Akka.API.Tests/CoreAPISpec.ApproveStreams.approved.txt index e8680bd6602..adf0f70f628 100644 --- a/src/core/Akka.API.Tests/CoreAPISpec.ApproveStreams.approved.txt +++ b/src/core/Akka.API.Tests/CoreAPISpec.ApproveStreams.approved.txt @@ -40,7 +40,7 @@ namespace Akka.Streams public abstract Akka.Streams.ActorMaterializerSettings Settings { get; } public abstract Akka.Actor.IActorRef Supervisor { get; } public abstract Akka.Actor.ActorSystem System { get; } - protected internal abstract Akka.Actor.IActorRef ActorOf(Akka.Streams.MaterializationContext context, Akka.Actor.Props props); + public abstract Akka.Actor.IActorRef ActorOf(Akka.Streams.MaterializationContext context, Akka.Actor.Props props); public static Akka.Streams.ActorMaterializer Create(Akka.Actor.IActorRefFactory context, Akka.Streams.ActorMaterializerSettings settings = null, string namePrefix = null) { } public static Akka.Configuration.Config DefaultConfig() { } public void Dispose() { } @@ -113,6 +113,7 @@ namespace Akka.Streams public TAttr GetFirstAttribute() where TAttr : class, Akka.Streams.Attributes.IAttribute { } public string GetNameLifted() { } + public string GetNameOrDefault(string defaultIfNotFound = "unknown-operation") { } public override string ToString() { } public sealed class AsyncBoundary : Akka.Streams.Attributes.IAttribute, System.IEquatable { @@ -621,6 +622,17 @@ namespace Akka.Streams System.Collections.Generic.IEnumerable OnNext(TIn element); System.Collections.Generic.IEnumerable OnTermination(System.Exception cause); } + public interface IUntypedPublisher + { + void Subscribe(Akka.Streams.IUntypedSubscriber subscriber); + } + public interface IUntypedSubscriber + { + void OnComplete(); + void OnError(System.Exception cause); + void OnNext(object element); + void OnSubscribe(Reactive.Streams.ISubscription subscription); + } public class static KillSwitches { public static Akka.Streams.SharedKillSwitch Shared(string name) { } @@ -1418,10 +1430,12 @@ namespace Akka.Streams.Dsl public static Akka.Streams.Dsl.Sink Ignore() { } public static Akka.Streams.Dsl.Sink> Last() { } public static Akka.Streams.Dsl.Sink> LastOrDefault() { } + public static Akka.Streams.Dsl.Sink> LazySink(System.Func>> sinkFactory, System.Func fallback) { } public static Akka.Streams.Dsl.Sink OnComplete(System.Action success, System.Action failure) { } public static Akka.Streams.Dsl.Sink> Publisher() { } public static Akka.Streams.Dsl.Sink> Queue() { } public static Akka.Streams.Dsl.Sink>> Seq() { } + public static Akka.Streams.SinkShape Shape(string name) { } public static Akka.Streams.Dsl.Sink> Sum(System.Func reduce) { } public static Akka.Streams.Dsl.Sink Wrap(Akka.Streams.IGraph, TMat> graph) { } } @@ -1456,6 +1470,7 @@ namespace Akka.Streams.Dsl public static Akka.Streams.Dsl.Source> Maybe() { } public static Akka.Streams.Dsl.Source> Queue(int bufferSize, Akka.Streams.OverflowStrategy overflowStrategy) { } public static Akka.Streams.Dsl.Source Repeat(T element) { } + public static Akka.Streams.SourceShape Shape(string name) { } public static Akka.Streams.Dsl.Source Single(T element) { } public static Akka.Streams.Dsl.Source Tick(System.TimeSpan initialDelay, System.TimeSpan interval, T tick) { } public static Akka.Streams.Dsl.Source Unfold(TState state, System.Func> unfold) { } @@ -1867,6 +1882,7 @@ namespace Akka.Streams.Dsl protected virtual Akka.Streams.Attributes InitialAttributes { get; } public Akka.Streams.Outlet Out { get; } public virtual Akka.Streams.FanInShape Shape { get; } + public System.Func Zipper { get; } protected virtual Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } } public class ZipWith : Akka.Streams.Stage.GraphStage> @@ -1877,6 +1893,7 @@ namespace Akka.Streams.Dsl protected virtual Akka.Streams.Attributes InitialAttributes { get; } public Akka.Streams.Outlet Out { get; } public virtual Akka.Streams.FanInShape Shape { get; } + public System.Func Zipper { get; } protected virtual Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } } public class ZipWith : Akka.Streams.Stage.GraphStage> @@ -1888,6 +1905,7 @@ namespace Akka.Streams.Dsl protected virtual Akka.Streams.Attributes InitialAttributes { get; } public Akka.Streams.Outlet Out { get; } public virtual Akka.Streams.FanInShape Shape { get; } + public System.Func Zipper { get; } protected virtual Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } } public class ZipWith : Akka.Streams.Stage.GraphStage> @@ -1900,6 +1918,7 @@ namespace Akka.Streams.Dsl protected virtual Akka.Streams.Attributes InitialAttributes { get; } public Akka.Streams.Outlet Out { get; } public virtual Akka.Streams.FanInShape Shape { get; } + public System.Func Zipper { get; } protected virtual Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } } public class ZipWith : Akka.Streams.Stage.GraphStage> @@ -1913,6 +1932,7 @@ namespace Akka.Streams.Dsl protected virtual Akka.Streams.Attributes InitialAttributes { get; } public Akka.Streams.Outlet Out { get; } public virtual Akka.Streams.FanInShape Shape { get; } + public System.Func Zipper { get; } protected virtual Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } } public class ZipWith : Akka.Streams.Stage.GraphStage> @@ -1927,6 +1947,7 @@ namespace Akka.Streams.Dsl protected virtual Akka.Streams.Attributes InitialAttributes { get; } public Akka.Streams.Outlet Out { get; } public virtual Akka.Streams.FanInShape Shape { get; } + public System.Func Zipper { get; } protected virtual Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } } public class ZipWith : Akka.Streams.Stage.GraphStage> @@ -1942,6 +1963,7 @@ namespace Akka.Streams.Dsl protected virtual Akka.Streams.Attributes InitialAttributes { get; } public Akka.Streams.Outlet Out { get; } public virtual Akka.Streams.FanInShape Shape { get; } + public System.Func Zipper { get; } protected virtual Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } } public class ZipWith : Akka.Streams.Stage.GraphStage> @@ -1958,6 +1980,7 @@ namespace Akka.Streams.Dsl protected virtual Akka.Streams.Attributes InitialAttributes { get; } public Akka.Streams.Outlet Out { get; } public virtual Akka.Streams.FanInShape Shape { get; } + public System.Func Zipper { get; } protected virtual Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } } public class static ZipWithN @@ -1976,6 +1999,26 @@ namespace Akka.Streams.Dsl public override string ToString() { } } } +namespace Akka.Streams.Dsl.Internal +{ + public class GraphImpl : Akka.Streams.IGraph, Akka.Streams.IGraph + where TShape : Akka.Streams.Shape + { + public GraphImpl(TShape shape, Akka.Streams.Implementation.IModule module) { } + public Akka.Streams.Implementation.IModule Module { get; } + public TShape Shape { get; } + public Akka.Streams.IGraph AddAttributes(Akka.Streams.Attributes attributes) { } + public Akka.Streams.IGraph Async() { } + public Akka.Streams.IGraph Named(string name) { } + public override string ToString() { } + public Akka.Streams.IGraph WithAttributes(Akka.Streams.Attributes attributes) { } + } + public class static ModuleExtractor + { + public static Akka.Streams.Util.Option Unapply(Akka.Streams.IGraph graph) + where TShape : Akka.Streams.Shape { } + } +} namespace Akka.Streams.Extra { public class static TimedFlowDsl @@ -1991,7 +2034,7 @@ namespace Akka.Streams.Extra } namespace Akka.Streams.Implementation { - public sealed class ActorMaterializerImpl : Akka.Streams.ActorMaterializer + public sealed class ActorMaterializerImpl : Akka.Streams.Implementation.ExtendedActorMaterializer { public ActorMaterializerImpl(Akka.Actor.ActorSystem system, Akka.Streams.ActorMaterializerSettings settings, Akka.Dispatch.Dispatchers dispatchers, Akka.Actor.IActorRef supervisor, Akka.Util.AtomicBoolean haveShutDown, Akka.Streams.Implementation.EnumerableActorName flowNames) { } public override Akka.Dispatch.MessageDispatcher ExecutionContext { get; } @@ -2000,14 +2043,19 @@ namespace Akka.Streams.Implementation public override Akka.Streams.ActorMaterializerSettings Settings { get; } public override Akka.Actor.IActorRef Supervisor { get; } public override Akka.Actor.ActorSystem System { get; } - protected internal override Akka.Actor.IActorRef ActorOf(Akka.Streams.MaterializationContext context, Akka.Actor.Props props) { } public override Akka.Streams.ActorMaterializerSettings EffectiveSettings(Akka.Streams.Attributes attributes) { } public override TMat Materialize(Akka.Streams.IGraph runnable) { } + public override TMat Materialize(Akka.Streams.IGraph runnable, System.Func subFlowFuser) { } public override Akka.Actor.ICancelable ScheduleOnce(System.TimeSpan delay, System.Action action) { } public override Akka.Actor.ICancelable ScheduleRepeatedly(System.TimeSpan initialDelay, System.TimeSpan interval, System.Action action) { } public override void Shutdown() { } public override Akka.Streams.IMaterializer WithNamePrefix(string name) { } } + public class static ActorPublisher + { + public static readonly Akka.Streams.Implementation.NormalShutdownException NormalShutdownReason; + public const string NormalShutdownReasonMessage = "Cannot subscribe to shut-down Publisher"; + } public class ActorPublisher : Akka.Streams.Implementation.IActorPublisher, Akka.Streams.IUntypedPublisher, Reactive.Streams.IPublisher { protected readonly Akka.Actor.IActorRef Impl; @@ -2017,6 +2065,22 @@ namespace Akka.Streams.Implementation public void Subscribe(Reactive.Streams.ISubscriber subscriber) { } public System.Collections.Generic.IEnumerable> TakePendingSubscribers() { } } + public sealed class ActorPublisherSource : Akka.Streams.Implementation.SourceModule + { + public ActorPublisherSource(Akka.Actor.Props props, Akka.Streams.Attributes attributes, Akka.Streams.SourceShape shape) { } + public override Akka.Streams.Attributes Attributes { get; } + public override Reactive.Streams.IPublisher Create(Akka.Streams.MaterializationContext context, out Akka.Actor.IActorRef materializer) { } + protected override Akka.Streams.Implementation.SourceModule NewInstance(Akka.Streams.SourceShape shape) { } + public override Akka.Streams.Implementation.IModule WithAttributes(Akka.Streams.Attributes attributes) { } + } + public sealed class ActorRefSink : Akka.Streams.Implementation.SinkModule + { + public ActorRefSink(Akka.Actor.IActorRef @ref, object onCompleteMessage, Akka.Streams.Attributes attributes, Akka.Streams.SinkShape shape) { } + public override Akka.Streams.Attributes Attributes { get; } + public override object Create(Akka.Streams.MaterializationContext context, out Akka.NotUsed materializer) { } + protected override Akka.Streams.Implementation.SinkModule NewInstance(Akka.Streams.SinkShape shape) { } + public override Akka.Streams.Implementation.IModule WithAttributes(Akka.Streams.Attributes attributes) { } + } public class ActorRefSinkActor : Akka.Streams.Actors.ActorSubscriber { protected readonly int HighWatermark; @@ -2028,6 +2092,23 @@ namespace Akka.Streams.Implementation public static Akka.Actor.Props Props(Akka.Actor.IActorRef @ref, int highWatermark, object onCompleteMessage) { } protected override bool Receive(object message) { } } + public sealed class ActorRefSource : Akka.Streams.Implementation.SourceModule + { + public ActorRefSource(int bufferSize, Akka.Streams.OverflowStrategy overflowStrategy, Akka.Streams.Attributes attributes, Akka.Streams.SourceShape shape) { } + public override Akka.Streams.Attributes Attributes { get; } + protected override string Label { get; } + public override Reactive.Streams.IPublisher Create(Akka.Streams.MaterializationContext context, out Akka.Actor.IActorRef materializer) { } + protected override Akka.Streams.Implementation.SourceModule NewInstance(Akka.Streams.SourceShape shape) { } + public override Akka.Streams.Implementation.IModule WithAttributes(Akka.Streams.Attributes attributes) { } + } + public sealed class ActorSubscriberSink : Akka.Streams.Implementation.SinkModule + { + public ActorSubscriberSink(Akka.Actor.Props props, Akka.Streams.Attributes attributes, Akka.Streams.SinkShape shape) { } + public override Akka.Streams.Attributes Attributes { get; } + public override object Create(Akka.Streams.MaterializationContext context, out Akka.Actor.IActorRef materializer) { } + protected override Akka.Streams.Implementation.SinkModule NewInstance(Akka.Streams.SinkShape shape) { } + public override Akka.Streams.Implementation.IModule WithAttributes(Akka.Streams.Attributes attributes) { } + } public class static ActorSubscription { public static Akka.Streams.Implementation.IActorSubscription Create(Akka.Actor.IActorRef implementor, Reactive.Streams.ISubscriber subscriber) { } @@ -2056,6 +2137,38 @@ namespace Akka.Streams.Implementation public virtual System.Collections.Immutable.ImmutableArray SubModules { get; } public virtual System.Collections.Immutable.IImmutableDictionary Upstreams { get; } } + public sealed class BackpressureTimeout : Akka.Streams.Implementation.Fusing.SimpleLinearGraphStage + { + public readonly System.TimeSpan Timeout; + public BackpressureTimeout(System.TimeSpan timeout) { } + protected override Akka.Streams.Attributes InitialAttributes { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } + public abstract class BatchingInputBuffer : Akka.Streams.Implementation.IInputs + { + public readonly int Count; + public readonly Akka.Streams.Implementation.IPump Pump; + protected BatchingInputBuffer(int count, Akka.Streams.Implementation.IPump pump) { } + public bool AreInputsAvailable { get; } + public bool AreInputsDepleted { get; } + public bool IsClosed { get; } + public bool IsOpen { get; } + public Akka.Streams.Implementation.TransferState NeedsInput { get; } + public Akka.Streams.Implementation.TransferState NeedsInputOrComplete { get; } + public virtual Akka.Streams.Implementation.SubReceive SubReceive { get; } + public virtual void Cancel() { } + protected virtual bool Completed(object message) { } + public virtual object DequeueInputElement() { } + protected virtual void EnqueueInputElement(object element) { } + protected virtual void InputOnError(System.Exception e) { } + protected virtual void OnComplete() { } + protected virtual void OnError(System.Exception e) { } + protected virtual void OnSubscribe(Reactive.Streams.ISubscription subscription) { } + public override string ToString() { } + protected virtual bool UpstreamRunning(object message) { } + protected virtual bool WaitingForUpstream(object message) { } + } public sealed class CancelingSubscriber : Reactive.Streams.ISubscriber { public static readonly Akka.Streams.Implementation.CancelingSubscriber Instance; @@ -2064,6 +2177,22 @@ namespace Akka.Streams.Implementation public void OnNext(T element) { } public void OnSubscribe(Reactive.Streams.ISubscription subscription) { } } + public sealed class CancelSink : Akka.Streams.Implementation.SinkModule + { + public CancelSink(Akka.Streams.Attributes attributes, Akka.Streams.SinkShape shape) { } + public override Akka.Streams.Attributes Attributes { get; } + public override object Create(Akka.Streams.MaterializationContext context, out Akka.NotUsed materializer) { } + protected override Akka.Streams.Implementation.SinkModule NewInstance(Akka.Streams.SinkShape shape) { } + public override Akka.Streams.Implementation.IModule WithAttributes(Akka.Streams.Attributes attributes) { } + } + public sealed class Completion : Akka.Streams.Implementation.Fusing.SimpleLinearGraphStage + { + public readonly System.TimeSpan Timeout; + public Completion(System.TimeSpan timeout) { } + protected override Akka.Streams.Attributes InitialAttributes { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } public sealed class CompositeModule : Akka.Streams.Implementation.Module { public CompositeModule(System.Collections.Immutable.ImmutableArray subModules, Akka.Streams.Shape shape, System.Collections.Immutable.IImmutableDictionary downstreams, System.Collections.Immutable.IImmutableDictionary upstreams, Akka.Streams.Implementation.StreamLayout.IMaterializedValueNode materializedValueComputation, Akka.Streams.Attributes attributes) { } @@ -2093,6 +2222,17 @@ namespace Akka.Streams.Implementation public override string ToString() { } public override Akka.Streams.Implementation.IModule WithAttributes(Akka.Streams.Attributes attributes) { } } + public sealed class DelayInitial : Akka.Streams.Stage.GraphStage> + { + public readonly System.TimeSpan Delay; + public readonly Akka.Streams.Inlet In; + public readonly Akka.Streams.Outlet Out; + public DelayInitial(System.TimeSpan delay) { } + protected override Akka.Streams.Attributes InitialAttributes { get; } + public override Akka.Streams.FlowShape Shape { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } public sealed class EmptyModule : Akka.Streams.Implementation.Module { public static readonly Akka.Streams.Implementation.EmptyModule Instance; @@ -2129,6 +2269,141 @@ namespace Akka.Streams.Implementation protected ExposedPublisherReceive(Akka.Actor.Receive activeReceive, System.Action unhandled) { } public bool Apply(object message) { } } + public abstract class ExtendedActorMaterializer : Akka.Streams.ActorMaterializer + { + protected ExtendedActorMaterializer() { } + public override Akka.Actor.IActorRef ActorOf(Akka.Streams.MaterializationContext context, Akka.Actor.Props props) { } + protected Akka.Actor.IActorRef ActorOf(Akka.Actor.Props props, string name, string dispatcher) { } + public abstract TMat Materialize(Akka.Streams.IGraph runnable, System.Func subFlowFuser); + } + public class static FanIn + { + public const byte Cancelled = 16; + public const byte Completed = 8; + public const byte Depleted = 4; + public const byte Marked = 1; + public const byte Pending = 2; + public struct OnComplete : Akka.Actor.INoSerializationVerificationNeeded, Akka.Event.IDeadLetterSuppression + { + public readonly int Id; + public OnComplete(int id) { } + } + public struct OnError : Akka.Actor.INoSerializationVerificationNeeded, Akka.Event.IDeadLetterSuppression + { + public readonly System.Exception Cause; + public readonly int Id; + public OnError(int id, System.Exception cause) { } + } + public struct OnNext : Akka.Actor.INoSerializationVerificationNeeded, Akka.Event.IDeadLetterSuppression + { + public readonly object Element; + public readonly int Id; + public OnNext(int id, object element) { } + } + public struct OnSubscribe : Akka.Actor.INoSerializationVerificationNeeded, Akka.Event.IDeadLetterSuppression + { + public readonly int Id; + public readonly Reactive.Streams.ISubscription Subscription; + public OnSubscribe(int id, Reactive.Streams.ISubscription subscription) { } + } + } + public abstract class FanIn : Akka.Actor.ActorBase, Akka.Streams.Implementation.IPump + { + protected readonly Akka.Streams.Implementation.InputBunch InputBunch; + protected readonly int InputCount; + protected readonly Akka.Streams.Implementation.SimpleOutputs PrimaryOutputs; + protected readonly Akka.Streams.ActorMaterializerSettings Settings; + protected FanIn(Akka.Streams.ActorMaterializerSettings settings, int inputCount) { } + public System.Action CurrentAction { get; set; } + public bool IsPumpFinished { get; } + protected Akka.Event.ILoggingAdapter Log { get; } + public Akka.Streams.Implementation.TransferState TransferState { get; set; } + protected void Fail(System.Exception cause) { } + public void GotUpstreamSubscription() { } + public void InitialPhase(int waitForUpstream, Akka.Streams.Implementation.TransferPhase andThen) { } + public void NextPhase(Akka.Streams.Implementation.TransferPhase phase) { } + protected override void PostRestart(System.Exception reason) { } + protected override void PostStop() { } + public void Pump() { } + public void PumpFailed(System.Exception e) { } + public void PumpFinished() { } + protected override bool Receive(object message) { } + public void WaitForUpstream(int waitForUpstream) { } + public struct SubInput : Reactive.Streams.ISubscriber + { + public SubInput(Akka.Actor.IActorRef impl, int id) { } + public void OnComplete() { } + public void OnError(System.Exception cause) { } + public void OnNext(T element) { } + public void OnSubscribe(Reactive.Streams.ISubscription subscription) { } + } + } + public class static FanOut + { + public struct ExposedPublishers : Akka.Actor.INoSerializationVerificationNeeded, Akka.Event.IDeadLetterSuppression + { + public readonly System.Collections.Immutable.ImmutableList> Publishers; + public ExposedPublishers(System.Collections.Immutable.ImmutableList> publishers) { } + } + public struct SubstreamCancel : Akka.Actor.INoSerializationVerificationNeeded, Akka.Event.IDeadLetterSuppression + { + public readonly int Id; + public SubstreamCancel(int id) { } + } + public struct SubstreamRequestMore : Akka.Actor.INoSerializationVerificationNeeded, Akka.Event.IDeadLetterSuppression + { + public readonly long Demand; + public readonly int Id; + public SubstreamRequestMore(int id, long demand) { } + } + public struct SubstreamSubscribePending : Akka.Actor.INoSerializationVerificationNeeded, Akka.Event.IDeadLetterSuppression + { + public readonly int Id; + public SubstreamSubscribePending(int id) { } + } + public class SubstreamSubscription : Reactive.Streams.ISubscription + { + public SubstreamSubscription(Akka.Actor.IActorRef parent, int id) { } + public void Cancel() { } + public void Request(long elements) { } + public override string ToString() { } + } + } + public abstract class FanOut : Akka.Actor.ActorBase, Akka.Streams.Implementation.IPump + { + protected readonly Akka.Streams.Implementation.OutputBunch OutputBunch; + protected readonly Akka.Streams.Implementation.BatchingInputBuffer PrimaryInputs; + protected FanOut(Akka.Streams.ActorMaterializerSettings settings, int outputCount) { } + public System.Action CurrentAction { get; set; } + public bool IsPumpFinished { get; } + protected Akka.Event.ILoggingAdapter Log { get; } + public Akka.Streams.Implementation.TransferState TransferState { get; set; } + protected void Fail(System.Exception e) { } + public void GotUpstreamSubscription() { } + public void InitialPhase(int waitForUpstream, Akka.Streams.Implementation.TransferPhase andThen) { } + public void NextPhase(Akka.Streams.Implementation.TransferPhase phase) { } + protected override void PostRestart(System.Exception reason) { } + protected override void PostStop() { } + public void Pump() { } + public void PumpFailed(System.Exception e) { } + public void PumpFinished() { } + protected override bool Receive(object message) { } + public void WaitForUpstream(int waitForUpstream) { } + } + public sealed class FirstOrDefaultStage : Akka.Streams.Stage.GraphStageWithMaterializedValue, System.Threading.Tasks.Task> + { + public readonly Akka.Streams.Inlet In; + public FirstOrDefaultStage() { } + public override Akka.Streams.SinkShape Shape { get; } + public override Akka.Streams.Stage.ILogicAndMaterializedValue> CreateLogicAndMaterializedValue(Akka.Streams.Attributes inheritedAttributes) { } + } + public class FlowNameCounter : Akka.Actor.ExtensionIdProvider, Akka.Actor.IExtension + { + public readonly Akka.Util.Internal.AtomicCounterLong Counter; + public FlowNameCounter() { } + public override Akka.Streams.Implementation.FlowNameCounter CreateExtension(Akka.Actor.ExtendedActorSystem system) { } + public static Akka.Streams.Implementation.FlowNameCounter Instance(Akka.Actor.ActorSystem system) { } + } public sealed class FusedModule : Akka.Streams.Implementation.Module { public readonly Akka.Streams.Fusing.StructuralInfo Info; @@ -2145,6 +2420,11 @@ namespace Akka.Streams.Implementation public override string ToString() { } public override Akka.Streams.Implementation.IModule WithAttributes(Akka.Streams.Attributes attributes) { } } + public interface IActorPublisher : Akka.Streams.IUntypedPublisher + { + void Shutdown(System.Exception reason); + System.Collections.Generic.IEnumerable TakePendingSubscribers(); + } public interface IActorSubscription : Reactive.Streams.ISubscription { } public interface ICursor { @@ -2154,6 +2434,36 @@ namespace Akka.Streams.Implementation { System.Collections.Generic.IEnumerable Cursors { get; } } + public sealed class Idle : Akka.Streams.Implementation.Fusing.SimpleLinearGraphStage + { + public readonly System.TimeSpan Timeout; + public Idle(System.TimeSpan timeout) { } + protected override Akka.Streams.Attributes InitialAttributes { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } + public sealed class IdleInject : Akka.Streams.Stage.GraphStage> + where TIn : TOut + { + public IdleInject(System.TimeSpan timeout, System.Func inject) { } + protected override Akka.Streams.Attributes InitialAttributes { get; } + public override Akka.Streams.FlowShape Shape { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } + public sealed class IdleTimeoutBidi : Akka.Streams.Stage.GraphStage> + { + public readonly Akka.Streams.Inlet In1; + public readonly Akka.Streams.Inlet In2; + public readonly Akka.Streams.Outlet Out1; + public readonly Akka.Streams.Outlet Out2; + public readonly System.TimeSpan Timeout; + public IdleTimeoutBidi(System.TimeSpan timeout) { } + protected override Akka.Streams.Attributes InitialAttributes { get; } + public override Akka.Streams.BidiShape Shape { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } public class static IgnorableMaterializedValueComposites { public static bool Apply(Akka.Streams.Implementation.StreamLayout.IMaterializedValueNode composition) { } @@ -2193,7 +2503,94 @@ namespace Akka.Streams.Implementation Akka.Streams.Implementation.IModule Wire(Akka.Streams.OutPort from, Akka.Streams.InPort to); Akka.Streams.Implementation.IModule WithAttributes(Akka.Streams.Attributes attributes); } + public sealed class Initial : Akka.Streams.Implementation.Fusing.SimpleLinearGraphStage + { + public readonly System.TimeSpan Timeout; + public Initial(System.TimeSpan timeout) { } + protected override Akka.Streams.Attributes InitialAttributes { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } + public abstract class InputBunch + { + public readonly Akka.Streams.Implementation.TransferState AllOfMarkedInputs; + public readonly Akka.Streams.Implementation.TransferState AnyOfMarkedInputs; + public readonly Akka.Streams.Implementation.SubReceive SubReceive; + protected InputBunch(int inputCount, int bufferSize, Akka.Streams.Implementation.IPump pump) { } + public bool IsAllCompleted { get; } + protected int LastDequeuedId { get; } + public void Cancel() { } + public void Cancel(int input) { } + public object Dequeue(int id) { } + public object DequeueAndYield() { } + public object DequeueAndYield(int id) { } + public object DequeuePreferring(int preferred) { } + public int IdToDequeue() { } + public Akka.Streams.Implementation.TransferState InputsAvailableFor(int id) { } + public Akka.Streams.Implementation.TransferState InputsOrCompleteAvailableFor(int id) { } + public bool IsCancelled(int index) { } + public bool IsCompleted(int index) { } + public bool IsDepleted(int index) { } + public bool IsPending(int index) { } + public void MarkAllInputs() { } + public void MarkInput(int input) { } + public virtual void OnCompleteWhenNoInput() { } + public virtual void OnDepleted(int input) { } + public abstract void OnError(int id, System.Exception cause); + public void UnmarkAllInputs() { } + public void UnmarkInput(int input) { } + } + public interface IPump + { + System.Action CurrentAction { get; set; } + bool IsPumpFinished { get; } + Akka.Streams.Implementation.TransferState TransferState { get; set; } + void GotUpstreamSubscription(); + void InitialPhase(int waitForUpstream, Akka.Streams.Implementation.TransferPhase andThen); + void NextPhase(Akka.Streams.Implementation.TransferPhase phase); + void Pump(); + void PumpFailed(System.Exception e); + void PumpFinished(); + void WaitForUpstream(int waitForUpstream); + } public interface ISpecViolation { } + public sealed class LastOrDefaultStage : Akka.Streams.Stage.GraphStageWithMaterializedValue, System.Threading.Tasks.Task> + { + public readonly Akka.Streams.Inlet In; + public LastOrDefaultStage() { } + public override Akka.Streams.SinkShape Shape { get; } + public override Akka.Streams.Stage.ILogicAndMaterializedValue> CreateLogicAndMaterializedValue(Akka.Streams.Attributes inheritedAttributes) { } + } + public abstract class MaterializerSession + { + protected readonly Akka.Streams.Attributes InitialAttributes; + public static readonly bool IsDebug; + protected readonly Akka.Streams.Implementation.IModule TopLevel; + protected MaterializerSession(Akka.Streams.Implementation.IModule topLevel, Akka.Streams.Attributes initialAttributes) { } + protected void AssignPort(Akka.Streams.InPort inPort, object subscriberOrVirtual) { } + protected void AssignPort(Akka.Streams.OutPort outPort, Akka.Streams.IUntypedPublisher publisher) { } + protected void EnterScope(Akka.Streams.Implementation.CopiedModule enclosing) { } + protected void ExitScope(Akka.Streams.Implementation.CopiedModule enclosing) { } + public object Materialize() { } + protected abstract object MaterializeAtomic(Akka.Streams.Implementation.AtomicModule atomic, Akka.Streams.Attributes effectiveAttributes, System.Collections.Generic.IDictionary materializedValues); + protected virtual object MaterializeComposite(Akka.Streams.Implementation.IModule composite, Akka.Streams.Attributes effectiveAttributes) { } + protected object MaterializeModule(Akka.Streams.Implementation.IModule module, Akka.Streams.Attributes effectiveAttributes) { } + protected virtual Akka.Streams.Attributes MergeAttributes(Akka.Streams.Attributes parent, Akka.Streams.Attributes current) { } + protected void RegisterSource(Akka.Streams.Implementation.Fusing.IMaterializedValueSource materializedSource) { } + public class MaterializationPanicException : System.Exception + { + public MaterializationPanicException(System.Exception innerException) { } + protected MaterializationPanicException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } + } + } + public sealed class MaybeSource : Akka.Streams.Implementation.SourceModule> + { + public MaybeSource(Akka.Streams.Attributes attributes, Akka.Streams.SourceShape shape) { } + public override Akka.Streams.Attributes Attributes { get; } + public override Reactive.Streams.IPublisher Create(Akka.Streams.MaterializationContext context, out System.Threading.Tasks.TaskCompletionSource<> materializer) { } + protected override Akka.Streams.Implementation.SourceModule> NewInstance(Akka.Streams.SourceShape shape) { } + public override Akka.Streams.Implementation.IModule WithAttributes(Akka.Streams.Attributes attributes) { } + } public abstract class Module : Akka.Streams.Implementation.IModule, System.IComparable { protected Module() { } @@ -2247,6 +2644,81 @@ namespace Akka.Streams.Implementation public static readonly Akka.Streams.Implementation.NothingToReadException Instance; protected NothingToReadException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } } + public class OutputBunch + { + public readonly Akka.Streams.Implementation.TransferState AllOfMarkedOutputs; + public readonly Akka.Streams.Implementation.TransferState AnyOfMarkedOutputs; + public readonly Akka.Streams.Implementation.SubReceive SubReceive; + public OutputBunch(int outputCount, Akka.Actor.IActorRef impl, Akka.Streams.Implementation.IPump pump) { } + public void Cancel(System.Exception e) { } + public void Complete() { } + public void Complete(int output) { } + public Akka.Streams.Implementation.TransferState DemandAvailableFor(int id) { } + public Akka.Streams.Implementation.TransferState DemandOrCancelAvailableFor(int id) { } + public void Enqueue(int id, T element) { } + public void EnqueueAndPrefer(T element, int preferred) { } + public void EnqueueAndYield(T element) { } + public void EnqueueMarked(T element) { } + public void Error(int output, System.Exception e) { } + public int IdToEnqueue() { } + public int IdToEnqueueAndYield() { } + public bool IsCancelled(int output) { } + public bool IsCompleted(int output) { } + public bool IsErrored(int output) { } + public bool IsPending(int output) { } + public void MarkAllOutputs() { } + public void MarkOutput(int output) { } + public void OnCancel(int output) { } + public void UnmarkAllOutputs() { } + public void UnmarkCancelledOutputs(bool enabled) { } + public void UnmarkOutput(int output) { } + } + public sealed class ProcessorModule : Akka.Streams.Implementation.AtomicModule, Akka.Streams.Implementation.IProcessorModule + { + public ProcessorModule(System.Func, TMat>> createProcessor, Akka.Streams.Attributes attributes = null) { } + public override Akka.Streams.Attributes Attributes { get; } + public Akka.Streams.Inlet In { get; } + public Akka.Streams.Outlet Out { get; } + public override Akka.Streams.Shape Shape { get; } + public override Akka.Streams.Implementation.IModule CarbonCopy() { } + public System.Tuple CreateProcessor() { } + public override Akka.Streams.Implementation.IModule ReplaceShape(Akka.Streams.Shape shape) { } + public override Akka.Streams.Implementation.IModule WithAttributes(Akka.Streams.Attributes attributes) { } + } + public sealed class PublisherSource : Akka.Streams.Implementation.SourceModule + { + public PublisherSource(Reactive.Streams.IPublisher publisher, Akka.Streams.Attributes attributes, Akka.Streams.SourceShape shape) { } + public override Akka.Streams.Attributes Attributes { get; } + protected override string Label { get; } + public override Reactive.Streams.IPublisher Create(Akka.Streams.MaterializationContext context, out Akka.NotUsed materializer) { } + protected override Akka.Streams.Implementation.SourceModule NewInstance(Akka.Streams.SourceShape shape) { } + public override Akka.Streams.Implementation.IModule WithAttributes(Akka.Streams.Attributes attributes) { } + } + public sealed class QueueSink : Akka.Streams.Stage.GraphStageWithMaterializedValue, Akka.Streams.ISinkQueue> + { + public readonly Akka.Streams.Inlet In; + public QueueSink() { } + protected override Akka.Streams.Attributes InitialAttributes { get; } + public override Akka.Streams.SinkShape Shape { get; } + public override Akka.Streams.Stage.ILogicAndMaterializedValue> CreateLogicAndMaterializedValue(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } + public sealed class QueueSource : Akka.Streams.Stage.GraphStageWithMaterializedValue, Akka.Streams.ISourceQueueWithComplete> + { + public QueueSource(int maxBuffer, Akka.Streams.OverflowStrategy overflowStrategy) { } + public Akka.Streams.Outlet Out { get; } + public override Akka.Streams.SourceShape Shape { get; } + public override Akka.Streams.Stage.ILogicAndMaterializedValue> CreateLogicAndMaterializedValue(Akka.Streams.Attributes inheritedAttributes) { } + public interface IInput { } + public sealed class Materialized : Akka.Streams.ISourceQueue, Akka.Streams.ISourceQueueWithComplete + { + public Materialized(System.Action.IInput> invokeLogic, System.Threading.Tasks.TaskCompletionSource completion) { } + public void Complete() { } + public void Fail(System.Exception ex) { } + public System.Threading.Tasks.Task OfferAsync(TOut element) { } + public System.Threading.Tasks.Task WatchCompletionAsync() { } + } + } public class static ReactiveStreamsCompliance { public const string CanNotSubscribeTheSameSubscriberMultipleTimes = "can not subscribe the same subscriber multiple times (see reactive-streams specif" + @@ -2296,11 +2768,53 @@ namespace Akka.Streams.Implementation public override string ToString() { } public bool Write(T value) { } } + public sealed class SeqStage : Akka.Streams.Stage.GraphStageWithMaterializedValue, System.Threading.Tasks.Task>> + { + public readonly Akka.Streams.Inlet In; + public SeqStage() { } + protected override Akka.Streams.Attributes InitialAttributes { get; } + public override Akka.Streams.SinkShape Shape { get; } + public override Akka.Streams.Stage.ILogicAndMaterializedValue>> CreateLogicAndMaterializedValue(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } public class SignalThrewException : Akka.Pattern.IllegalStateException, Akka.Streams.Implementation.ISpecViolation { public SignalThrewException(string message, System.Exception cause) { } protected SignalThrewException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } } + public class SimpleOutputs : Akka.Streams.Implementation.IOutputs + { + public readonly Akka.Actor.IActorRef Actor; + protected long DownstreamDemand; + protected Akka.Streams.Implementation.IActorPublisher ExposedPublisher; + protected bool IsDownstreamCompleted; + public readonly Akka.Streams.Implementation.IPump Pump; + protected Akka.Streams.IUntypedSubscriber Subscriber; + public SimpleOutputs(Akka.Actor.IActorRef actor, Akka.Streams.Implementation.IPump pump) { } + public long DemandCount { get; } + public bool IsClosed { get; } + public bool IsDemandAvailable { get; } + public bool IsOpen { get; } + public bool IsSubscribed { get; } + public Akka.Streams.Implementation.TransferState NeedsDemand { get; } + public Akka.Streams.Implementation.TransferState NeedsDemandOrCancel { get; } + public virtual Akka.Streams.Implementation.SubReceive SubReceive { get; } + public virtual void Cancel() { } + public virtual void Complete() { } + protected Reactive.Streams.ISubscription CreateSubscription() { } + protected bool DownstreamRunning(object message) { } + public void EnqueueOutputElement(object element) { } + public virtual void Error(System.Exception e) { } + protected bool WaitingExposedPublisher(object message) { } + } + public sealed class SinkholeSink : Akka.Streams.Implementation.SinkModule + { + public SinkholeSink(Akka.Streams.SinkShape shape, Akka.Streams.Attributes attributes) { } + public override Akka.Streams.Attributes Attributes { get; } + public override object Create(Akka.Streams.MaterializationContext context, out System.Threading.Tasks.Task materializer) { } + protected override Akka.Streams.Implementation.SinkModule NewInstance(Akka.Streams.SinkShape shape) { } + public override Akka.Streams.Implementation.IModule WithAttributes(Akka.Streams.Attributes attributes) { } + } public sealed class SinkholeSubscriber : Reactive.Streams.ISubscriber { public SinkholeSubscriber(System.Threading.Tasks.TaskCompletionSource whenCompleted) { } @@ -2321,6 +2835,18 @@ namespace Akka.Streams.Implementation public override Akka.Streams.Implementation.IModule ReplaceShape(Akka.Streams.Shape shape) { } public virtual string ToString() { } } + public abstract class SourceModule : Akka.Streams.Implementation.AtomicModule, Akka.Streams.Implementation.ISourceModule + { + protected SourceModule(Akka.Streams.SourceShape shape) { } + protected virtual string Label { get; } + public override Akka.Streams.Shape Shape { get; } + protected Akka.Streams.SourceShape AmendShape(Akka.Streams.Attributes attributes) { } + public override Akka.Streams.Implementation.IModule CarbonCopy() { } + public abstract Reactive.Streams.IPublisher Create(Akka.Streams.MaterializationContext context, out TMat materializer); + protected abstract Akka.Streams.Implementation.SourceModule NewInstance(Akka.Streams.SourceShape shape); + public override Akka.Streams.Implementation.IModule ReplaceShape(Akka.Streams.Shape shape) { } + public virtual string ToString() { } + } public class static StreamLayout { public static readonly bool IsDebug; @@ -2403,12 +2929,105 @@ namespace Akka.Streams.Implementation public override Akka.Streams.Dsl.IFlow ViaMaterialized(Akka.Streams.IGraph, TMat2> flow, System.Func combine) { } public Akka.Streams.Implementation.SubFlowImpl WithAttributes(Akka.Streams.Attributes attributes) { } } + public class SubFusingActorMaterializerImpl : Akka.Streams.IMaterializer + { + public SubFusingActorMaterializerImpl(Akka.Streams.Implementation.ExtendedActorMaterializer delegateMaterializer, System.Func registerShell) { } + public Akka.Dispatch.MessageDispatcher ExecutionContext { get; } + public TMat Materialize(Akka.Streams.IGraph runnable) { } + public Akka.Actor.ICancelable ScheduleOnce(System.TimeSpan delay, System.Action action) { } + public Akka.Actor.ICancelable ScheduleRepeatedly(System.TimeSpan initialDelay, System.TimeSpan interval, System.Action action) { } + public Akka.Streams.IMaterializer WithNamePrefix(string namePrefix) { } + } + public class SubReceive + { + public SubReceive(Akka.Actor.Receive initial) { } + public Akka.Actor.Receive CurrentReceive { get; } + public void Become(Akka.Actor.Receive receive) { } + } + public sealed class SubscriberSink : Akka.Streams.Implementation.SinkModule + { + public SubscriberSink(Reactive.Streams.ISubscriber subscriber, Akka.Streams.Attributes attributes, Akka.Streams.SinkShape shape) { } + public override Akka.Streams.Attributes Attributes { get; } + public override object Create(Akka.Streams.MaterializationContext context, out Akka.NotUsed materializer) { } + protected override Akka.Streams.Implementation.SinkModule NewInstance(Akka.Streams.SinkShape shape) { } + public override Akka.Streams.Implementation.IModule WithAttributes(Akka.Streams.Attributes attributes) { } + } + public sealed class SubscriberSource : Akka.Streams.Implementation.SourceModule> + { + public SubscriberSource(Akka.Streams.Attributes attributes, Akka.Streams.SourceShape shape) { } + public override Akka.Streams.Attributes Attributes { get; } + public override Reactive.Streams.IPublisher Create(Akka.Streams.MaterializationContext context, out Reactive.Streams.ISubscriber<> materializer) { } + protected override Akka.Streams.Implementation.SourceModule> NewInstance(Akka.Streams.SourceShape shape) { } + public override Akka.Streams.Implementation.IModule WithAttributes(Akka.Streams.Attributes attributes) { } + } public class SubscriptionTimeoutException : System.Exception { public SubscriptionTimeoutException(string message) { } public SubscriptionTimeoutException(string message, System.Exception innerException) { } protected SubscriptionTimeoutException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } } + public class Throttle : Akka.Streams.Implementation.Fusing.SimpleLinearGraphStage + { + public Throttle(int cost, System.TimeSpan per, int maximumBurst, System.Func costCalculation, Akka.Streams.ThrottleMode mode) { } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } + public class static Timers + { + public const string GraphStageLogicTimer = "GraphStageLogicTimer"; + public static System.TimeSpan IdleTimeoutCheckInterval(System.TimeSpan timeout) { } + } + public struct TransferPhase + { + public readonly System.Action Action; + public readonly Akka.Streams.Implementation.TransferState Precondition; + public TransferPhase(Akka.Streams.Implementation.TransferState precondition, System.Action action) { } + } + public abstract class TransferState + { + protected TransferState() { } + public abstract bool IsCompleted { get; } + public bool IsExecutable { get; } + public abstract bool IsReady { get; } + public Akka.Streams.Implementation.TransferState And(Akka.Streams.Implementation.TransferState other) { } + public Akka.Streams.Implementation.TransferState Or(Akka.Streams.Implementation.TransferState other) { } + } + public class Unfold : Akka.Streams.Stage.GraphStage> + { + public readonly Akka.Streams.Outlet Out; + public readonly TState State; + public readonly System.Func> UnfoldFunc; + public Unfold(TState state, System.Func> unfoldFunc) { } + public override Akka.Streams.SourceShape Shape { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + } + public class UnfoldAsync : Akka.Streams.Stage.GraphStage> + { + public readonly Akka.Streams.Outlet Out; + public readonly TState State; + public readonly System.Func>> UnfoldFunc; + public UnfoldAsync(TState state, System.Func>> unfoldFunc) { } + public override Akka.Streams.SourceShape Shape { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + } + public sealed class UnfoldResourceSource : Akka.Streams.Stage.GraphStage> + { + public UnfoldResourceSource(System.Func create, System.Func> readData, System.Action close) { } + protected override Akka.Streams.Attributes InitialAttributes { get; } + public Akka.Streams.Outlet Out { get; } + public override Akka.Streams.SourceShape Shape { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } + public sealed class UnfoldResourceSourceAsync : Akka.Streams.Stage.GraphStage> + { + public UnfoldResourceSourceAsync(System.Func> create, System.Func>> readData, System.Func close) { } + protected override Akka.Streams.Attributes InitialAttributes { get; } + public Akka.Streams.Outlet Out { get; } + public override Akka.Streams.SourceShape Shape { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } public sealed class VirtualProcessor : Akka.Util.AtomicReference, Reactive.Streams.IProcessor, Reactive.Streams.IPublisher, Reactive.Streams.ISubscriber { public VirtualProcessor() { } @@ -2421,6 +3040,189 @@ namespace Akka.Streams.Implementation } namespace Akka.Streams.Implementation.Fusing { + public class ActorGraphInterpreter : Akka.Actor.ActorBase + { + public ActorGraphInterpreter(Akka.Streams.Implementation.Fusing.GraphInterpreterShell shell) { } + public Akka.Event.ILoggingAdapter Log { get; } + protected override void PostStop() { } + protected override void PreStart() { } + public static Akka.Actor.Props Props(Akka.Streams.Implementation.Fusing.GraphInterpreterShell shell) { } + protected override bool Receive(object message) { } + public Akka.Actor.IActorRef RegisterShell(Akka.Streams.Implementation.Fusing.GraphInterpreterShell shell) { } + public struct Abort : Akka.Actor.INoSerializationVerificationNeeded, Akka.Event.IDeadLetterSuppression, Akka.Streams.Implementation.Fusing.ActorGraphInterpreter.IBoundaryEvent + { + public Abort(Akka.Streams.Implementation.Fusing.GraphInterpreterShell shell) { } + public Akka.Streams.Implementation.Fusing.GraphInterpreterShell Shell { get; } + } + public struct AsyncInput : Akka.Actor.INoSerializationVerificationNeeded, Akka.Event.IDeadLetterSuppression, Akka.Streams.Implementation.Fusing.ActorGraphInterpreter.IBoundaryEvent + { + public readonly object Event; + public readonly System.Action Handler; + public readonly Akka.Streams.Stage.GraphStageLogic Logic; + public AsyncInput(Akka.Streams.Implementation.Fusing.GraphInterpreterShell shell, Akka.Streams.Stage.GraphStageLogic logic, object @event, System.Action handler) { } + public Akka.Streams.Implementation.Fusing.GraphInterpreterShell Shell { get; } + } + public class BatchingActorInputBoundary : Akka.Streams.Implementation.Fusing.GraphInterpreter.UpstreamBoundaryStageLogic + { + public BatchingActorInputBoundary(int size, int id) { } + public override Akka.Streams.Outlet Out { get; } + public void Cancel() { } + public void OnComplete() { } + public void OnError(System.Exception reason) { } + public void OnInternalError(System.Exception reason) { } + public void OnNext(object element) { } + public void OnSubscribe(Reactive.Streams.ISubscription subscription) { } + public override string ToString() { } + } + public sealed class BoundaryPublisher : Akka.Streams.Implementation.ActorPublisher + { + public BoundaryPublisher(Akka.Actor.IActorRef parent, Akka.Streams.Implementation.Fusing.GraphInterpreterShell shell, int id) { } + protected override object WakeUpMessage { get; } + } + public sealed class BoundarySubscriber : Reactive.Streams.ISubscriber + { + public BoundarySubscriber(Akka.Actor.IActorRef parent, Akka.Streams.Implementation.Fusing.GraphInterpreterShell shell, int id) { } + public void OnComplete() { } + public void OnError(System.Exception cause) { } + public void OnNext(T element) { } + public void OnSubscribe(Reactive.Streams.ISubscription subscription) { } + } + public sealed class BoundarySubscription : Reactive.Streams.ISubscription + { + public BoundarySubscription(Akka.Actor.IActorRef parent, Akka.Streams.Implementation.Fusing.GraphInterpreterShell shell, int id) { } + public void Cancel() { } + public void Request(long elements) { } + public override string ToString() { } + } + public struct Cancel : Akka.Actor.INoSerializationVerificationNeeded, Akka.Event.IDeadLetterSuppression, Akka.Streams.Implementation.Fusing.ActorGraphInterpreter.IBoundaryEvent + { + public readonly int Id; + public Cancel(Akka.Streams.Implementation.Fusing.GraphInterpreterShell shell, int id) { } + public Akka.Streams.Implementation.Fusing.GraphInterpreterShell Shell { get; } + } + public struct ExposedPublisher : Akka.Actor.INoSerializationVerificationNeeded, Akka.Event.IDeadLetterSuppression, Akka.Streams.Implementation.Fusing.ActorGraphInterpreter.IBoundaryEvent + { + public readonly int Id; + public readonly Akka.Streams.Implementation.IActorPublisher Publisher; + public ExposedPublisher(Akka.Streams.Implementation.Fusing.GraphInterpreterShell shell, int id, Akka.Streams.Implementation.IActorPublisher publisher) { } + public Akka.Streams.Implementation.Fusing.GraphInterpreterShell Shell { get; } + } + public interface IBoundaryEvent : Akka.Actor.INoSerializationVerificationNeeded, Akka.Event.IDeadLetterSuppression + { + Akka.Streams.Implementation.Fusing.GraphInterpreterShell Shell { get; } + } + public struct OnComplete : Akka.Actor.INoSerializationVerificationNeeded, Akka.Event.IDeadLetterSuppression, Akka.Streams.Implementation.Fusing.ActorGraphInterpreter.IBoundaryEvent + { + public readonly int Id; + public OnComplete(Akka.Streams.Implementation.Fusing.GraphInterpreterShell shell, int id) { } + public Akka.Streams.Implementation.Fusing.GraphInterpreterShell Shell { get; } + } + public struct OnError : Akka.Actor.INoSerializationVerificationNeeded, Akka.Event.IDeadLetterSuppression, Akka.Streams.Implementation.Fusing.ActorGraphInterpreter.IBoundaryEvent + { + public readonly System.Exception Cause; + public readonly int Id; + public OnError(Akka.Streams.Implementation.Fusing.GraphInterpreterShell shell, int id, System.Exception cause) { } + public Akka.Streams.Implementation.Fusing.GraphInterpreterShell Shell { get; } + } + public struct OnNext : Akka.Actor.INoSerializationVerificationNeeded, Akka.Event.IDeadLetterSuppression, Akka.Streams.Implementation.Fusing.ActorGraphInterpreter.IBoundaryEvent + { + public readonly object Event; + public readonly int Id; + public OnNext(Akka.Streams.Implementation.Fusing.GraphInterpreterShell shell, int id, object @event) { } + public Akka.Streams.Implementation.Fusing.GraphInterpreterShell Shell { get; } + } + public struct OnSubscribe : Akka.Actor.INoSerializationVerificationNeeded, Akka.Event.IDeadLetterSuppression, Akka.Streams.Implementation.Fusing.ActorGraphInterpreter.IBoundaryEvent + { + public readonly int Id; + public readonly Reactive.Streams.ISubscription Subscription; + public OnSubscribe(Akka.Streams.Implementation.Fusing.GraphInterpreterShell shell, int id, Reactive.Streams.ISubscription subscription) { } + public Akka.Streams.Implementation.Fusing.GraphInterpreterShell Shell { get; } + } + public struct RequestMore : Akka.Actor.INoSerializationVerificationNeeded, Akka.Event.IDeadLetterSuppression, Akka.Streams.Implementation.Fusing.ActorGraphInterpreter.IBoundaryEvent + { + public readonly long Demand; + public readonly int Id; + public RequestMore(Akka.Streams.Implementation.Fusing.GraphInterpreterShell shell, int id, long demand) { } + public Akka.Streams.Implementation.Fusing.GraphInterpreterShell Shell { get; } + } + public struct Resume : Akka.Actor.INoSerializationVerificationNeeded, Akka.Event.IDeadLetterSuppression, Akka.Streams.Implementation.Fusing.ActorGraphInterpreter.IBoundaryEvent + { + public Resume(Akka.Streams.Implementation.Fusing.GraphInterpreterShell shell) { } + public Akka.Streams.Implementation.Fusing.GraphInterpreterShell Shell { get; } + } + public struct SubscribePending : Akka.Actor.INoSerializationVerificationNeeded, Akka.Event.IDeadLetterSuppression, Akka.Streams.Implementation.Fusing.ActorGraphInterpreter.IBoundaryEvent + { + public readonly int Id; + public SubscribePending(Akka.Streams.Implementation.Fusing.GraphInterpreterShell shell, int id) { } + public Akka.Streams.Implementation.Fusing.GraphInterpreterShell Shell { get; } + } + } + public sealed class Aggregate : Akka.Streams.Stage.GraphStage> + { + public Aggregate(TOut zero, System.Func aggregate) { } + public Akka.Streams.Inlet In { get; } + protected override Akka.Streams.Attributes InitialAttributes { get; } + public Akka.Streams.Outlet Out { get; } + public override Akka.Streams.FlowShape Shape { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } + public sealed class Batch : Akka.Streams.Stage.GraphStage> + { + public Batch(long max, System.Func costFunc, System.Func seed, System.Func aggregate) { } + public override Akka.Streams.FlowShape Shape { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + } + public sealed class Buffer : Akka.Streams.Stage.DetachedStage + { + public Buffer(int count, Akka.Streams.OverflowStrategy overflowStrategy) { } + public override Akka.Streams.Stage.IDownstreamDirective OnPull(Akka.Streams.Stage.IDetachedContext context) { } + public override Akka.Streams.Stage.IUpstreamDirective OnPush(T element, Akka.Streams.Stage.IDetachedContext context) { } + public override Akka.Streams.Stage.ITerminationDirective OnUpstreamFinish(Akka.Streams.Stage.IDetachedContext context) { } + public override void PreStart(Akka.Streams.Stage.ILifecycleContext context) { } + } + public sealed class Collect : Akka.Streams.Stage.GraphStage> + { + public Collect(System.Func func) { } + public Akka.Streams.Inlet In { get; } + protected override Akka.Streams.Attributes InitialAttributes { get; } + public Akka.Streams.Outlet Out { get; } + public override Akka.Streams.FlowShape Shape { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } + public sealed class Delay : Akka.Streams.Implementation.Fusing.SimpleLinearGraphStage + { + public Delay(System.TimeSpan delay, Akka.Streams.DelayOverflowStrategy strategy) { } + protected override Akka.Streams.Attributes InitialAttributes { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } + public sealed class Detacher : Akka.Streams.Stage.GraphStage> + { + public readonly Akka.Streams.Inlet Inlet; + public readonly Akka.Streams.Outlet Outlet; + public Detacher() { } + protected override Akka.Streams.Attributes InitialAttributes { get; } + public override Akka.Streams.FlowShape Shape { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } + public sealed class Drop : Akka.Streams.Implementation.Fusing.SimpleLinearGraphStage + { + public Drop(long count) { } + protected override Akka.Streams.Attributes InitialAttributes { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } + public sealed class Expand : Akka.Streams.Stage.GraphStage> + { + public Expand(System.Func> extrapolate) { } + protected override Akka.Streams.Attributes InitialAttributes { get; } + public override Akka.Streams.FlowShape Shape { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } public sealed class GraphAssembly { public readonly int[] InletOwners; @@ -2504,10 +3306,70 @@ namespace Akka.Streams.Implementation.Fusing public abstract Akka.Streams.Outlet Out { get; } } } + public sealed class GraphInterpreterShell + { + public GraphInterpreterShell(Akka.Streams.Implementation.Fusing.GraphAssembly assembly, Akka.Streams.Stage.IInHandler[] inHandlers, Akka.Streams.Stage.IOutHandler[] outHandlers, Akka.Streams.Stage.GraphStageLogic[] logics, Akka.Streams.Shape shape, Akka.Streams.ActorMaterializerSettings settings, Akka.Streams.Implementation.ExtendedActorMaterializer materializer) { } + public bool CanShutdown { get; } + public Akka.Streams.Implementation.Fusing.GraphInterpreter Interpreter { get; } + public bool IsInitialized { get; } + public bool IsTerminated { get; } + public Akka.Event.ILoggingAdapter Log { get; } + public Akka.Actor.IActorRef Self { get; } + public int Init(Akka.Actor.IActorRef self, Akka.Streams.Implementation.SubFusingActorMaterializerImpl subMat, System.Action enqueueToShourtCircuit, int eventLimit) { } + public int Receive(Akka.Streams.Implementation.Fusing.ActorGraphInterpreter.IBoundaryEvent e, int eventLimit) { } + public override string ToString() { } + public void TryAbort(System.Exception reason) { } + } + public sealed class GraphModule : Akka.Streams.Implementation.AtomicModule + { + public readonly Akka.Streams.Implementation.Fusing.GraphAssembly Assembly; + public readonly Akka.Streams.Implementation.IModule[] MaterializedValueIds; + public GraphModule(Akka.Streams.Implementation.Fusing.GraphAssembly assembly, Akka.Streams.Shape shape, Akka.Streams.Attributes attributes, Akka.Streams.Implementation.IModule[] materializedValueIds) { } + public override Akka.Streams.Attributes Attributes { get; } + public override Akka.Streams.Shape Shape { get; } + public override Akka.Streams.Implementation.IModule CarbonCopy() { } + public override Akka.Streams.Implementation.IModule ReplaceShape(Akka.Streams.Shape newShape) { } + public override string ToString() { } + public override Akka.Streams.Implementation.IModule WithAttributes(Akka.Streams.Attributes attributes) { } + } + public class GraphStageModule : Akka.Streams.Implementation.AtomicModule + { + public readonly Akka.Streams.Stage.IGraphStageWithMaterializedValue Stage; + public GraphStageModule(Akka.Streams.Shape shape, Akka.Streams.Attributes attributes, Akka.Streams.Stage.IGraphStageWithMaterializedValue stage) { } + public override Akka.Streams.Attributes Attributes { get; } + public override Akka.Streams.Shape Shape { get; } + public override Akka.Streams.Implementation.IModule CarbonCopy() { } + public override Akka.Streams.Implementation.IModule ReplaceShape(Akka.Streams.Shape shape) { } + public override string ToString() { } + public override Akka.Streams.Implementation.IModule WithAttributes(Akka.Streams.Attributes attributes) { } + } public class static GraphStages { public static Akka.Streams.Implementation.Fusing.SimpleLinearGraphStage Identity() { } } + public sealed class Grouped : Akka.Streams.Stage.GraphStage>> + { + public Grouped(int count) { } + public Akka.Streams.Inlet In { get; } + protected override Akka.Streams.Attributes InitialAttributes { get; } + public Akka.Streams.Outlet> Out { get; } + public override Akka.Streams.FlowShape> Shape { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } + public sealed class GroupedWithin : Akka.Streams.Stage.GraphStage>> + { + public GroupedWithin(int count, System.TimeSpan timeout) { } + protected override Akka.Streams.Attributes InitialAttributes { get; } + public override Akka.Streams.FlowShape> Shape { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + } + public sealed class Identity : Akka.Streams.Implementation.Fusing.SimpleLinearGraphStage + { + public static readonly Akka.Streams.Implementation.Fusing.Identity Instance; + protected override Akka.Streams.Attributes InitialAttributes { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + } public interface IMaterializedValueSource { Akka.Streams.Implementation.StreamLayout.IMaterializedValueNode Computation { get; } @@ -2516,6 +3378,103 @@ namespace Akka.Streams.Implementation.Fusing Akka.Streams.Implementation.Fusing.IMaterializedValueSource CopySource(); void SetValue(object result); } + public sealed class Intersperse : Akka.Streams.Stage.GraphStage> + { + public readonly Akka.Streams.Inlet In; + public readonly Akka.Streams.Outlet Out; + public Intersperse(T inject) { } + public Intersperse(T start, T inject, T end) { } + public bool InjectStartEnd { get; } + public override Akka.Streams.FlowShape Shape { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + } + public sealed class LimitWeighted : Akka.Streams.Stage.GraphStage> + { + public LimitWeighted(long max, System.Func costFunc) { } + public Akka.Streams.Inlet In { get; } + protected override Akka.Streams.Attributes InitialAttributes { get; } + public Akka.Streams.Outlet Out { get; } + public override Akka.Streams.FlowShape Shape { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } + public sealed class Log : Akka.Streams.Implementation.Fusing.SimpleLinearGraphStage + { + public Log(string name, System.Func extract, Akka.Event.ILoggingAdapter adapter) { } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } + public sealed class MaterializedValueSource : Akka.Streams.Stage.GraphStage>, Akka.Streams.Implementation.Fusing.IMaterializedValueSource + { + public readonly Akka.Streams.Outlet Outlet; + public MaterializedValueSource(Akka.Streams.Implementation.StreamLayout.IMaterializedValueNode computation, Akka.Streams.Outlet outlet) { } + public MaterializedValueSource(Akka.Streams.Implementation.StreamLayout.IMaterializedValueNode computation) { } + public Akka.Streams.Implementation.StreamLayout.IMaterializedValueNode Computation { get; } + protected override Akka.Streams.Attributes InitialAttributes { get; } + public override Akka.Streams.SourceShape Shape { get; } + public Akka.Streams.Implementation.Fusing.MaterializedValueSource CopySource() { } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public void SetValue(T value) { } + public override string ToString() { } + } + public sealed class OnCompleted : Akka.Streams.Stage.PushStage + { + public OnCompleted(System.Action success, System.Action failure) { } + public override Akka.Streams.Stage.ISyncDirective OnPush(TIn element, Akka.Streams.Stage.IContext context) { } + public override Akka.Streams.Stage.ITerminationDirective OnUpstreamFailure(System.Exception cause, Akka.Streams.Stage.IContext context) { } + public override Akka.Streams.Stage.ITerminationDirective OnUpstreamFinish(Akka.Streams.Stage.IContext context) { } + } + public sealed class Recover : Akka.Streams.Stage.GraphStage> + { + public Recover(System.Func> recovery) { } + public Akka.Streams.Inlet In { get; } + protected override Akka.Streams.Attributes InitialAttributes { get; } + public Akka.Streams.Outlet Out { get; } + public override Akka.Streams.FlowShape Shape { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } + public sealed class RecoverWith : Akka.Streams.Implementation.Fusing.SimpleLinearGraphStage + { + public RecoverWith(System.Func, TMat>> partialFunction, int maximumRetries) { } + protected override Akka.Streams.Attributes InitialAttributes { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } + public sealed class Scan : Akka.Streams.Stage.GraphStage> + { + public Scan(TOut zero, System.Func aggregate) { } + public Akka.Streams.Inlet In { get; } + protected override Akka.Streams.Attributes InitialAttributes { get; } + public Akka.Streams.Outlet Out { get; } + public override Akka.Streams.FlowShape Shape { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } + public sealed class Select : Akka.Streams.Stage.PushStage + { + public Select(System.Func func, Akka.Streams.Supervision.Decider decider) { } + public override Akka.Streams.Supervision.Directive Decide(System.Exception cause) { } + public override Akka.Streams.Stage.ISyncDirective OnPush(TIn element, Akka.Streams.Stage.IContext context) { } + } + public sealed class SelectAsync : Akka.Streams.Stage.GraphStage> + { + public readonly Akka.Streams.Inlet In; + public readonly Akka.Streams.Outlet Out; + public SelectAsync(int parallelism, System.Func> mapFunc) { } + protected override Akka.Streams.Attributes InitialAttributes { get; } + public override Akka.Streams.FlowShape Shape { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + } + public sealed class SelectAsyncUnordered : Akka.Streams.Stage.GraphStage> + { + public readonly Akka.Streams.Inlet In; + public readonly Akka.Streams.Outlet Out; + public SelectAsyncUnordered(int parallelism, System.Func> mapFunc) { } + protected override Akka.Streams.Attributes InitialAttributes { get; } + public override Akka.Streams.FlowShape Shape { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + } public abstract class SimpleLinearGraphStage : Akka.Streams.Stage.GraphStage> { public readonly Akka.Streams.Inlet Inlet; @@ -2523,6 +3482,257 @@ namespace Akka.Streams.Implementation.Fusing protected SimpleLinearGraphStage() { } public override Akka.Streams.FlowShape Shape { get; } } + public sealed class SingleSource : Akka.Streams.Stage.GraphStage> + { + public readonly Akka.Streams.Outlet Outlet; + public SingleSource(T element) { } + public override Akka.Streams.SourceShape Shape { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + } + public sealed class SkipWhile : Akka.Streams.Stage.GraphStage> + { + public SkipWhile(System.Predicate predicate) { } + public Akka.Streams.Inlet In { get; } + protected override Akka.Streams.Attributes InitialAttributes { get; } + public Akka.Streams.Outlet Out { get; } + public override Akka.Streams.FlowShape Shape { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } + public sealed class SkipWithin : Akka.Streams.Implementation.Fusing.SimpleLinearGraphStage + { + public SkipWithin(System.TimeSpan timeout) { } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + } + public sealed class Sliding : Akka.Streams.Stage.GraphStage>> + { + public Sliding(int count, int step) { } + public Akka.Streams.Inlet In { get; } + protected override Akka.Streams.Attributes InitialAttributes { get; } + public Akka.Streams.Outlet> Out { get; } + public override Akka.Streams.FlowShape> Shape { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } + public sealed class StatefulSelectMany : Akka.Streams.Stage.GraphStage> + { + public StatefulSelectMany(System.Func>> concatFactory) { } + protected override Akka.Streams.Attributes InitialAttributes { get; } + public override Akka.Streams.FlowShape Shape { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } + public sealed class Sum : Akka.Streams.Implementation.Fusing.SimpleLinearGraphStage + { + public Sum(System.Func reduce) { } + protected override Akka.Streams.Attributes InitialAttributes { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } + public abstract class SupervisedGraphStageLogic : Akka.Streams.Stage.GraphStageLogic + { + protected SupervisedGraphStageLogic(Akka.Streams.Attributes inheritedAttributes, Akka.Streams.Shape shape) { } + protected virtual void OnRestart(System.Exception ex) { } + protected virtual void OnResume(System.Exception ex) { } + protected virtual void OnStop(System.Exception ex) { } + protected Akka.Streams.Util.Option WithSupervision(System.Func function) { } + } + public sealed class Take : Akka.Streams.Implementation.Fusing.SimpleLinearGraphStage + { + public Take(long count) { } + protected override Akka.Streams.Attributes InitialAttributes { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } + public sealed class TakeWhile : Akka.Streams.Implementation.Fusing.SimpleLinearGraphStage + { + public TakeWhile(System.Predicate predicate) { } + protected override Akka.Streams.Attributes InitialAttributes { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } + public sealed class TakeWithin : Akka.Streams.Implementation.Fusing.SimpleLinearGraphStage + { + public TakeWithin(System.TimeSpan timeout) { } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + } + public sealed class TaskSource : Akka.Streams.Stage.GraphStage> + { + public readonly Akka.Streams.Outlet Outlet; + public TaskSource(System.Threading.Tasks.Task task) { } + public override Akka.Streams.SourceShape Shape { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } + public sealed class TickSource : Akka.Streams.Stage.GraphStageWithMaterializedValue, Akka.Actor.ICancelable> + { + public TickSource(System.TimeSpan initialDelay, System.TimeSpan interval, T tick) { } + protected override Akka.Streams.Attributes InitialAttributes { get; } + public Akka.Streams.Outlet Out { get; } + public override Akka.Streams.SourceShape Shape { get; } + public override Akka.Streams.Stage.ILogicAndMaterializedValue CreateLogicAndMaterializedValue(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } + public sealed class Where : Akka.Streams.Implementation.Fusing.SimpleLinearGraphStage + { + public Where(System.Predicate predicate) { } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } +} +namespace Akka.Streams.Implementation.IO +{ + public class IncomingConnectionStage : Akka.Streams.Stage.GraphStage> + { + public IncomingConnectionStage(Akka.Actor.IActorRef connection, System.Net.EndPoint remoteAddress, bool halfClose) { } + protected override Akka.Streams.Attributes InitialAttributes { get; } + public override Akka.Streams.FlowShape Shape { get; } + protected override Akka.Streams.Stage.GraphStageLogic CreateLogic(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } +} +namespace Akka.Streams.Implementation.Stages +{ + public sealed class Buffer : Akka.Streams.Implementation.Stages.SymbolicStage + { + public Buffer(int size, Akka.Streams.OverflowStrategy overflowStrategy, Akka.Streams.Attributes attributes = null) { } + public override Akka.Streams.Stage.IStage Create(Akka.Streams.Attributes effectiveAttributes) { } + } + public class static DefaultAttributes + { + public static readonly Akka.Streams.Attributes ActorPublisherSource; + public static readonly Akka.Streams.Attributes ActorRefSink; + public static readonly Akka.Streams.Attributes ActorRefSource; + public static readonly Akka.Streams.Attributes ActorRefWithAck; + public static readonly Akka.Streams.Attributes ActorSubscriberSink; + public static readonly Akka.Streams.Attributes Aggregate; + public static readonly Akka.Streams.Attributes BackpressureTimeout; + public static readonly Akka.Streams.Attributes Balance; + public static readonly Akka.Streams.Attributes Batch; + public static readonly Akka.Streams.Attributes BatchWeighted; + public static readonly Akka.Streams.Attributes Broadcast; + public static readonly Akka.Streams.Attributes Buffer; + public static readonly Akka.Streams.Attributes CancelledSink; + public static readonly Akka.Streams.Attributes Collect; + public static readonly Akka.Streams.Attributes Completion; + public static readonly Akka.Streams.Attributes Concat; + public static readonly Akka.Streams.Attributes ConcatAll; + public static readonly Akka.Streams.Attributes ConcatMaterializedSource; + public static readonly Akka.Streams.Attributes ConcatSource; + public static readonly Akka.Streams.Attributes Conflate; + public static readonly Akka.Streams.Attributes CycledSource; + public static readonly Akka.Streams.Attributes Delay; + public static readonly Akka.Streams.Attributes DelayInitial; + public static readonly Akka.Streams.Attributes DelimiterFraming; + public static readonly Akka.Streams.Attributes Drop; + public static readonly Akka.Streams.Attributes EmptySource; + public static readonly Akka.Streams.Attributes EnumerableSource; + public static readonly Akka.Streams.Attributes Expand; + public static readonly Akka.Streams.Attributes FailedSource; + public static readonly Akka.Streams.Attributes FanoutPublisherSink; + public static readonly Akka.Streams.Attributes FileSink; + public static readonly Akka.Streams.Attributes FileSource; + public static readonly Akka.Streams.Attributes FirstOrDefaultSink; + public static readonly Akka.Streams.Attributes FirstSink; + public static readonly Akka.Streams.Attributes FlattenMerge; + public static readonly Akka.Streams.Attributes Fused; + public static readonly Akka.Streams.Attributes GroupBy; + public static readonly Akka.Streams.Attributes Grouped; + public static readonly Akka.Streams.Attributes IdentityOp; + public static readonly Akka.Streams.Attributes Idle; + public static readonly Akka.Streams.Attributes IdleInject; + public static readonly Akka.Streams.Attributes IdleTimeoutBidi; + public static readonly Akka.Streams.Attributes IgnoreSink; + public static readonly Akka.Streams.Attributes Initial; + public static readonly Akka.Streams.Attributes InputStreamSink; + public static readonly Akka.Streams.Attributes InputStreamSource; + public static readonly Akka.Streams.Attributes IODispatcher; + public static readonly Akka.Streams.Attributes LastOrDefaultSink; + public static readonly Akka.Streams.Attributes LastSink; + public static readonly Akka.Streams.Attributes LazySink; + public static readonly Akka.Streams.Attributes Limit; + public static readonly Akka.Streams.Attributes LimitWeighted; + public static readonly Akka.Streams.Attributes Log; + public static readonly Akka.Streams.Attributes MapAsync; + public static readonly Akka.Streams.Attributes MapAsyncUnordered; + public static readonly Akka.Streams.Attributes MaybeSource; + public static readonly Akka.Streams.Attributes Merge; + public static readonly Akka.Streams.Attributes MergePreferred; + public static readonly Akka.Streams.Attributes OutputStreamSink; + public static readonly Akka.Streams.Attributes OutputStreamSource; + public static readonly Akka.Streams.Attributes PrefixAndTail; + public static readonly Akka.Streams.Attributes Processor; + public static readonly Akka.Streams.Attributes ProcessorWithKey; + public static readonly Akka.Streams.Attributes PublisherSink; + public static readonly Akka.Streams.Attributes PublisherSource; + public static readonly Akka.Streams.Attributes QueueSink; + public static readonly Akka.Streams.Attributes QueueSource; + public static readonly Akka.Streams.Attributes Recover; + public static readonly Akka.Streams.Attributes RecoverWith; + public static readonly Akka.Streams.Attributes Repeat; + public static readonly Akka.Streams.Attributes Scan; + public static readonly Akka.Streams.Attributes Select; + public static readonly Akka.Streams.Attributes SeqSink; + public static readonly Akka.Streams.Attributes SingleSource; + public static readonly Akka.Streams.Attributes Skip; + public static readonly Akka.Streams.Attributes SkipWhile; + public static readonly Akka.Streams.Attributes Sliding; + public static readonly Akka.Streams.Attributes Split; + public static readonly Akka.Streams.Attributes StatefulSelectMany; + public static readonly Akka.Streams.Attributes SubscriberSink; + public static readonly Akka.Streams.Attributes SubscriberSource; + public static readonly Akka.Streams.Attributes Sum; + public static readonly Akka.Streams.Attributes Take; + public static readonly Akka.Streams.Attributes TakeWhile; + public static readonly Akka.Streams.Attributes TaskSource; + public static readonly Akka.Streams.Attributes TerminationWatcher; + public static readonly Akka.Streams.Attributes TickSource; + public static readonly Akka.Streams.Attributes Unfold; + public static readonly Akka.Streams.Attributes UnfoldAsync; + public static readonly Akka.Streams.Attributes UnfoldInf; + public static readonly Akka.Streams.Attributes UnfoldResourceSource; + public static readonly Akka.Streams.Attributes UnfoldResourceSourceAsync; + public static readonly Akka.Streams.Attributes Unzip; + public static readonly Akka.Streams.Attributes Where; + public static readonly Akka.Streams.Attributes Zip; + public static readonly Akka.Streams.Attributes ZipN; + public static readonly Akka.Streams.Attributes ZipWithN; + } + public sealed class FirstOrDefault : Akka.Streams.Stage.GraphStageWithMaterializedValue, System.Threading.Tasks.Task> + { + public FirstOrDefault(bool throwOnDefault = False) { } + public override Akka.Streams.SinkShape Shape { get; } + public override Akka.Streams.Stage.ILogicAndMaterializedValue> CreateLogicAndMaterializedValue(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } + public interface ISymbolicStage : Akka.Streams.Stage.IStage + { + Akka.Streams.Attributes Attributes { get; } + Akka.Streams.Stage.IStage Create(Akka.Streams.Attributes effectiveAttributes); + } + public sealed class LastOrDefault : Akka.Streams.Stage.GraphStageWithMaterializedValue, System.Threading.Tasks.Task> + { + public LastOrDefault(bool throwOnDefault = False) { } + public override Akka.Streams.SinkShape Shape { get; } + public override Akka.Streams.Stage.ILogicAndMaterializedValue> CreateLogicAndMaterializedValue(Akka.Streams.Attributes inheritedAttributes) { } + public override string ToString() { } + } + public sealed class Select : Akka.Streams.Implementation.Stages.SymbolicStage + { + public Select(System.Func mapper, Akka.Streams.Attributes attributes = null) { } + public override Akka.Streams.Stage.IStage Create(Akka.Streams.Attributes effectiveAttributes) { } + } + public sealed class SymbolicGraphStage : Akka.Streams.Stage.PushPullGraphStage + { + public SymbolicGraphStage(Akka.Streams.Implementation.Stages.ISymbolicStage symbolicStage) { } + } + public abstract class SymbolicStage : Akka.Streams.Implementation.Stages.ISymbolicStage, Akka.Streams.Stage.IStage + { + protected SymbolicStage(Akka.Streams.Attributes attributes) { } + public Akka.Streams.Attributes Attributes { get; } + public abstract Akka.Streams.Stage.IStage Create(Akka.Streams.Attributes effectiveAttributes); + protected Akka.Streams.Supervision.Decider Supervision(Akka.Streams.Attributes attributes) { } + } } namespace Akka.Streams.IO { diff --git a/src/core/Akka.Streams.Tests/Actor/ActorPublisherSpec.cs b/src/core/Akka.Streams.Tests/Actor/ActorPublisherSpec.cs index dd390e14c25..5a770400a1a 100644 --- a/src/core/Akka.Streams.Tests/Actor/ActorPublisherSpec.cs +++ b/src/core/Akka.Streams.Tests/Actor/ActorPublisherSpec.cs @@ -15,12 +15,15 @@ using Akka.Pattern; using Akka.Streams.Actors; using Akka.Streams.Dsl; +using Akka.Streams.Implementation; using Akka.Streams.TestKit; using Akka.Streams.TestKit.Tests; using Akka.TestKit; using FluentAssertions; using Xunit; using Xunit.Abstractions; +using ActorPublisher = Akka.Streams.Actors.ActorPublisher; +using Cancel = Akka.Streams.Actors.Cancel; namespace Akka.Streams.Tests.Actor { @@ -247,7 +250,23 @@ public void ActorPublisher_should_only_allow_one_subscriber() s.ExpectSubscription(); var s2 = this.CreateManualSubscriberProbe(); ActorPublisher.Create(actorRef).Subscribe(s2); - s2.ExpectSubscriptionAndError().Should().BeOfType(); + s2.ExpectSubscriptionAndError() + .Should() + .BeOfType() + .Which.Message.Should() + .Be($"ActorPublisher {ReactiveStreamsCompliance.SupportsOnlyASingleSubscriber}"); + } + + [Fact] + public void ActorPublisher_should_not_subscribe_the_same_subscriber_multiple_times() + { + var probe = CreateTestProbe(); + var actorRef = Sys.ActorOf(TestPublisher.Props(probe.Ref)); + var s = this.CreateManualSubscriberProbe(); + ActorPublisher.Create(actorRef).Subscribe(s); + s.ExpectSubscription(); + ActorPublisher.Create(actorRef).Subscribe(s); + s.ExpectError().Message.Should().Be(ReactiveStreamsCompliance.CanNotSubscribeTheSameSubscriberMultipleTimes); } [Fact] @@ -454,7 +473,7 @@ public void ActorPublisher_should_handle_stash() } } - internal class TestPublisher : ActorPublisher + internal class TestPublisher : Actors.ActorPublisher { public static Props Props(IActorRef probe, bool useTestDispatcher = true) { @@ -512,7 +531,7 @@ protected override bool Receive(object message) public IStash Stash { get; set; } } - internal class Sender : ActorPublisher + internal class Sender : Actors.ActorPublisher { public static Props Props { get; } = Props.Create().WithDispatcher("akka.test.stream-dispatcher"); @@ -559,7 +578,7 @@ private void DeliverBuffer() } } - internal class TimeoutingPublisher : ActorPublisher + internal class TimeoutingPublisher : Actors.ActorPublisher { public static Props Props(IActorRef probe, TimeSpan timeout) => Akka.Actor.Props.Create(() => new TimeoutingPublisher(probe, timeout)) diff --git a/src/core/Akka.Streams.Tests/Akka.Streams.Tests.csproj b/src/core/Akka.Streams.Tests/Akka.Streams.Tests.csproj index 603e0ac6a01..ec664a996c4 100644 --- a/src/core/Akka.Streams.Tests/Akka.Streams.Tests.csproj +++ b/src/core/Akka.Streams.Tests/Akka.Streams.Tests.csproj @@ -144,6 +144,7 @@ + diff --git a/src/core/Akka.Streams.Tests/Dsl/FlowGroupBySpec.cs b/src/core/Akka.Streams.Tests/Dsl/FlowGroupBySpec.cs index 8a7aa74babe..aa33fb1a677 100644 --- a/src/core/Akka.Streams.Tests/Dsl/FlowGroupBySpec.cs +++ b/src/core/Akka.Streams.Tests/Dsl/FlowGroupBySpec.cs @@ -14,6 +14,7 @@ using Akka.Streams.Dsl; using Akka.Streams.Dsl.Internal; using Akka.Streams.Implementation; +using Akka.Streams.Implementation.Fusing; using Akka.Streams.Supervision; using Akka.Streams.TestKit; using Akka.Streams.TestKit.Tests; @@ -481,6 +482,41 @@ public void GroupBy_must_work_under_fuzzing_stress_test() }, Materializer); } + [Fact] + public void GroupBy_must_Work_if_pull_is_exercised_from_both_substream_and_main() + { + this.AssertAllStagesStopped(() => + { + var upstream = this.CreatePublisherProbe(); + var downstreamMaster = this.CreateSubscriberProbe>(); + + Source.FromPublisher(upstream) + .Via(new GroupBy(2, element => element == 0)) + .RunWith(Sink.FromSubscriber(downstreamMaster), Materializer); + + var substream = this.CreateSubscriberProbe(); + + downstreamMaster.Request(1); + upstream.SendNext(1); + downstreamMaster.ExpectNext().RunWith(Sink.FromSubscriber(substream), Materializer); + + // Read off first buffered element from subsource + substream.Request(1); + substream.ExpectNext(1); + + // Both will attempt to pull upstream + substream.Request(1); + substream.ExpectNoMsg(TimeSpan.FromMilliseconds(100)); + downstreamMaster.Request(1); + downstreamMaster.ExpectNoMsg(TimeSpan.FromMilliseconds(100)); + + // Cleanup, not part of the actual test + substream.Cancel(); + downstreamMaster.Cancel(); + upstream.SendComplete(); + }, Materializer); + } + [Fact] public void GroupBy_must_work_with_random_demand() { diff --git a/src/core/Akka.Streams.Tests/Dsl/FlowScanSpec.cs b/src/core/Akka.Streams.Tests/Dsl/FlowScanSpec.cs index 9bac202ef2b..724d99ff9a9 100644 --- a/src/core/Akka.Streams.Tests/Dsl/FlowScanSpec.cs +++ b/src/core/Akka.Streams.Tests/Dsl/FlowScanSpec.cs @@ -130,5 +130,27 @@ public void A_Scan_must_resume_properly() .ToStrict(TimeSpan.FromSeconds(1)) .ShouldAllBeEquivalentTo(new[] {0, 1, 4, 9, 16}); } + + [Fact] + public void A_Scan_must_scan_normally_for_empty_source() + { + Source.Empty() + .Scan(0, (i, i1) => i + i1) + .RunWith(this.SinkProbe(), Materializer) + .Request(2) + .ExpectNext(0) + .ExpectComplete(); + } + + [Fact] + public void A_Scan_must_fail_when_upstream_failed() + { + var cause = new TestException(""); + Source.Failed(cause) + .Scan(0, (i, i1) => i + i1) + .RunWith(this.SinkProbe(), Materializer) + .Request(2) + .ExpectError().Should().Be(cause); + } } } diff --git a/src/core/Akka.Streams.Tests/Dsl/LazySinkSpec.cs b/src/core/Akka.Streams.Tests/Dsl/LazySinkSpec.cs new file mode 100644 index 00000000000..0e368b4673d --- /dev/null +++ b/src/core/Akka.Streams.Tests/Dsl/LazySinkSpec.cs @@ -0,0 +1,242 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2015-2016 Lightbend Inc. +// Copyright (C) 2013-2016 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; +using System.Linq; +using System.Threading.Tasks; +using Akka.Streams.Dsl; +using Akka.Streams.Supervision; +using Akka.Streams.TestKit; +using Akka.Streams.TestKit.Tests; +using Akka.TestKit; +using Akka.Util.Internal; +using FluentAssertions; +using Xunit; +using Xunit.Abstractions; + +namespace Akka.Streams.Tests.Dsl +{ + public class LazySinkSpec : AkkaSpec + { + public LazySinkSpec(ITestOutputHelper helper) : base(helper) + { + var settings = ActorMaterializerSettings.Create(Sys).WithInputBuffer(1,1); + Materializer = Sys.Materializer(settings); + } + + private ActorMaterializer Materializer { get; } + + private static Func Fallback() + { + return () => + { + Assert.True(false, "Must not call fallback function"); + return default(TMat); + }; + } + + private static readonly Exception Ex = new TestException(""); + + [Fact] + public void A_LazySink_must_work_in_the_happy_case() + { + this.AssertAllStagesStopped(() => + { + var lazySink = Sink.LazySink((int _) => Task.FromResult(this.SinkProbe()), + Fallback>()); + var taskProbe = Source.From(Enumerable.Range(0, 11)).RunWith(lazySink, Materializer); + var probe = taskProbe.AwaitResult(TimeSpan.FromMilliseconds(300)); + probe.Request(100); + Enumerable.Range(0, 11).ForEach(i => probe.ExpectNext(i)); + }, Materializer); + } + + [Fact] + public void A_LazySink_must_work_with_slow_sink_init() + { + this.AssertAllStagesStopped(() => + { + var p = new TaskCompletionSource>>(); + var sourceProbe = this.CreateManualPublisherProbe(); + var taskProbe = Source.FromPublisher(sourceProbe) + .RunWith(Sink.LazySink((int _) => p.Task, Fallback>()), Materializer); + + var sourceSub = sourceProbe.ExpectSubscription(); + sourceSub.ExpectRequest(1); + sourceSub.SendNext(0); + sourceSub.ExpectRequest(1); + sourceProbe.ExpectNoMsg(TimeSpan.FromMilliseconds(200)); + taskProbe.Wait(TimeSpan.FromMilliseconds(200)).ShouldBeFalse(); + + p.SetResult(this.SinkProbe()); + var probe = taskProbe.AwaitResult(TimeSpan.FromMilliseconds(300)); + probe.Request(100); + probe.ExpectNext(0); + Enumerable.Range(1,10).ForEach(i => + { + sourceSub.SendNext(i); + probe.ExpectNext(i); + }); + sourceSub.SendComplete(); + }, Materializer); + } + + [Fact] + public void A_LazySink_must_complete_when_there_was_no_elements_in_stream() + { + this.AssertAllStagesStopped(() => + { + var lazySink = Sink.LazySink((int _) => Task.FromResult(Sink.Aggregate(0, (int i, int i2) => i + i2)), + () => Task.FromResult(0)); + var taskProbe = Source.Empty().RunWith(lazySink, Materializer); + var taskResult = taskProbe.AwaitResult(TimeSpan.FromMilliseconds(300)); + taskResult.AwaitResult(TimeSpan.FromMilliseconds(300)).ShouldBe(0); + }, Materializer); + } + + [Fact] + public void A_LazySink_must_complete_normally_when_upstream_is_completed() + { + this.AssertAllStagesStopped(() => + { + var lazySink = Sink.LazySink((int _) => Task.FromResult(this.SinkProbe()), + Fallback>()); + var taskProbe = Source.Single(1).RunWith(lazySink, Materializer); + var taskResult = taskProbe.AwaitResult(TimeSpan.FromMilliseconds(300)); + taskResult.Request(1).ExpectNext(1).ExpectComplete(); + }, Materializer); + } + + [Fact] + public void A_LazySink_must_fail_gracefully_when_sink_factory_method_failed() + { + this.AssertAllStagesStopped(() => + { + var sourceProbe = this.CreateManualPublisherProbe(); + var taskProbe = Source.FromPublisher(sourceProbe).RunWith(Sink.LazySink((int _) => + { + throw Ex; + }, Fallback>()), Materializer); + + var sourceSub = sourceProbe.ExpectSubscription(); + sourceSub.ExpectRequest(1); + sourceSub.SendNext(0); + sourceSub.ExpectCancellation(); + taskProbe.Invoking(t => t.Wait()).ShouldThrow(); + }, Materializer); + } + + [Fact] + public void A_LazySink_must_fail_gracefully_when_upstream_failed() + { + this.AssertAllStagesStopped(() => + { + var sourceProbe = this.CreateManualPublisherProbe(); + var lazySink = Sink.LazySink((int _) => Task.FromResult(this.SinkProbe()), + Fallback>()); + var taskProbe = Source.FromPublisher(sourceProbe).RunWith(lazySink, Materializer); + + var sourceSub = sourceProbe.ExpectSubscription(); + sourceSub.ExpectRequest(1); + sourceSub.SendNext(0); + var probe = taskProbe.AwaitResult(TimeSpan.FromMilliseconds(300)); + probe.Request(1).ExpectNext(0); + sourceSub.SendError(Ex); + probe.ExpectError().Should().Be(Ex); + }, Materializer); + } + + [Fact] + public void A_LazySink_must_fail_gracefully_when_factory_task_failed() + { + this.AssertAllStagesStopped(() => + { + var failedTask = new TaskFactory>>().StartNew(() => + { + throw Ex; + }); + var sourceProbe = this.CreateManualPublisherProbe(); + var lazySink = Sink.LazySink((int _) => failedTask, Fallback>()); + var graph = + Source.FromPublisher(sourceProbe) + .ToMaterialized(lazySink, Keep.Right) + .WithAttributes(ActorAttributes.CreateSupervisionStrategy(Deciders.StoppingDecider)); + var taskProbe = RunnableGraph.FromGraph(graph).Run(Materializer); + + var sourceSub = sourceProbe.ExpectSubscription(); + sourceSub.ExpectRequest(1); + sourceSub.SendNext(0); + taskProbe.Invoking(t => t.Wait(TimeSpan.FromMilliseconds(300))).ShouldThrow(); + }, Materializer); + } + + [Fact] + public void A_LazySink_must_cancel_upstream_when_internal_sink_is_cancelled() + { + this.AssertAllStagesStopped(() => + { + var sourceProbe = this.CreateManualPublisherProbe(); + var lazySink = Sink.LazySink((int _) => Task.FromResult(this.SinkProbe()), + Fallback>()); + var taskProbe = Source.FromPublisher(sourceProbe).RunWith(lazySink, Materializer); + var sourceSub = sourceProbe.ExpectSubscription(); + sourceSub.ExpectRequest(1); + sourceSub.SendNext(0); + sourceSub.ExpectRequest(1); + var probe = taskProbe.AwaitResult(TimeSpan.FromMilliseconds(300)); + probe.Request(1).ExpectNext(0); + probe.Cancel(); + sourceSub.ExpectCancellation(); + }, Materializer); + } + + [Fact] + public void A_LazySink_must_contine_if_supervision_is_resume() + { + this.AssertAllStagesStopped(() => + { + var sourceProbe = this.CreateManualPublisherProbe(); + var lazySink = Sink.LazySink((int a) => + { + if (a == 0) + throw Ex; + return Task.FromResult(this.SinkProbe()); + }, + Fallback>()); + var graph = + Source.FromPublisher(sourceProbe) + .ToMaterialized(lazySink, Keep.Right) + .WithAttributes(ActorAttributes.CreateSupervisionStrategy(Deciders.ResumingDecider)); + var taskProbe = RunnableGraph.FromGraph(graph).Run(Materializer); + var sourceSub = sourceProbe.ExpectSubscription(); + sourceSub.ExpectRequest(1); + sourceSub.SendNext(0); + sourceSub.ExpectRequest(1); + sourceSub.SendNext(1); + var probe = taskProbe.AwaitResult(TimeSpan.FromMilliseconds(300)); + probe.Request(1); + probe.ExpectNext(1); + probe.Cancel(); + }, Materializer); + } + + [Fact] + public void A_LazySink_must_fail_task_when_zero_throws_expception() + { + this.AssertAllStagesStopped(() => + { + var lazySink = Sink.LazySink((int _) => Task.FromResult(Sink.Aggregate(0, (i, i1) => i + i1)), + () => + { + throw Ex; + }); + var taskProbe = Source.Empty().RunWith(lazySink, Materializer); + taskProbe.Invoking(t => t.Wait(TimeSpan.FromMilliseconds(300))).ShouldThrow(); + }, Materializer); + } + } +} diff --git a/src/core/Akka.Streams.Tests/Implementation/Fusing/InterpreterSpec.cs b/src/core/Akka.Streams.Tests/Implementation/Fusing/InterpreterSpec.cs index 36d6ba44373..d5f6b3660ce 100644 --- a/src/core/Akka.Streams.Tests/Implementation/Fusing/InterpreterSpec.cs +++ b/src/core/Akka.Streams.Tests/Implementation/Fusing/InterpreterSpec.cs @@ -231,10 +231,7 @@ public void Interpreter_should_implement_take_inside_a_chain() [Fact] public void Interpreter_should_implement_fold() { - WithOneBoundedSetup(new IStage[] - { - new Aggregate(0, (agg, x) => agg + x, Deciders.StoppingDecider) - }, + WithOneBoundedSetup(new Aggregate(0, (agg, x) => agg + x), (lastEvents, upstream, downstream) => { lastEvents().Should().BeEmpty(); @@ -259,10 +256,7 @@ public void Interpreter_should_implement_fold() [Fact] public void Interpreter_should_implement_fold_with_proper_cancel() { - WithOneBoundedSetup(new IStage[] - { - new Aggregate(0, (agg, x) => agg + x, Deciders.StoppingDecider) - }, + WithOneBoundedSetup(new Aggregate(0, (agg, x) => agg + x), (lastEvents, upstream, downstream) => { lastEvents().Should().BeEmpty(); @@ -287,10 +281,7 @@ public void Interpreter_should_implement_fold_with_proper_cancel() [Fact] public void Interpreter_should_work_if_fold_completes_while_not_in_a_push_position() { - WithOneBoundedSetup(new IStage[] - { - new Aggregate(0, (agg, x) => agg + x, Deciders.StoppingDecider) - }, + WithOneBoundedSetup(new Aggregate(0, (agg, x) => agg + x), (lastEvents, upstream, downstream) => { lastEvents().Should().BeEmpty(); @@ -306,9 +297,7 @@ public void Interpreter_should_work_if_fold_completes_while_not_in_a_push_positi [Fact] public void Interpreter_should_implement_grouped() { - WithOneBoundedSetup(ToGraphStage( - new Grouped(3) - ), + WithOneBoundedSetup(new Grouped(3), (lastEvents, upstream, downstream) => { lastEvents().Should().BeEmpty(); @@ -619,10 +608,10 @@ public void Interpreter_should_work_with_PushAndFinish_if_indirect_upstream_comp [Fact] public void Interpreter_should_work_with_PushAndFinish_if_upstream_completes_with_PushAndFinish_and_downstream_immediately_pulls() { - WithOneBoundedSetup(new IStage[] + WithOneBoundedSetup(new IGraphStageWithMaterializedValue, object>[] { - new PushFinishStage(), - new Aggregate(0, (x, y) => x + y, Deciders.StoppingDecider) + ToGraphStage(new PushFinishStage()), + new Aggregate(0, (x, y) => x + y) }, (lastEvents, upstream, downstream) => { diff --git a/src/core/Akka.Streams.Tests/Implementation/Fusing/InterpreterSupervisionSpec.cs b/src/core/Akka.Streams.Tests/Implementation/Fusing/InterpreterSupervisionSpec.cs index 0621b0a807f..f698b2fc03a 100644 --- a/src/core/Akka.Streams.Tests/Implementation/Fusing/InterpreterSupervisionSpec.cs +++ b/src/core/Akka.Streams.Tests/Implementation/Fusing/InterpreterSupervisionSpec.cs @@ -119,7 +119,7 @@ public void Interpreter_error_handling_should_resume_when_Map_throws_before_Grou WithOneBoundedSetup(new IGraphStageWithMaterializedValue[] { ToGraphStage(new Select(x => x + 1, resumingDecider)), ToGraphStage(new Select(x => { if (x == 0) throw TE(); return x + 10; }, resumingDecider)), - ToGraphStage(new Grouped(3)) + new Grouped(3) }, (lastEvents, upstream, downstream) => { @@ -145,7 +145,7 @@ public void Interpreter_error_handling_should_complete_after_resume_when_Map_thr WithOneBoundedSetup(new IGraphStageWithMaterializedValue[] { ToGraphStage(new Select(x => x + 1, resumingDecider)), ToGraphStage(new Select(x => { if (x == 0) throw TE(); return x + 10; }, resumingDecider)), - ToGraphStage(new Grouped(1000)) + new Grouped(1000) }, (lastEvents, upstream, downstream) => { diff --git a/src/core/Akka.Streams.Tests/Implementation/Fusing/LifecycleInterpreterSpec.cs b/src/core/Akka.Streams.Tests/Implementation/Fusing/LifecycleInterpreterSpec.cs index d9e10092548..bb94e9c08e8 100644 --- a/src/core/Akka.Streams.Tests/Implementation/Fusing/LifecycleInterpreterSpec.cs +++ b/src/core/Akka.Streams.Tests/Implementation/Fusing/LifecycleInterpreterSpec.cs @@ -393,7 +393,7 @@ public void Interpreter_must_call_PostStop_when_PushAndFinish_called_with_PushAn var ops = new IGraphStageWithMaterializedValue, object>[] { new PushFinishStage(() => TestActor.Tell("stop")), - ToGraphStage(new Aggregate("", (x, y) => x+y, Deciders.StoppingDecider)) + new Aggregate("", (x, y) => x+y) }; WithOneBoundedSetup(ops, (lastEvents, upstream, downstream) => diff --git a/src/core/Akka.Streams/ActorMaterializer.cs b/src/core/Akka.Streams/ActorMaterializer.cs index 708bac6ef39..9c67778dbcf 100644 --- a/src/core/Akka.Streams/ActorMaterializer.cs +++ b/src/core/Akka.Streams/ActorMaterializer.cs @@ -69,15 +69,6 @@ public static ActorMaterializer Create(IActorRefFactory context, ActorMaterializ flowNames: EnumerableActorName.Create(namePrefix ?? "Flow")); } - internal static ActorMaterializer Downcast(IMaterializer materializer) - { - //FIXME this method is going to cause trouble for other Materializer implementations - if (materializer is ActorMaterializer) - return (ActorMaterializer)materializer; - - throw new ArgumentException($"Expected {typeof(ActorMaterializer)} but got {materializer.GetType()}"); - } - private static ActorSystem ActorSystemOf(IActorRefFactory context) { if (context is ExtendedActorSystem) @@ -124,11 +115,27 @@ private static ActorSystem ActorSystemOf(IActorRefFactory context) /// public abstract void Shutdown(); - protected internal abstract IActorRef ActorOf(MaterializationContext context, Props props); + public abstract IActorRef ActorOf(MaterializationContext context, Props props); public void Dispose() => Shutdown(); } + /// + /// INTERNAL API + /// + internal static class ActorMaterializerHelper + { + internal static ActorMaterializer Downcast(IMaterializer materializer) + { + //FIXME this method is going to cause trouble for other Materializer implementations + var downcast = materializer as ActorMaterializer; + if (downcast != null) + return downcast; + + throw new ArgumentException($"Expected {typeof(ActorMaterializer)} but got {materializer.GetType()}"); + } + } + /// /// This exception signals that an actor implementing a Reactive Streams Subscriber, Publisher or Processor /// has been terminated without being notified by an onError, onComplete or cancel signal. This usually happens diff --git a/src/core/Akka.Streams/Actors/ActorPublisher.cs b/src/core/Akka.Streams/Actors/ActorPublisher.cs index b8b98d2baaf..052f788c32a 100644 --- a/src/core/Akka.Streams/Actors/ActorPublisher.cs +++ b/src/core/Akka.Streams/Actors/ActorPublisher.cs @@ -233,7 +233,6 @@ public void OnNext(T element) { case LifecycleState.Active: case LifecycleState.PreSubscriber: - case LifecycleState.CompleteThenStop: if (_demand > 0) { _demand--; @@ -245,8 +244,11 @@ public void OnNext(T element) "OnNext is not allowed when the stream has not requested elements, total demand was 0"); } break; - case LifecycleState.ErrorEmitted: throw new IllegalStateException("OnNext must not be called after OnError"); - case LifecycleState.Completed: throw new IllegalStateException("OnNext must not be called after OnComplete"); + case LifecycleState.ErrorEmitted: + throw new IllegalStateException("OnNext must not be called after OnError"); + case LifecycleState.Completed: + case LifecycleState.CompleteThenStop: + throw new IllegalStateException("OnNext must not be called after OnComplete"); case LifecycleState.Canceled: break; } } @@ -447,10 +449,10 @@ protected override bool AroundReceive(Receive receive, object message) break; case LifecycleState.Active: case LifecycleState.Canceled: - ReactiveStreamsCompliance.TryOnSubscribe(subscriber, CancelledSubscription.Instance); - ReactiveStreamsCompliance.TryOnError(subscriber, _subscriber == subscriber - ? new IllegalStateException("Cannot subscribe the same subscriber multiple times") - : new IllegalStateException("Only supports one subscriber")); + if(_subscriber == subscriber) + ReactiveStreamsCompliance.RejectDuplicateSubscriber(subscriber); + else + ReactiveStreamsCompliance.RejectAdditionalSubscriber(subscriber, "ActorPublisher"); break; } } diff --git a/src/core/Akka.Streams/Attributes.cs b/src/core/Akka.Streams/Attributes.cs index 10420025d15..1302ad0fedc 100644 --- a/src/core/Akka.Streams/Attributes.cs +++ b/src/core/Akka.Streams/Attributes.cs @@ -198,7 +198,7 @@ public Attributes And(Attributes other) /// public string GetNameLifted() => GetNameOrDefault(null); - internal string GetNameOrDefault(string defaultIfNotFound = "unknown-operation") + public string GetNameOrDefault(string defaultIfNotFound = "unknown-operation") { if (_attributes.Length == 0) return null; diff --git a/src/core/Akka.Streams/CodeGen/Dsl/ZipWith.cs b/src/core/Akka.Streams/CodeGen/Dsl/ZipWith.cs index 102ec8cacc1..afec9dacc54 100644 --- a/src/core/Akka.Streams/CodeGen/Dsl/ZipWith.cs +++ b/src/core/Akka.Streams/CodeGen/Dsl/ZipWith.cs @@ -1,5 +1,5 @@  -// --- auto generated: 21.04.2016 07:48:48 --- // +// --- auto generated: 02.10.2016 19:34:41 --- // //----------------------------------------------------------------------- // // Copyright (C) 2015-2016 Lightbend Inc. @@ -127,7 +127,7 @@ public Logic(Shape shape, ZipWith stage) : base(shape) private void PushAll() { - Push(_stage.Out, _stage._zipper(Grab(_stage.In0), Grab(_stage.In1))); + Push(_stage.Out, _stage.Zipper(Grab(_stage.In0), Grab(_stage.In1))); if (_willShutDown) CompleteStage(); else { Pull(_stage.In0); @@ -147,10 +147,9 @@ public override string ToString() } } - private readonly Func _zipper; public ZipWith(Func zipper) { - _zipper = zipper; + Zipper = zipper; InitialAttributes = Attributes.CreateName("ZipWith"); Shape = new FanInShape("ZipWith"); Out = Shape.Out; @@ -166,7 +165,11 @@ public ZipWith(Func zipper) public Inlet In1 { get; } protected sealed override Attributes InitialAttributes { get; } + public sealed override FanInShape Shape { get; } + + public Func Zipper { get; } + protected sealed override GraphStageLogic CreateLogic(Attributes inheritedAttributes) { return new Logic(Shape, this); @@ -220,7 +223,7 @@ public Logic(Shape shape, ZipWith stage) : base(shape) private void PushAll() { - Push(_stage.Out, _stage._zipper(Grab(_stage.In0), Grab(_stage.In1), Grab(_stage.In2))); + Push(_stage.Out, _stage.Zipper(Grab(_stage.In0), Grab(_stage.In1), Grab(_stage.In2))); if (_willShutDown) CompleteStage(); else { Pull(_stage.In0); @@ -242,10 +245,9 @@ public override string ToString() } } - private readonly Func _zipper; public ZipWith(Func zipper) { - _zipper = zipper; + Zipper = zipper; InitialAttributes = Attributes.CreateName("ZipWith"); Shape = new FanInShape("ZipWith"); Out = Shape.Out; @@ -263,7 +265,11 @@ public ZipWith(Func zipper) public Inlet In2 { get; } protected sealed override Attributes InitialAttributes { get; } + public sealed override FanInShape Shape { get; } + + public Func Zipper { get; } + protected sealed override GraphStageLogic CreateLogic(Attributes inheritedAttributes) { return new Logic(Shape, this); @@ -326,7 +332,7 @@ public Logic(Shape shape, ZipWith stage) : base(sh private void PushAll() { - Push(_stage.Out, _stage._zipper(Grab(_stage.In0), Grab(_stage.In1), Grab(_stage.In2), Grab(_stage.In3))); + Push(_stage.Out, _stage.Zipper(Grab(_stage.In0), Grab(_stage.In1), Grab(_stage.In2), Grab(_stage.In3))); if (_willShutDown) CompleteStage(); else { Pull(_stage.In0); @@ -350,10 +356,9 @@ public override string ToString() } } - private readonly Func _zipper; public ZipWith(Func zipper) { - _zipper = zipper; + Zipper = zipper; InitialAttributes = Attributes.CreateName("ZipWith"); Shape = new FanInShape("ZipWith"); Out = Shape.Out; @@ -373,7 +378,11 @@ public ZipWith(Func zipper) public Inlet In3 { get; } protected sealed override Attributes InitialAttributes { get; } + public sealed override FanInShape Shape { get; } + + public Func Zipper { get; } + protected sealed override GraphStageLogic CreateLogic(Attributes inheritedAttributes) { return new Logic(Shape, this); @@ -445,7 +454,7 @@ public Logic(Shape shape, ZipWith stage) : b private void PushAll() { - Push(_stage.Out, _stage._zipper(Grab(_stage.In0), Grab(_stage.In1), Grab(_stage.In2), Grab(_stage.In3), Grab(_stage.In4))); + Push(_stage.Out, _stage.Zipper(Grab(_stage.In0), Grab(_stage.In1), Grab(_stage.In2), Grab(_stage.In3), Grab(_stage.In4))); if (_willShutDown) CompleteStage(); else { Pull(_stage.In0); @@ -471,10 +480,9 @@ public override string ToString() } } - private readonly Func _zipper; public ZipWith(Func zipper) { - _zipper = zipper; + Zipper = zipper; InitialAttributes = Attributes.CreateName("ZipWith"); Shape = new FanInShape("ZipWith"); Out = Shape.Out; @@ -496,7 +504,11 @@ public ZipWith(Func zipper) public Inlet In4 { get; } protected sealed override Attributes InitialAttributes { get; } + public sealed override FanInShape Shape { get; } + + public Func Zipper { get; } + protected sealed override GraphStageLogic CreateLogic(Attributes inheritedAttributes) { return new Logic(Shape, this); @@ -577,7 +589,7 @@ public Logic(Shape shape, ZipWith stag private void PushAll() { - Push(_stage.Out, _stage._zipper(Grab(_stage.In0), Grab(_stage.In1), Grab(_stage.In2), Grab(_stage.In3), Grab(_stage.In4), Grab(_stage.In5))); + Push(_stage.Out, _stage.Zipper(Grab(_stage.In0), Grab(_stage.In1), Grab(_stage.In2), Grab(_stage.In3), Grab(_stage.In4), Grab(_stage.In5))); if (_willShutDown) CompleteStage(); else { Pull(_stage.In0); @@ -605,10 +617,9 @@ public override string ToString() } } - private readonly Func _zipper; public ZipWith(Func zipper) { - _zipper = zipper; + Zipper = zipper; InitialAttributes = Attributes.CreateName("ZipWith"); Shape = new FanInShape("ZipWith"); Out = Shape.Out; @@ -632,7 +643,11 @@ public ZipWith(Func zipper) public Inlet In5 { get; } protected sealed override Attributes InitialAttributes { get; } + public sealed override FanInShape Shape { get; } + + public Func Zipper { get; } + protected sealed override GraphStageLogic CreateLogic(Attributes inheritedAttributes) { return new Logic(Shape, this); @@ -722,7 +737,7 @@ public Logic(Shape shape, ZipWith _zipper; public ZipWith(Func zipper) { - _zipper = zipper; + Zipper = zipper; InitialAttributes = Attributes.CreateName("ZipWith"); Shape = new FanInShape("ZipWith"); Out = Shape.Out; @@ -781,7 +795,11 @@ public ZipWith(Func zipper) public Inlet In6 { get; } protected sealed override Attributes InitialAttributes { get; } + public sealed override FanInShape Shape { get; } + + public Func Zipper { get; } + protected sealed override GraphStageLogic CreateLogic(Attributes inheritedAttributes) { return new Logic(Shape, this); @@ -880,7 +898,7 @@ public Logic(Shape shape, ZipWith _zipper; public ZipWith(Func zipper) { - _zipper = zipper; + Zipper = zipper; InitialAttributes = Attributes.CreateName("ZipWith"); Shape = new FanInShape("ZipWith"); Out = Shape.Out; @@ -943,7 +960,11 @@ public ZipWith(Func zipper public Inlet In7 { get; } protected sealed override Attributes InitialAttributes { get; } + public sealed override FanInShape Shape { get; } + + public Func Zipper { get; } + protected sealed override GraphStageLogic CreateLogic(Attributes inheritedAttributes) { return new Logic(Shape, this); @@ -1051,7 +1072,7 @@ public Logic(Shape shape, ZipWith _zipper; public ZipWith(Func zipper) { - _zipper = zipper; + Zipper = zipper; InitialAttributes = Attributes.CreateName("ZipWith"); Shape = new FanInShape("ZipWith"); Out = Shape.Out; @@ -1118,7 +1138,11 @@ public ZipWith(Func public Inlet In8 { get; } protected sealed override Attributes InitialAttributes { get; } + public sealed override FanInShape Shape { get; } + + public Func Zipper { get; } + protected sealed override GraphStageLogic CreateLogic(Attributes inheritedAttributes) { return new Logic(Shape, this); diff --git a/src/core/Akka.Streams/CodeGen/Dsl/ZipWith.tt b/src/core/Akka.Streams/CodeGen/Dsl/ZipWith.tt index 866e7c3b5bf..9ec46f67d45 100644 --- a/src/core/Akka.Streams/CodeGen/Dsl/ZipWith.tt +++ b/src/core/Akka.Streams/CodeGen/Dsl/ZipWith.tt @@ -72,7 +72,7 @@ namespace Akka.Streams.Dsl private void PushAll() { - Push(_stage.Out, _stage._zipper(<#= string.Join(", ", Enumerable.Range(0, i).Select(x => "Grab(_stage.In" + x + ")")) #>)); + Push(_stage.Out, _stage.Zipper(<#= string.Join(", ", Enumerable.Range(0, i).Select(x => "Grab(_stage.In" + x + ")")) #>)); if (_willShutDown) CompleteStage(); else { <# for (var t = 0; t < i; t++) { #> @@ -94,10 +94,9 @@ namespace Akka.Streams.Dsl } } - private readonly Func<<#= typeParams #>, TOut> _zipper; public ZipWith(Func<<#= typeParams #>, TOut> zipper) { - _zipper = zipper; + Zipper = zipper; InitialAttributes = Attributes.CreateName("ZipWith"); Shape = new <#= fanInShape #>("ZipWith"); Out = Shape.Out; @@ -115,7 +114,11 @@ public Inlet> In<#= t #> { get; } <# } #> protected sealed override Attributes InitialAttributes { get; } + public sealed override <#= fanInShape #> Shape { get; } + + public Func<<#= typeParams #>, TOut> Zipper { get; } + protected sealed override GraphStageLogic CreateLogic(Attributes inheritedAttributes) { return new Logic(Shape, this); diff --git a/src/core/Akka.Streams/Dsl/Internal/GraphImpl.cs b/src/core/Akka.Streams/Dsl/Internal/GraphImpl.cs index c043659fa39..9eb93406b8b 100644 --- a/src/core/Akka.Streams/Dsl/Internal/GraphImpl.cs +++ b/src/core/Akka.Streams/Dsl/Internal/GraphImpl.cs @@ -6,10 +6,14 @@ //----------------------------------------------------------------------- using Akka.Streams.Implementation; +using Akka.Streams.Util; namespace Akka.Streams.Dsl.Internal { - internal class GraphImpl : IGraph where TShape : Shape + /// + /// INTERNAL API + /// + public class GraphImpl : IGraph where TShape : Shape { public GraphImpl(TShape shape, IModule module) { @@ -31,4 +35,16 @@ public GraphImpl(TShape shape, IModule module) public override string ToString() => $"Graph({Shape}, {Module})"; } + + /// + /// INTERNAL API + /// + public static class ModuleExtractor + { + public static Option Unapply(IGraph graph) where TShape : Shape + { + var module = graph as IModule; + return module != null ? new Option(module) : Option.None; + } + } } \ No newline at end of file diff --git a/src/core/Akka.Streams/Dsl/Internal/InternalFlowOperations.cs b/src/core/Akka.Streams/Dsl/Internal/InternalFlowOperations.cs index 5da9651c1b3..786d6578200 100644 --- a/src/core/Akka.Streams/Dsl/Internal/InternalFlowOperations.cs +++ b/src/core/Akka.Streams/Dsl/Internal/InternalFlowOperations.cs @@ -364,7 +364,7 @@ public static IFlow Collect(this IFlow f /// Thrown, if is less than or equal zero. public static IFlow, TMat> Grouped(this IFlow flow, int n) { - return flow.AndThen(new Grouped(n)); + return flow.Via(new Fusing.Grouped(n)); } /// @@ -442,7 +442,7 @@ public static IFlow LimitWeighted(this IFlow flow, lo /// Thrown when or is less than or equal zero. public static IFlow, TMat> Sliding(this IFlow flow, int n, int step = 1) { - return flow.AndThen(new Sliding(n, step)); + return flow.Via(new Fusing.Sliding(n, step)); } /// @@ -489,7 +489,7 @@ public static IFlow Scan(this IFlow flow public static IFlow Aggregate(this IFlow flow, TOut zero, Func fold) { - return flow.AndThen(new Aggregate(zero, fold)); + return flow.Via(new Fusing.Aggregate(zero, fold)); } /// @@ -1390,7 +1390,7 @@ public static IFlow InitialDelay(this IFlow flow, Tim public static IFlow Log(this IFlow flow, string name, Func extract = null, ILoggingAdapter log = null) { - return flow.AndThen(new Log(name, extract ?? Identity(), log)); + return flow.Via(new Fusing.Log(name, extract ?? Identity(), log)); } /// diff --git a/src/core/Akka.Streams/Dsl/Sink.cs b/src/core/Akka.Streams/Dsl/Sink.cs index a4bad45c62a..fd2a6cec026 100644 --- a/src/core/Akka.Streams/Dsl/Sink.cs +++ b/src/core/Akka.Streams/Dsl/Sink.cs @@ -121,7 +121,7 @@ public Sink AddAttributes(Attributes attributes) public static class Sink { - private static SinkShape Shape(string name) => new SinkShape(new Inlet(name + ".in")); + public static SinkShape Shape(string name) => new SinkShape(new Inlet(name + ".in")); /// /// A graph with the shape of a sink logically is a sink, this method makes @@ -363,6 +363,18 @@ public static Sink ActorSubscriber(Props props) /// public static Sink> Queue() => FromGraph(new QueueSink()); + /// + /// Creates a real upon receiving the first element. Internal will not be created if there are no elements, + /// because of completion or error. + /// + /// If throws an exception and the supervision decision is + /// the will be completed with failure. For all other supervision options it will try to create sink with next element. + /// + /// will be executed when there was no elements and completed is received from upstream. + /// + public static Sink> LazySink(Func>> sinkFactory, + Func fallback) => FromGraph(new LazySink(sinkFactory, fallback)); + /// /// A graph with the shape of a sink logically is a sink, this method makes /// it so also in type. diff --git a/src/core/Akka.Streams/Dsl/Source.cs b/src/core/Akka.Streams/Dsl/Source.cs index ec4f7ea97a1..18bc65a93a4 100644 --- a/src/core/Akka.Streams/Dsl/Source.cs +++ b/src/core/Akka.Streams/Dsl/Source.cs @@ -266,7 +266,7 @@ public Source ZipWithN(Func, TOut2> public static class Source { - private static SourceShape Shape(string name) => new SourceShape(new Outlet(name + ".out")); + public static SourceShape Shape(string name) => new SourceShape(new Outlet(name + ".out")); /// /// Helper to create from . diff --git a/src/core/Akka.Streams/Implementation/ActorMaterializerImpl.cs b/src/core/Akka.Streams/Implementation/ActorMaterializerImpl.cs index 7892649c314..72f5be8284c 100644 --- a/src/core/Akka.Streams/Implementation/ActorMaterializerImpl.cs +++ b/src/core/Akka.Streams/Implementation/ActorMaterializerImpl.cs @@ -15,14 +15,49 @@ using Akka.Event; using Akka.Pattern; using Akka.Streams.Implementation.Fusing; -using Akka.Streams.Implementation.Stages; using Akka.Util; using Akka.Util.Internal; -using Reactive.Streams; namespace Akka.Streams.Implementation { - public sealed class ActorMaterializerImpl : ActorMaterializer + /// + /// ExtendedActorMaterializer used by subtypes which materializer using GraphInterpreterShell + /// + public abstract class ExtendedActorMaterializer : ActorMaterializer + { + public abstract TMat Materialize(IGraph runnable, Func subFlowFuser); + + public override IActorRef ActorOf(MaterializationContext context, Props props) + { + var dispatcher = props.Deploy.Dispatcher == Deploy.NoDispatcherGiven + ? EffectiveSettings(context.EffectiveAttributes).Dispatcher + : props.Dispatcher; + + return ActorOf(props, context.StageName, dispatcher); + } + + protected IActorRef ActorOf(Props props, string name, string dispatcher) + { + if (Supervisor is LocalActorRef) + { + var aref = (LocalActorRef)Supervisor; + return ((ActorCell)aref.Underlying).AttachChild(props.WithDispatcher(dispatcher), isSystemService: false, name: name); + } + if (Supervisor is RepointableActorRef) + { + var aref = (RepointableActorRef)Supervisor; + if (aref.IsStarted) + return ((ActorCell)aref.Underlying).AttachChild(props.WithDispatcher(dispatcher), isSystemService: false, name: name); + + var timeout = aref.Underlying.System.Settings.CreationTimeout; + var f = Supervisor.Ask(new StreamSupervisor.Materialize(props.WithDispatcher(dispatcher), name), timeout); + return f.Result; + } + throw new IllegalStateException($"Stream supervisor must be a local actor, was [{Supervisor.GetType()}]"); + } + } + + public sealed class ActorMaterializerImpl : ExtendedActorMaterializer { #region Materializer session implementation @@ -210,7 +245,7 @@ public override ICancelable ScheduleRepeatedly(TimeSpan initialDelay, TimeSpan i public override TMat Materialize(IGraph runnable) => Materialize(runnable, null); - internal TMat Materialize(IGraph runnable, Func subFlowFuser) + public override TMat Materialize(IGraph runnable, Func subFlowFuser) { var runnableGraph = _settings.IsAutoFusing ? Fusing.Fusing.Aggressive(runnable) @@ -237,44 +272,15 @@ public override void Shutdown() Supervisor.Tell(PoisonPill.Instance); } - protected internal override IActorRef ActorOf(MaterializationContext context, Props props) - { - var dispatcher = props.Deploy.Dispatcher == Deploy.NoDispatcherGiven - ? EffectiveSettings(context.EffectiveAttributes).Dispatcher - : props.Dispatcher; - - return ActorOf(props, context.StageName, dispatcher); - } - - private IActorRef ActorOf(Props props, string name, string dispatcher) - { - if (Supervisor is LocalActorRef) - { - var aref = (LocalActorRef)Supervisor; - return ((ActorCell)aref.Underlying).AttachChild(props.WithDispatcher(dispatcher), isSystemService: false, name: name); - } - if (Supervisor is RepointableActorRef) - { - var aref = (RepointableActorRef)Supervisor; - if (aref.IsStarted) - return ((ActorCell)aref.Underlying).AttachChild(props.WithDispatcher(dispatcher), isSystemService: false, name: name); - - var timeout = aref.Underlying.System.Settings.CreationTimeout; - var f = Supervisor.Ask(new StreamSupervisor.Materialize(props.WithDispatcher(dispatcher), name), timeout); - return f.Result; - } - throw new IllegalStateException($"Stream supervisor must be a local actor, was [{Supervisor.GetType()}]"); - } - private ILoggingAdapter GetLogger() => _system.Log; } - internal class SubFusingActorMaterializerImpl : IMaterializer + public class SubFusingActorMaterializerImpl : IMaterializer { - private readonly ActorMaterializerImpl _delegateMaterializer; + private readonly ExtendedActorMaterializer _delegateMaterializer; private readonly Func _registerShell; - public SubFusingActorMaterializerImpl(ActorMaterializerImpl delegateMaterializer, Func registerShell) + public SubFusingActorMaterializerImpl(ExtendedActorMaterializer delegateMaterializer, Func registerShell) { _delegateMaterializer = delegateMaterializer; _registerShell = registerShell; @@ -295,7 +301,7 @@ public ICancelable ScheduleRepeatedly(TimeSpan initialDelay, TimeSpan interval, public MessageDispatcher ExecutionContext => _delegateMaterializer.ExecutionContext; } - internal class FlowNameCounter : ExtensionIdProvider, IExtension + public class FlowNameCounter : ExtensionIdProvider, IExtension { public static FlowNameCounter Instance(ActorSystem system) => system.WithExtension(); diff --git a/src/core/Akka.Streams/Implementation/ActorProcessor.cs b/src/core/Akka.Streams/Implementation/ActorProcessor.cs index 4e4ff0468b6..06ffead5765 100644 --- a/src/core/Akka.Streams/Implementation/ActorProcessor.cs +++ b/src/core/Akka.Streams/Implementation/ActorProcessor.cs @@ -55,7 +55,7 @@ public void OnError(Exception cause) public void OnComplete() => Impl.Tell(Actors.OnComplete.Instance); } - internal abstract class BatchingInputBuffer : IInputs + public abstract class BatchingInputBuffer : IInputs { public readonly int Count; public readonly IPump Pump; @@ -217,7 +217,7 @@ protected virtual bool Completed(object message) protected virtual void InputOnError(Exception e) => Clear(); } - internal class SimpleOutputs : IOutputs + public class SimpleOutputs : IOutputs { public readonly IActorRef Actor; public readonly IPump Pump; diff --git a/src/core/Akka.Streams/Implementation/ActorPublisher.cs b/src/core/Akka.Streams/Implementation/ActorPublisher.cs index 9462a604102..180097e910d 100644 --- a/src/core/Akka.Streams/Implementation/ActorPublisher.cs +++ b/src/core/Akka.Streams/Implementation/ActorPublisher.cs @@ -67,13 +67,13 @@ public NormalShutdownException(string message) : base(message) { } protected NormalShutdownException(SerializationInfo info, StreamingContext context) : base(info, context) { } } - internal interface IActorPublisher : IUntypedPublisher + public interface IActorPublisher : IUntypedPublisher { void Shutdown(Exception reason); IEnumerable TakePendingSubscribers(); } - internal static class ActorPublisher + public static class ActorPublisher { public const string NormalShutdownReasonMessage = "Cannot subscribe to shut-down Publisher"; public static readonly NormalShutdownException NormalShutdownReason = new NormalShutdownException(NormalShutdownReasonMessage); diff --git a/src/core/Akka.Streams/Implementation/FanIn.cs b/src/core/Akka.Streams/Implementation/FanIn.cs index 98498d7af2f..6333190cc49 100644 --- a/src/core/Akka.Streams/Implementation/FanIn.cs +++ b/src/core/Akka.Streams/Implementation/FanIn.cs @@ -16,7 +16,7 @@ namespace Akka.Streams.Implementation { using State = Byte; - internal abstract class InputBunch + public abstract class InputBunch { #region internal classes @@ -284,7 +284,7 @@ private void RegisterCompleted(int index) private void Marked(int index, bool on) => SetState(index, FanIn.Marked, on); } - internal static class FanIn + public static class FanIn { [Serializable] public struct OnError : INoSerializationVerificationNeeded, IDeadLetterSuppression @@ -343,7 +343,7 @@ public OnSubscribe(int id, ISubscription subscription) public const State Cancelled = 16; } - internal abstract class FanIn : ActorBase, IPump + public abstract class FanIn : ActorBase, IPump { #region Internal classes diff --git a/src/core/Akka.Streams/Implementation/FanOut.cs b/src/core/Akka.Streams/Implementation/FanOut.cs index 952b5a77053..b006a92f4a3 100644 --- a/src/core/Akka.Streams/Implementation/FanOut.cs +++ b/src/core/Akka.Streams/Implementation/FanOut.cs @@ -15,7 +15,7 @@ namespace Akka.Streams.Implementation { - internal class OutputBunch + public class OutputBunch { #region internal classes @@ -287,7 +287,7 @@ public TransferState DemandOrCancelAvailableFor(int id) /// /// INTERNAL API /// - internal static class FanOut + public static class FanOut { [Serializable] public struct SubstreamRequestMore : INoSerializationVerificationNeeded, IDeadLetterSuppression @@ -357,7 +357,7 @@ public ExposedPublishers(ImmutableList> publishers) /// /// INTERNAL API /// - internal abstract class FanOut : ActorBase, IPump + public abstract class FanOut : ActorBase, IPump { #region internal classes diff --git a/src/core/Akka.Streams/Implementation/Fusing/ActorGraphInterpreter.cs b/src/core/Akka.Streams/Implementation/Fusing/ActorGraphInterpreter.cs index 2332f7a3d82..0c36ae62473 100644 --- a/src/core/Akka.Streams/Implementation/Fusing/ActorGraphInterpreter.cs +++ b/src/core/Akka.Streams/Implementation/Fusing/ActorGraphInterpreter.cs @@ -19,7 +19,10 @@ // ReSharper disable MemberHidesStaticFromOuterClass namespace Akka.Streams.Implementation.Fusing { - internal sealed class GraphModule : AtomicModule + /// + /// INTERNAL API + /// + public sealed class GraphModule : AtomicModule { public readonly IModule[] MaterializedValueIds; public readonly GraphAssembly Assembly; @@ -59,7 +62,10 @@ public override string ToString() => "GraphModule\n" + $" MaterializedValueIds={string.Join("\n ", MaterializedValueIds)}"; } - internal sealed class GraphInterpreterShell + /// + /// INTERNAL API + /// + public sealed class GraphInterpreterShell { private readonly GraphAssembly _assembly; private readonly IInHandler[] _inHandlers; @@ -67,7 +73,7 @@ internal sealed class GraphInterpreterShell private readonly GraphStageLogic[] _logics; private readonly Shape _shape; private readonly ActorMaterializerSettings _settings; - internal readonly ActorMaterializerImpl Materializer; + internal readonly ExtendedActorMaterializer Materializer; /// /// Limits the number of events processed by the interpreter before scheduling @@ -99,7 +105,7 @@ internal sealed class GraphInterpreterShell private bool _interpreterCompleted; private readonly ActorGraphInterpreter.Resume _resume; - public GraphInterpreterShell(GraphAssembly assembly, IInHandler[] inHandlers, IOutHandler[] outHandlers, GraphStageLogic[] logics, Shape shape, ActorMaterializerSettings settings, ActorMaterializerImpl materializer) + public GraphInterpreterShell(GraphAssembly assembly, IInHandler[] inHandlers, IOutHandler[] outHandlers, GraphStageLogic[] logics, Shape shape, ActorMaterializerSettings settings, ExtendedActorMaterializer materializer) { _assembly = assembly; _inHandlers = inHandlers; @@ -370,7 +376,10 @@ private BusLogging GetLogger() public override string ToString() => $"GraphInterpreterShell\n {_assembly.ToString().Replace("\n", "\n ")}"; } - internal class ActorGraphInterpreter : ActorBase + /// + /// INTERNAL API + /// + public class ActorGraphInterpreter : ActorBase { #region messages @@ -766,7 +775,7 @@ private void Clear() public override string ToString() => $"BatchingActorInputBoundary(id={_id}, fill={_inputBufferElements}/{_size}, completed={_upstreamCompleted}, canceled={_downstreamCanceled})"; } - public interface IActorOutputBoundary + internal interface IActorOutputBoundary { void SubscribePending(); void ExposedPublisher(IActorPublisher publisher); @@ -775,7 +784,7 @@ public interface IActorOutputBoundary void Fail(Exception reason); } - public class ActorOutputBoundary : GraphInterpreter.DownstreamBoundaryStageLogic, IActorOutputBoundary + internal class ActorOutputBoundary : GraphInterpreter.DownstreamBoundaryStageLogic, IActorOutputBoundary { #region InHandler private sealed class InHandler : Stage.InHandler diff --git a/src/core/Akka.Streams/Implementation/Fusing/GraphStages.cs b/src/core/Akka.Streams/Implementation/Fusing/GraphStages.cs index da6f7578707..e857413d958 100644 --- a/src/core/Akka.Streams/Implementation/Fusing/GraphStages.cs +++ b/src/core/Akka.Streams/Implementation/Fusing/GraphStages.cs @@ -49,7 +49,10 @@ internal static IGraph, NotUsed> WithDetachedInputs(G } } - internal class GraphStageModule : AtomicModule + /// + /// INTERNAL API + /// + public class GraphStageModule : AtomicModule { public readonly IGraphStageWithMaterializedValue Stage; @@ -73,6 +76,9 @@ public GraphStageModule(Shape shape, Attributes attributes, IGraphStageWithMater public override string ToString() => $"GraphStage({Stage}) [{GetHashCode()}%08x]"; } + /// + /// INTERNAL API + /// public abstract class SimpleLinearGraphStage : GraphStage> { public readonly Inlet Inlet; @@ -89,7 +95,7 @@ protected SimpleLinearGraphStage() public override FlowShape Shape { get; } } - internal sealed class Identity : SimpleLinearGraphStage + public sealed class Identity : SimpleLinearGraphStage { #region internal classes private sealed class Logic : GraphStageLogic @@ -113,7 +119,10 @@ private Identity() protected override GraphStageLogic CreateLogic(Attributes inheritedAttributes) => new Logic(this); } - internal sealed class Detacher : GraphStage> + /// + /// INTERNAL API + /// + public sealed class Detacher : GraphStage> { #region internal classes private sealed class Logic : GraphStageLogic @@ -313,7 +322,7 @@ public override ILogicAndMaterializedValue CreateLogicAndMateriali public override string ToString() => "MonitorFlow"; } - internal sealed class TickSource : GraphStageWithMaterializedValue, ICancelable> + public sealed class TickSource : GraphStageWithMaterializedValue, ICancelable> { #region internal classes @@ -406,7 +415,12 @@ public interface IMaterializedValueSource void SetValue(object result); } - internal sealed class MaterializedValueSource : GraphStage>, IMaterializedValueSource + /// + /// INTERNAL API + /// + /// This source is not reusable, it is only created internally. + /// + public sealed class MaterializedValueSource : GraphStage>, IMaterializedValueSource { #region internal classes @@ -465,7 +479,7 @@ public MaterializedValueSource(StreamLayout.IMaterializedValueNode computation, public override string ToString() => $"MaterializedValueSource({Computation})"; } - internal sealed class SingleSource : GraphStage> + public sealed class SingleSource : GraphStage> { #region Internal classes private sealed class Logic : GraphStageLogic @@ -497,7 +511,7 @@ public SingleSource(T element) protected override GraphStageLogic CreateLogic(Attributes inheritedAttributes) => new Logic(this); } - internal sealed class TaskSource : GraphStage> + public sealed class TaskSource : GraphStage> { #region Internal classes private sealed class Logic : GraphStageLogic diff --git a/src/core/Akka.Streams/Implementation/Fusing/Ops.cs b/src/core/Akka.Streams/Implementation/Fusing/Ops.cs index c10909d4a62..a626fac5699 100644 --- a/src/core/Akka.Streams/Implementation/Fusing/Ops.cs +++ b/src/core/Akka.Streams/Implementation/Fusing/Ops.cs @@ -18,13 +18,14 @@ using Akka.Streams.Supervision; using Akka.Streams.Util; using Akka.Util; +using Akka.Util.Internal; namespace Akka.Streams.Implementation.Fusing { /// /// INTERNAL API /// - internal sealed class Select : PushStage + public sealed class Select : PushStage { private readonly Func _func; private readonly Decider _decider; @@ -43,7 +44,7 @@ public Select(Func func, Decider decider) /// /// INTERNAL API /// - internal sealed class Where : SimpleLinearGraphStage + public sealed class Where : SimpleLinearGraphStage { #region Logic @@ -59,14 +60,14 @@ public Logic(Where stage, Attributes inheritedAttributes) : base(stage.Shape) try { var element = Grab(stage.Inlet); - if(stage._predicate(element)) + if (stage._predicate(element)) Push(stage.Outlet, element); else Pull(stage.Inlet); } catch (Exception ex) { - if(decider(ex) == Directive.Stop) + if (decider(ex) == Directive.Stop) FailStage(ex); else Pull(stage.Inlet); @@ -79,7 +80,7 @@ public Logic(Where stage, Attributes inheritedAttributes) : base(stage.Shape) public override string ToString() => "WhereLogic"; } - #endregion + #endregion private readonly Predicate _predicate; @@ -97,7 +98,7 @@ protected override GraphStageLogic CreateLogic(Attributes inheritedAttributes) /// /// INTERNAL API /// - internal sealed class TakeWhile : SimpleLinearGraphStage + public sealed class TakeWhile : SimpleLinearGraphStage { #region Logic @@ -114,14 +115,14 @@ public Logic(TakeWhile take, Attributes inheritedAttributes) : base(take.Shap try { var element = Grab(take.Inlet); - if(take._predicate(element)) + if (take._predicate(element)) Push(take.Outlet, element); else CompleteStage(); } catch (Exception ex) { - if(decider(ex) == Directive.Stop) + if (decider(ex) == Directive.Stop) FailStage(ex); else Pull(take.Inlet); @@ -152,7 +153,7 @@ protected override GraphStageLogic CreateLogic(Attributes inheritedAttributes) /// /// INTERNAL API /// - internal sealed class SkipWhile : GraphStage> + public sealed class SkipWhile : GraphStage> { #region Logic @@ -185,7 +186,7 @@ public Logic(SkipWhile skip, Attributes inheritedAttributes) : base(inherited protected override void OnResume(Exception ex) { - if(!HasBeenPulled(_skip.In)) + if (!HasBeenPulled(_skip.In)) Pull(_skip.In); } } @@ -213,11 +214,11 @@ protected override GraphStageLogic CreateLogic(Attributes inheritedAttributes) public override string ToString() => "SkipWhile"; } - + /// /// INTERNAL API /// - internal abstract class SupervisedGraphStageLogic : GraphStageLogic + public abstract class SupervisedGraphStageLogic : GraphStageLogic { private readonly Lazy _decider; @@ -268,7 +269,7 @@ protected virtual void OnResume(Exception ex) /// /// INTERNAL API /// - internal sealed class Collect : GraphStage> + public sealed class Collect : GraphStage> { #region Logic @@ -286,19 +287,19 @@ public Logic(Collect collect, Attributes inheritedAttributes) var result = WithSupervision(() => collect._func(Grab(collect.In))); if (result.HasValue) { - if(result.Value.IsDefaultForType()) + if (result.Value.IsDefaultForType()) Pull(collect.In); else Push(collect.Out, result.Value); } }); - SetHandler(collect.Out, onPull: ()=> Pull(collect.In)); + SetHandler(collect.Out, onPull: () => Pull(collect.In)); } protected override void OnResume(Exception ex) { - if(!HasBeenPulled(_collect.In)) + if (!HasBeenPulled(_collect.In)) Pull(_collect.In); } } @@ -330,8 +331,7 @@ protected override GraphStageLogic CreateLogic(Attributes inheritedAttributes) /// /// INTERNAL API /// - - internal sealed class Recover : GraphStage> + public sealed class Recover : GraphStage> { #region Logic @@ -399,11 +399,10 @@ public Recover(Func> recovery) public override string ToString() => "Recover"; } - /// /// INTERNAL API /// - internal sealed class Take : SimpleLinearGraphStage + public sealed class Take : SimpleLinearGraphStage { #region Logic @@ -455,7 +454,7 @@ public Take(long count) /// /// INTERNAL API /// - internal sealed class Drop : SimpleLinearGraphStage + public sealed class Drop : SimpleLinearGraphStage { #region Logic @@ -499,7 +498,7 @@ public Drop(long count) /// /// INTERNAL API /// - internal sealed class Scan : GraphStage> + public sealed class Scan : GraphStage> { #region Logic @@ -540,7 +539,14 @@ public Logic(Scan stage, Attributes inheritedAttributes) : base(stage }; // Initial behavior makes sure that the zero gets flushed if upstream is empty - SetHandler(stage.In, TotallyIgnorantInput); + SetHandler(stage.In, onPush: () => { }, onUpstreamFinish: () => + { + SetHandler(stage.Out, onPull: () => + { + Push(stage.Out, aggregator); + CompleteStage(); + }); + }); SetHandler(stage.Out, onPull: () => { Push(stage.Out, aggregator); @@ -571,7 +577,8 @@ public Scan(TOut zero, Func aggregate) public override FlowShape Shape { get; } - protected override GraphStageLogic CreateLogic(Attributes inheritedAttributes) => new Logic(this, inheritedAttributes); + protected override GraphStageLogic CreateLogic(Attributes inheritedAttributes) + => new Logic(this, inheritedAttributes); public override string ToString() => "Scan"; } @@ -579,39 +586,85 @@ public Scan(TOut zero, Func aggregate) /// /// INTERNAL API /// - internal sealed class Aggregate : PushPullStage + public sealed class Aggregate : GraphStage> { + #region Logic + + private sealed class Logic : SupervisedGraphStageLogic + { + private readonly Aggregate _stage; + private TOut _aggregator; + + public Logic(Aggregate stage, Attributes inheritedAttributes) + : base(inheritedAttributes, stage.Shape) + { + _stage = stage; + _aggregator = _stage._zero; + + SetHandler(stage.In, + onPush: () => + { + var element = WithSupervision(() => Grab(stage.In)); + if (element.HasValue) + _aggregator = _stage._aggregate(_aggregator, element.Value); + + Pull(stage.In); + }, + onUpstreamFinish: () => + { + if (IsAvailable(stage.Out)) + { + Push(stage.Out, _aggregator); + CompleteStage(); + } + }); + + SetHandler(stage.Out, onPull: () => + { + if (IsClosed(stage.In)) + { + Push(stage.Out, _aggregator); + CompleteStage(); + } + else + Pull(stage.In); + }); + } + + protected override void OnResume(Exception ex) => _aggregator = _stage._zero; + } + + #endregion + private readonly TOut _zero; private readonly Func _aggregate; - private readonly Decider _decider; - private TOut _aggregator; - public Aggregate(TOut zero, Func aggregate, Decider decider) + public Aggregate(TOut zero, Func aggregate) { - _zero = _aggregator = zero; + _zero = zero; _aggregate = aggregate; - _decider = decider; - } - public override ISyncDirective OnPush(TIn element, IContext context) - { - _aggregator = _aggregate(_aggregator, element); - return context.Pull(); + Shape = new FlowShape(In, Out); } - public override ISyncDirective OnPull(IContext context) => context.IsFinishing ? (ISyncDirective) context.PushAndFinish(_aggregator) : context.Pull(); + protected override Attributes InitialAttributes { get; } = DefaultAttributes.Aggregate; - public override ITerminationDirective OnUpstreamFinish(IContext context) => context.AbsorbTermination(); + public Inlet In { get; } = new Inlet("Aggregate.in"); - public override Directive Decide(Exception cause) => _decider(cause); + public Outlet Out { get; } = new Outlet("Aggregate.out"); - public override IStage Restart() => new Aggregate(_zero, _aggregate, _decider); + public override FlowShape Shape { get; } + + protected override GraphStageLogic CreateLogic(Attributes inheritedAttributes) + => new Logic(this, inheritedAttributes); + + public override string ToString() => "Aggregate"; } /// /// INTERNAL API /// - internal sealed class Intersperse : GraphStage> + public sealed class Intersperse : GraphStage> { #region internal class @@ -629,7 +682,8 @@ public StartInHandler(Intersperse stage, Logic logic) public override void OnPush() { // if else (to avoid using Iterator[T].flatten in hot code) - if (_stage.InjectStartEnd) _logic.EmitMultiple(_stage.Out, new[] {_stage._start, _logic.Grab(_stage.In)}); + if (_stage.InjectStartEnd) + _logic.EmitMultiple(_stage.Out, new[] {_stage._start, _logic.Grab(_stage.In)}); else _logic.Emit(_stage.Out, _logic.Grab(_stage.In)); _logic.SetHandler(_stage.In, new RestInHandler(_stage, _logic)); } @@ -652,7 +706,8 @@ public RestInHandler(Intersperse stage, Logic logic) _logic = logic; } - public override void OnPush() => _logic.EmitMultiple(_stage.Out, new[] {_stage._inject, _logic.Grab(_stage.In)}); + public override void OnPush() + => _logic.EmitMultiple(_stage.Out, new[] {_stage._inject, _logic.Grab(_stage.In)}); public override void OnUpstreamFinish() { @@ -706,51 +761,84 @@ public Intersperse(T start, T inject, T end) /// /// INTERNAL API /// - internal sealed class Grouped : PushPullStage> + public sealed class Grouped : GraphStage>> { - private readonly int _count; - private List _buffer; - private int _left; + #region Logic - public Grouped(int count) + private sealed class Logic : GraphStageLogic { - _count = _left = count; - _buffer = new List(_count); - } + private readonly Grouped _stage; + private List _buffer; + private int _left; - public override ISyncDirective OnPush(T element, IContext> context) - { - _buffer.Add(element); - _left--; - if (_left == 0) + public Logic(Grouped stage) : base(stage.Shape) { - var result = _buffer; - _buffer = new List(_count); - _left = _count; - return context.Push(result); + _stage = stage; + _buffer = new List(stage._count); + _left = stage._count; + + SetHandler(stage.In, onPush: () => + { + _buffer.Add(Grab(stage.In)); + _left--; + + if (_left == 0) + PushAndClearBuffer(); + else + Pull(stage.In); + }, onUpstreamFinish: () => + { + // This means the buf is filled with some elements but not enough (left < n) to group together. + // Since the upstream has finished we have to push them to downstream though. + if (_left < stage._count) + PushAndClearBuffer(); + + CompleteStage(); + }); + + SetHandler(stage.Out, onPull: () => Pull(stage.In)); } - return context.Pull(); - } - public override ISyncDirective OnPull(IContext> context) - { - if (context.IsFinishing) + private void PushAndClearBuffer() { - var result = _buffer; - _left = _count; - _buffer = new List(_count); - return context.PushAndFinish(result); + var elements = _buffer; + _buffer = new List(_stage._count); + _left = _stage._count; + Push(_stage.Out, elements); } - return context.Pull(); } - public override ITerminationDirective OnUpstreamFinish(IContext> context) => _left == _count ? context.Finish() : context.AbsorbTermination(); + #endregion + + private readonly int _count; + + public Grouped(int count) + { + if (count <= 0) + throw new ArgumentException("count must be greater than 0", nameof(count)); + + _count = count; + + Shape = new FlowShape>(In, Out); + } + + protected override Attributes InitialAttributes { get; } = DefaultAttributes.Grouped; + + public Inlet In { get; } = new Inlet("Grouped.in"); + + public Outlet> Out { get; } = new Outlet>("Grouped.out"); + + public override FlowShape> Shape { get; } + + protected override GraphStageLogic CreateLogic(Attributes inheritedAttributes) => new Logic(this); + + public override string ToString() => "Grouped"; } /// /// INTERNAL API /// - internal sealed class LimitWeighted : GraphStage> + public sealed class LimitWeighted : GraphStage> { #region Logic @@ -759,7 +847,8 @@ private sealed class Logic : SupervisedGraphStageLogic private readonly LimitWeighted _limit; private long _left; - public Logic(LimitWeighted limit, Attributes inheritedAttributes) : base(inheritedAttributes, limit.Shape) + public Logic(LimitWeighted limit, Attributes inheritedAttributes) + : base(inheritedAttributes, limit.Shape) { _limit = limit; _left = limit._max; @@ -816,7 +905,8 @@ public LimitWeighted(long max, Func costFunc) public override FlowShape Shape { get; } - protected override GraphStageLogic CreateLogic(Attributes inheritedAttributes) => new Logic(this, inheritedAttributes); + protected override GraphStageLogic CreateLogic(Attributes inheritedAttributes) + => new Logic(this, inheritedAttributes); public override string ToString() => "LimitWeighted"; } @@ -824,55 +914,91 @@ public LimitWeighted(long max, Func costFunc) /// /// INTERNAL API /// - internal sealed class Sliding : PushPullStage> + public sealed class Sliding : GraphStage>> { + #region Logic + + private sealed class Logic : GraphStageLogic + { + private IImmutableList _buffer; + + public Logic(Sliding stage) : base(stage.Shape) + { + _buffer = ImmutableList.Empty; + + SetHandler(stage.In, onPush: () => + { + _buffer = _buffer.Add(Grab(stage.In)); + if (_buffer.Count < stage._count) + Pull(stage.In); + else if (_buffer.Count == stage._count) + Push(stage.Out, _buffer); + else if (stage._step <= stage._count) + { + _buffer = _buffer.Drop(stage._step).ToImmutableList(); + if (_buffer.Count == stage._count) + Push(stage.Out, _buffer); + else + Pull(stage.In); + } + else if (stage._step > stage._count) + { + if (_buffer.Count == stage._step) + _buffer = _buffer.Drop(stage._step).ToImmutableList(); + Pull(stage.In); + } + }, onUpstreamFinish: () => + { + // We can finish current stage directly if: + // 1. the buf is empty or + // 2. when the step size is greater than the sliding size (step > n) and current stage is in between + // two sliding (ie. buf.size >= n && buf.size < step). + // Otherwise it means there is still a not finished sliding so we have to push them before finish current stage. + if (_buffer.Count < stage._count && _buffer.Count > 0) + Push(stage.Out, _buffer); + + CompleteStage(); + }); + + SetHandler(stage.Out, onPull: () => Pull(stage.In)); + } + } + + #endregion + private readonly int _count; private readonly int _step; - private IImmutableList _buffer; public Sliding(int count, int step) { + if (count <= 0) + throw new ArgumentException("count must be greater than 0", nameof(count)); + if (step <= 0) + throw new ArgumentException("step must be greater than 0", nameof(step)); + _count = count; _step = step; - _buffer = ImmutableList.Empty; + + Shape = new FlowShape>(In, Out); } - public override ISyncDirective OnPush(T element, IContext> context) - { - _buffer = _buffer.Add(element); + protected override Attributes InitialAttributes { get; } = DefaultAttributes.Sliding; - if (_buffer.Count < _count) - return context.Pull(); - if (_buffer.Count == _count) - return context.Push(_buffer); - if (_step > _count) - { - if (_buffer.Count == _step) - _buffer = ImmutableList.Empty; - return context.Pull(); - } + public Inlet In { get; } = new Inlet("Sliding.in"); - _buffer = _buffer.Skip(_step).ToImmutableList(); - return _buffer.Count == _count ? (ISyncDirective) context.Push(_buffer) : context.Pull(); - } + public Outlet> Out { get; } = new Outlet>("Sliding.out"); - public override ISyncDirective OnPull(IContext> context) - { - if (!context.IsFinishing) - return context.Pull(); - if (_buffer.Count >= _count) - return context.Finish(); + public override FlowShape> Shape { get; } - return context.PushAndFinish(_buffer); - } + protected override GraphStageLogic CreateLogic(Attributes inheritedAttributes) => new Logic(this); - public override ITerminationDirective OnUpstreamFinish(IContext> context) => _buffer.Count == 0 ? context.Finish() : context.AbsorbTermination(); + public override string ToString() => "Sliding"; } /// /// INTERNAL API /// - internal sealed class Buffer : DetachedStage + public sealed class Buffer : DetachedStage { private readonly int _count; private readonly Func, T, IUpstreamDirective> _enqueueAction; @@ -884,9 +1010,11 @@ public Buffer(int count, OverflowStrategy overflowStrategy) _enqueueAction = EnqueueAction(overflowStrategy); } - public override void PreStart(ILifecycleContext context) => _buffer = Buffer.Create(_count, context.Materializer); + public override void PreStart(ILifecycleContext context) + => _buffer = Buffer.Create(_count, context.Materializer); - public override IUpstreamDirective OnPush(T element, IDetachedContext context) => context.IsHoldingDownstream ? context.PushAndPull(element) : _enqueueAction(context, element); + public override IUpstreamDirective OnPush(T element, IDetachedContext context) + => context.IsHoldingDownstream ? context.PushAndPull(element) : _enqueueAction(context, element); public override IDownstreamDirective OnPull(IDetachedContext context) { @@ -902,7 +1030,8 @@ public override IDownstreamDirective OnPull(IDetachedContext context) return context.Push(_buffer.Dequeue()); } - public override ITerminationDirective OnUpstreamFinish(IDetachedContext context) => _buffer.IsEmpty ? context.Finish() : context.AbsorbTermination(); + public override ITerminationDirective OnUpstreamFinish(IDetachedContext context) + => _buffer.IsEmpty ? context.Finish() : context.AbsorbTermination(); private Func, T, IUpstreamDirective> EnqueueAction(OverflowStrategy overflowStrategy) { @@ -949,7 +1078,8 @@ private Func, T, IUpstreamDirective> EnqueueAction(OverflowS return (context, element) => { if (_buffer.IsFull) - return context.Fail(new BufferOverflowException($"Buffer overflow (max capacity was {_count})")); + return + context.Fail(new BufferOverflowException($"Buffer overflow (max capacity was {_count})")); _buffer.Enqueue(element); return context.Pull(); }; @@ -962,7 +1092,7 @@ private Func, T, IUpstreamDirective> EnqueueAction(OverflowS /// /// INTERNAL API /// - internal sealed class OnCompleted : PushStage + public sealed class OnCompleted : PushStage { private readonly Action _success; private readonly Action _failure; @@ -991,7 +1121,7 @@ public override ITerminationDirective OnUpstreamFinish(IContext context) /// /// INTERNAL API /// - internal sealed class Batch : GraphStage> + public sealed class Batch : GraphStage> { #region internal classes @@ -1187,13 +1317,14 @@ public Batch(long max, Func costFunc, Func seed, Func Shape { get; } - protected override GraphStageLogic CreateLogic(Attributes inheritedAttributes) => new Logic(inheritedAttributes, this); + protected override GraphStageLogic CreateLogic(Attributes inheritedAttributes) + => new Logic(inheritedAttributes, this); } /// /// INTERNAL API /// - internal sealed class Expand : GraphStage> + public sealed class Expand : GraphStage> { #region internal classes @@ -1288,7 +1419,7 @@ public Expand(Func> extrapolate) /// /// INTERNAL API /// - internal sealed class SelectAsync : GraphStage> + public sealed class SelectAsync : GraphStage> { #region internal classes @@ -1308,7 +1439,9 @@ public Holder(Result element, Action> callback) public void Invoke(Result result) { - Element = result.IsSuccess && result.Value == null ? Result.Failure(ReactiveStreamsCompliance.ElementMustNotBeNullException) : result; + Element = result.IsSuccess && result.Value == null + ? Result.Failure(ReactiveStreamsCompliance.ElementMustNotBeNullException) + : result; _callback(this); } } @@ -1431,13 +1564,14 @@ public SelectAsync(int parallelism, Func> mapFunc) public override FlowShape Shape { get; } - protected override GraphStageLogic CreateLogic(Attributes inheritedAttributes) => new Logic(inheritedAttributes, this); + protected override GraphStageLogic CreateLogic(Attributes inheritedAttributes) + => new Logic(inheritedAttributes, this); } /// /// INTERNAL API /// - internal sealed class SelectAsyncUnordered : GraphStage> + public sealed class SelectAsyncUnordered : GraphStage> { #region internal classes @@ -1471,7 +1605,9 @@ public Logic(Attributes inheritedAttributes, SelectAsyncUnordered sta } else { - var ex = !result.IsSuccess ? result.Exception : ReactiveStreamsCompliance.ElementMustNotBeNullException; + var ex = !result.IsSuccess + ? result.Exception + : ReactiveStreamsCompliance.ElementMustNotBeNullException; if (_decider(ex) == Directive.Stop) FailStage(ex); else if (IsClosed(stage.In) && Todo == 0) @@ -1545,89 +1681,127 @@ public SelectAsyncUnordered(int parallelism, Func> mapFunc) public override FlowShape Shape { get; } - protected override GraphStageLogic CreateLogic(Attributes inheritedAttributes) => new Logic(inheritedAttributes, this); + protected override GraphStageLogic CreateLogic(Attributes inheritedAttributes) + => new Logic(inheritedAttributes, this); } /// /// INTERNAL API /// - internal sealed class Log : PushStage + public sealed class Log : SimpleLinearGraphStage { - private static readonly Attributes.LogLevels DefaultLogLevels = new Attributes.LogLevels(onElement: LogLevel.DebugLevel, onFinish: LogLevel.DebugLevel, onFailure: LogLevel.ErrorLevel); + private static readonly Attributes.LogLevels DefaultLogLevels = new Attributes.LogLevels( + onElement: LogLevel.DebugLevel, + onFinish: LogLevel.DebugLevel, + onFailure: LogLevel.ErrorLevel); - private readonly string _name; - private readonly Func _extract; - private readonly ILoggingAdapter _adapter; - private readonly Decider _decider; - private Attributes.LogLevels _logLevels; - private ILoggingAdapter _log; + #region Logic - public Log(string name, Func extract, ILoggingAdapter adapter, Decider decider) + private sealed class Logic : GraphStageLogic { - _name = name; - _extract = extract; - _adapter = adapter; - _decider = decider; - } + private readonly Log _stage; + private readonly Attributes _inheritedAttributes; + private readonly Decider _decider; + private Attributes.LogLevels _logLevels; + private ILoggingAdapter _log; - public override void PreStart(ILifecycleContext context) - { - _logLevels = context.Attributes.GetAttribute(DefaultLogLevels); - _log = _adapter; - if (_log == null) + public Logic(Log stage, Attributes inheritedAttributes) : base(stage.Shape) { - ActorMaterializer materializer; - try + _stage = stage; + _inheritedAttributes = inheritedAttributes; + _decider = + inheritedAttributes.GetAttribute(new ActorAttributes.SupervisionStrategy(Deciders.StoppingDecider)) + .Decider; + + SetHandler(stage.Inlet, onPush: () => { - materializer = ActorMaterializer.Downcast(context.Materializer); - } - catch (Exception ex) + try + { + var element = Grab(stage.Inlet); + if (IsEnabled(_logLevels.OnElement)) + _log.Log(_logLevels.OnElement, $"[{stage._name}] Element: {stage._extract(element)}"); + + Push(stage.Outlet, element); + } + catch (Exception ex) + { + if (_decider(ex) == Directive.Stop) + FailStage(ex); + else + Pull(stage.Inlet); + } + }, onUpstreamFailure: ex => { - throw new Exception("Log stage can only provide LoggingAdapter when used with ActorMaterializer! Provide a LoggingAdapter explicitly or use the actor based flow materializer.", ex); - } + if (IsEnabled(_logLevels.OnFailure)) + { + if (_logLevels.OnFailure == LogLevel.ErrorLevel) + _log.Error(ex, $"[{stage._name}] Upstream failed."); + else + _log.Log(_logLevels.OnFailure, + $"[{stage._name}] Upstream failed, cause: {ex.GetType()} {ex.Message}"); + } - _log = new BusLogging(materializer.System.EventStream, _name, GetType(), new DefaultLogMessageFormatter()); - } - } + FailStage(ex); + }, onUpstreamFinish: () => + { + if (IsEnabled(_logLevels.OnFinish)) + _log.Log(_logLevels.OnFinish, $"[{stage._name}] Upstream finished."); - public override ISyncDirective OnPush(T element, IContext context) - { - if (IsEnabled(_logLevels.OnElement)) - _log.Log(_logLevels.OnElement, "[{0}] Element: {1}", _name, _extract(element)); + CompleteStage(); + }); - return context.Push(element); - } + SetHandler(stage.Outlet, onPull: ()=> Pull(stage.Inlet), onDownstreamFinish: () => + { + if (IsEnabled(_logLevels.OnFinish)) + _log.Log(_logLevels.OnFinish, $"[{stage._name}] Downstream finished."); - public override ITerminationDirective OnUpstreamFailure(Exception cause, IContext context) - { - if (IsEnabled(_logLevels.OnFailure)) - if (_logLevels.OnFailure == LogLevel.ErrorLevel) - _log.Error(cause, "[{0}] Upstream failed.", _name); + CompleteStage(); + }); + + } + + public override void PreStart() + { + _logLevels = _inheritedAttributes.GetAttribute(DefaultLogLevels); + if (_stage._adapter != null) + _log = _stage._adapter; else - _log.Log(_logLevels.OnFailure, "[{0}] Upstream failed, cause: {1} {2}", _name, cause.GetType(), cause.Message); + { + try + { + var materializer = ActorMaterializerHelper.Downcast(Materializer); + _log = new BusLogging(materializer.System.EventStream, _stage._name, GetType(), new DefaultLogMessageFormatter()); + } + catch (Exception ex) + { + throw new Exception( + "Log stage can only provide LoggingAdapter when used with ActorMaterializer! Provide a LoggingAdapter explicitly or use the actor based flow materializer.", + ex); + } + } + } - return base.OnUpstreamFailure(cause, context); + private bool IsEnabled(LogLevel level) => level != Attributes.LogLevels.Off; } - public override ITerminationDirective OnUpstreamFinish(IContext context) - { - if (IsEnabled(_logLevels.OnFinish)) - _log.Log(_logLevels.OnFinish, "[{0}] Upstream finished.", _name); + #endregion - return base.OnUpstreamFinish(context); - } + private readonly string _name; + private readonly Func _extract; + private readonly ILoggingAdapter _adapter; - public override ITerminationDirective OnDownstreamFinish(IContext context) + public Log(string name, Func extract, ILoggingAdapter adapter) { - if (IsEnabled(_logLevels.OnFinish)) - _log.Log(_logLevels.OnFinish, "[{0}] Downstream finished.", _name); - - return base.OnDownstreamFinish(context); + _name = name; + _extract = extract; + _adapter = adapter; } - public override Directive Decide(Exception cause) => _decider(cause); + // TODO more optimisations can be done here - prepare logOnPush function etc + protected override GraphStageLogic CreateLogic(Attributes inheritedAttributes) + => new Logic(this, inheritedAttributes); - private bool IsEnabled(LogLevel level) => level != Attributes.LogLevels.Off; + public override string ToString() => "Log"; } /// @@ -1643,7 +1817,7 @@ internal enum TimerKeys /// /// INTERNAL API /// - internal sealed class GroupedWithin : GraphStage>> + public sealed class GroupedWithin : GraphStage>> { #region internal classes @@ -1767,7 +1941,7 @@ public GroupedWithin(int count, TimeSpan timeout) /// /// INTERNAL API /// - internal sealed class Delay : SimpleLinearGraphStage + public sealed class Delay : SimpleLinearGraphStage { #region internal classes @@ -1917,7 +2091,7 @@ public Delay(TimeSpan delay, DelayOverflowStrategy strategy) /// /// INTERNAL API /// - internal sealed class TakeWithin : SimpleLinearGraphStage + public sealed class TakeWithin : SimpleLinearGraphStage { #region internal class @@ -1952,7 +2126,7 @@ public TakeWithin(TimeSpan timeout) /// /// INTERNAL API /// - internal sealed class SkipWithin : SimpleLinearGraphStage + public sealed class SkipWithin : SimpleLinearGraphStage { private readonly TimeSpan _timeout; @@ -1994,7 +2168,7 @@ public SkipWithin(TimeSpan timeout) /// /// INTERNAL API /// - internal sealed class Sum : SimpleLinearGraphStage + public sealed class Sum : SimpleLinearGraphStage { #region internal classes @@ -2047,7 +2221,7 @@ public Sum(Func reduce) /// /// INTERNAL API /// - internal sealed class RecoverWith : SimpleLinearGraphStage + public sealed class RecoverWith : SimpleLinearGraphStage { #region internal classes @@ -2139,7 +2313,7 @@ public RecoverWith(Func, TMat>> partialFunct /// /// INTERNAL API /// - internal sealed class StatefulSelectMany : GraphStage> + public sealed class StatefulSelectMany : GraphStage> { #region internal classes @@ -2238,4 +2412,4 @@ public StatefulSelectMany(Func>> concatFactory) public override string ToString() => "StatefulSelectMany"; } -} \ No newline at end of file +} diff --git a/src/core/Akka.Streams/Implementation/Fusing/StreamOfStreams.cs b/src/core/Akka.Streams/Implementation/Fusing/StreamOfStreams.cs index 7d5c87d5a5f..20701f51315 100644 --- a/src/core/Akka.Streams/Implementation/Fusing/StreamOfStreams.cs +++ b/src/core/Akka.Streams/Implementation/Fusing/StreamOfStreams.cs @@ -186,7 +186,7 @@ public Logic(PrefixAndTail stage) : base(stage.Shape) protected internal override void OnTimer(object timerKey) { - var materializer = ActorMaterializer.Downcast(Interpreter.Materializer); + var materializer = ActorMaterializerHelper.Downcast(Interpreter.Materializer); var timeoutSettings = materializer.Settings.SubscriptionTimeoutSettings; var timeout = timeoutSettings.Timeout; @@ -213,7 +213,7 @@ protected internal override void OnTimer(object timerKey) private Source OpenSubstream() { - var timeout = ActorMaterializer.Downcast(Interpreter.Materializer).Settings.SubscriptionTimeoutSettings.Timeout; + var timeout = ActorMaterializerHelper.Downcast(Interpreter.Materializer).Settings.SubscriptionTimeoutSettings.Timeout; _tailSource = new SubSourceOutlet(this, "TailSource"); _tailSource.SetHandler(_subHandler); SetKeepGoing(true); @@ -403,7 +403,7 @@ public Logic(GroupBy stage, Attributes inheritedAttributes) : base(stag ClearNextElement(); } } - else + else if(!HasBeenPulled(_stage.In)) TryPull(_stage.In); } }, @@ -451,7 +451,7 @@ private void Fail(Exception ex) public override void PreStart() { - var settings = ActorMaterializer.Downcast(Interpreter.Materializer).Settings; + var settings = ActorMaterializerHelper.Downcast(Interpreter.Materializer).Settings; _timeout = settings.SubscriptionTimeoutSettings.Timeout; } @@ -771,7 +771,7 @@ public Logic(Split stage) : base(stage.Shape) public override void PreStart() { - var settings = ActorMaterializer.Downcast(Interpreter.Materializer).Settings; + var settings = ActorMaterializerHelper.Downcast(Interpreter.Materializer).Settings; _timeout = settings.SubscriptionTimeoutSettings.Timeout; } diff --git a/src/core/Akka.Streams/Implementation/IO/IOSinks.cs b/src/core/Akka.Streams/Implementation/IO/IOSinks.cs index 19365ad2a4f..470fba74f86 100644 --- a/src/core/Akka.Streams/Implementation/IO/IOSinks.cs +++ b/src/core/Akka.Streams/Implementation/IO/IOSinks.cs @@ -48,7 +48,7 @@ protected override SinkModule> NewInstance(SinkShape< public override object Create(MaterializationContext context, out Task materializer) { - var mat = ActorMaterializer.Downcast(context.Materializer); + var mat = ActorMaterializerHelper.Downcast(context.Materializer); var settings = mat.EffectiveSettings(context.EffectiveAttributes); var ioResultPromise = new TaskCompletionSource(); @@ -88,7 +88,7 @@ protected override SinkModule> NewInstance(SinkShape< public override object Create(MaterializationContext context, out Task materializer) { - var mat = ActorMaterializer.Downcast(context.Materializer); + var mat = ActorMaterializerHelper.Downcast(context.Materializer); var settings = mat.EffectiveSettings(context.EffectiveAttributes); var ioResultPromise = new TaskCompletionSource(); diff --git a/src/core/Akka.Streams/Implementation/IO/IOSources.cs b/src/core/Akka.Streams/Implementation/IO/IOSources.cs index eace0a9a9f8..950ebf110f9 100644 --- a/src/core/Akka.Streams/Implementation/IO/IOSources.cs +++ b/src/core/Akka.Streams/Implementation/IO/IOSources.cs @@ -50,7 +50,7 @@ protected override SourceModule> NewInstance(SourceSh public override IPublisher Create(MaterializationContext context, out Task task) { // FIXME rewrite to be based on GraphStage rather than dangerous downcasts - var materializer = ActorMaterializer.Downcast(context.Materializer); + var materializer = ActorMaterializerHelper.Downcast(context.Materializer); var settings = materializer.EffectiveSettings(context.EffectiveAttributes); var ioResultPromise = new TaskCompletionSource(); @@ -90,7 +90,7 @@ protected override SourceModule> NewInstance(SourceSh public override IPublisher Create(MaterializationContext context, out Task task) { - var materializer = ActorMaterializer.Downcast(context.Materializer); + var materializer = ActorMaterializerHelper.Downcast(context.Materializer); var ioResultPromise = new TaskCompletionSource(); IPublisher pub; diff --git a/src/core/Akka.Streams/Implementation/IO/OutputStreamSourceStage.cs b/src/core/Akka.Streams/Implementation/IO/OutputStreamSourceStage.cs index 802226aaaa2..21828976313 100644 --- a/src/core/Akka.Streams/Implementation/IO/OutputStreamSourceStage.cs +++ b/src/core/Akka.Streams/Implementation/IO/OutputStreamSourceStage.cs @@ -111,7 +111,7 @@ public Logic(OutputStreamSourceStage stage, BlockingCollection dataQ public override void PreStart() { - _dispatcher = ActorMaterializer.Downcast(Materializer).System.Dispatchers.Lookup(_dispatcherId); + _dispatcher = ActorMaterializerHelper.Downcast(Materializer).System.Dispatchers.Lookup(_dispatcherId); base.PreStart(); } diff --git a/src/core/Akka.Streams/Implementation/IO/TcpStages.cs b/src/core/Akka.Streams/Implementation/IO/TcpStages.cs index 36dab5af4e7..b5282a026fc 100644 --- a/src/core/Akka.Streams/Implementation/IO/TcpStages.cs +++ b/src/core/Akka.Streams/Implementation/IO/TcpStages.cs @@ -194,7 +194,7 @@ public ConnectionSourceStage(IActorRef tcpManager, EndPoint endpoint, int backlo /// /// INTERNAL API /// - internal class IncomingConnectionStage : GraphStage> + public class IncomingConnectionStage : GraphStage> { private readonly IActorRef _connection; private readonly EndPoint _remoteAddress; diff --git a/src/core/Akka.Streams/Implementation/Modules.cs b/src/core/Akka.Streams/Implementation/Modules.cs index a249191bfaf..f77af4eb832 100644 --- a/src/core/Akka.Streams/Implementation/Modules.cs +++ b/src/core/Akka.Streams/Implementation/Modules.cs @@ -19,7 +19,10 @@ internal interface ISourceModule IUntypedPublisher Create(MaterializationContext context, out object materializer); } - internal abstract class SourceModule : AtomicModule, ISourceModule + /// + /// INTERNAL API + /// + public abstract class SourceModule : AtomicModule, ISourceModule { private readonly SourceShape _shape; @@ -71,10 +74,11 @@ protected SourceShape AmendShape(Attributes attributes) } /// + /// INTERNAL API /// Holds a `Subscriber` representing the input side of the flow. The `Subscriber` can later be connected to an upstream `Publisher`. /// /// - internal sealed class SubscriberSource : SourceModule> + public sealed class SubscriberSource : SourceModule> { public SubscriberSource(Attributes attributes, SourceShape shape) : base(shape) { @@ -98,12 +102,13 @@ public override IPublisher Create(MaterializationContext context, out ISub } /// + /// INTERNAL API /// Construct a transformation starting with given publisher. The transformation steps are executed /// by a series of instances that mediate the flow of elements /// downstream and the propagation of back-pressure upstream. /// /// - internal sealed class PublisherSource : SourceModule + public sealed class PublisherSource : SourceModule { private readonly IPublisher _publisher; @@ -132,7 +137,10 @@ public override IPublisher Create(MaterializationContext context, out NotU } } - internal sealed class MaybeSource : SourceModule> + /// + /// INTERNAL API + /// + public sealed class MaybeSource : SourceModule> { public MaybeSource(Attributes attributes, SourceShape shape) : base(shape) { @@ -155,10 +163,11 @@ public override IPublisher Create(MaterializationContext context, out Task } /// + /// INTERNAL API /// Creates and wraps an actor into from the given , which should be props for an . /// /// - internal sealed class ActorPublisherSource : SourceModule + public sealed class ActorPublisherSource : SourceModule { private readonly Props _props; @@ -178,13 +187,16 @@ protected override SourceModule NewInstance(SourceShape s public override IPublisher Create(MaterializationContext context, out IActorRef materializer) { - var publisherRef = ActorMaterializer.Downcast(context.Materializer).ActorOf(context, _props); + var publisherRef = ActorMaterializerHelper.Downcast(context.Materializer).ActorOf(context, _props); materializer = publisherRef; return new ActorPublisherImpl(publisherRef); } } - internal sealed class ActorRefSource : SourceModule + /// + /// INTERNAL API + /// + public sealed class ActorRefSource : SourceModule { private readonly int _bufferSize; private readonly OverflowStrategy _overflowStrategy; @@ -210,7 +222,7 @@ protected override SourceModule NewInstance(SourceShape s public override IPublisher Create(MaterializationContext context, out IActorRef materializer) { - var mat = ActorMaterializer.Downcast(context.Materializer); + var mat = ActorMaterializerHelper.Downcast(context.Materializer); materializer = mat.ActorOf(context, ActorRefSourceActor.Props(_bufferSize, _overflowStrategy, mat.Settings)); return new ActorPublisherImpl(materializer); } diff --git a/src/core/Akka.Streams/Implementation/ReactiveStreamsCompliance.cs b/src/core/Akka.Streams/Implementation/ReactiveStreamsCompliance.cs index 599e97437cc..9f497044c50 100644 --- a/src/core/Akka.Streams/Implementation/ReactiveStreamsCompliance.cs +++ b/src/core/Akka.Streams/Implementation/ReactiveStreamsCompliance.cs @@ -162,13 +162,13 @@ public static void RejectDuplicateSubscriber(ISubscriber subscriber) public static void RejectAdditionalSubscriber(ISubscriber subscriber, string rejector) { TryOnSubscribe(subscriber, CancelledSubscription.Instance); - TryOnError(subscriber, new IllegalStateException(rejector + " supports only a single subscriber")); + TryOnError(subscriber, new IllegalStateException(rejector + " " + SupportsOnlyASingleSubscriber)); } internal static void RejectAdditionalSubscriber(IUntypedSubscriber subscriber, string rejector) { TryOnSubscribe(subscriber, CancelledSubscription.Instance); - TryOnError(subscriber, new IllegalStateException(rejector + " supports only a single subscriber")); + TryOnError(subscriber, new IllegalStateException(rejector + " " + SupportsOnlyASingleSubscriber)); } public static void RejectDueToNonPositiveDemand(ISubscriber subscriber) diff --git a/src/core/Akka.Streams/Implementation/Sinks.cs b/src/core/Akka.Streams/Implementation/Sinks.cs index a2794225ff5..0156df079c4 100644 --- a/src/core/Akka.Streams/Implementation/Sinks.cs +++ b/src/core/Akka.Streams/Implementation/Sinks.cs @@ -11,11 +11,15 @@ using Akka.Actor; using Akka.Pattern; using Akka.Streams.Actors; +using Akka.Streams.Dsl; using Akka.Streams.Implementation.Stages; using Akka.Streams.Stage; +using Akka.Streams.Supervision; using Akka.Streams.Util; using Akka.Util; using Reactive.Streams; +using Decider = Akka.Streams.Supervision.Decider; +using Directive = Akka.Streams.Supervision.Directive; namespace Akka.Streams.Implementation { @@ -25,6 +29,9 @@ internal interface ISinkModule object Create(MaterializationContext context, out object materializer); } + /// + /// INTERNAL API + /// public abstract class SinkModule : AtomicModule, ISinkModule { private readonly SinkShape _shape; @@ -64,7 +71,8 @@ public override IModule ReplaceShape(Shape shape) if (Equals(_shape, shape)) return this; - throw new NotSupportedException("cannot replace the shape of a Sink, you need to wrap it in a Graph for that"); + throw new NotSupportedException( + "cannot replace the shape of a Sink, you need to wrap it in a Graph for that"); } public override IModule CarbonCopy() @@ -99,10 +107,10 @@ public PublisherSink(Attributes attributes, SinkShape shape) public override Attributes Attributes { get; } - public override IModule WithAttributes(Attributes attributes) + public override IModule WithAttributes(Attributes attributes) => new PublisherSink(attributes, AmendShape(attributes)); - protected override SinkModule> NewInstance(SinkShape shape) + protected override SinkModule> NewInstance(SinkShape shape) => new PublisherSink(Attributes, shape); /// @@ -138,10 +146,10 @@ protected override SinkModule> NewInstance(SinkShape s public override object Create(MaterializationContext context, out IPublisher materializer) { - var actorMaterializer = ActorMaterializer.Downcast(context.Materializer); + var actorMaterializer = ActorMaterializerHelper.Downcast(context.Materializer); var settings = actorMaterializer.EffectiveSettings(Attributes); var impl = actorMaterializer.ActorOf(context, FanoutProcessorImpl.Props(settings)); - var fanoutProcessor = new ActorProcessor(impl); + var fanoutProcessor = new ActorProcessor(impl); impl.Tell(new ExposedPublisher(fanoutProcessor)); // Resolve cyclic dependency with actor. This MUST be the first message no matter what. materializer = fanoutProcessor; @@ -154,7 +162,7 @@ public override object Create(MaterializationContext context, out IPublisher - internal sealed class SinkholeSink : SinkModule + public sealed class SinkholeSink : SinkModule { public SinkholeSink(SinkShape shape, Attributes attributes) : base(shape) { @@ -182,7 +190,7 @@ public override object Create(MaterializationContext context, out Task materiali /// /// Attaches a subscriber to this stream. /// - internal sealed class SubscriberSink : SinkModule + public sealed class SubscriberSink : SinkModule { private readonly ISubscriber _subscriber; @@ -212,7 +220,7 @@ public override object Create(MaterializationContext context, out NotUsed materi /// /// A sink that immediately cancels its upstream upon materialization. /// - internal sealed class CancelSink : SinkModule + public sealed class CancelSink : SinkModule { public CancelSink(Attributes attributes, SinkShape shape) : base(shape) @@ -222,7 +230,8 @@ public CancelSink(Attributes attributes, SinkShape shape) public override Attributes Attributes { get; } - protected override SinkModule NewInstance(SinkShape shape) => new CancelSink(Attributes, shape); + protected override SinkModule NewInstance(SinkShape shape) + => new CancelSink(Attributes, shape); public override object Create(MaterializationContext context, out NotUsed materializer) { @@ -240,7 +249,7 @@ public override IModule WithAttributes(Attributes attributes) /// Creates and wraps an actor into from the given , /// which should be for an . /// - internal sealed class ActorSubscriberSink : SinkModule + public sealed class ActorSubscriberSink : SinkModule { private readonly Props _props; private readonly Attributes _attributes; @@ -262,7 +271,7 @@ protected override SinkModule NewInstance(SinkShape shape) public override object Create(MaterializationContext context, out IActorRef materializer) { - var subscriberRef = ActorMaterializer.Downcast(context.Materializer).ActorOf(context, _props); + var subscriberRef = ActorMaterializerHelper.Downcast(context.Materializer).ActorOf(context, _props); materializer = subscriberRef; return ActorSubscriber.Create(subscriberRef); } @@ -271,7 +280,7 @@ public override object Create(MaterializationContext context, out IActorRef mate /// /// INTERNAL API /// - internal sealed class ActorRefSink : SinkModule + public sealed class ActorRefSink : SinkModule { private readonly IActorRef _ref; private readonly object _onCompleteMessage; @@ -295,7 +304,7 @@ protected override SinkModule NewInstance(SinkShape shape) public override object Create(MaterializationContext context, out NotUsed materializer) { - var actorMaterializer = ActorMaterializer.Downcast(context.Materializer); + var actorMaterializer = ActorMaterializerHelper.Downcast(context.Materializer); var effectiveSettings = actorMaterializer.EffectiveSettings(context.EffectiveAttributes); var subscriberRef = actorMaterializer.ActorOf(context, ActorRefSinkActor.Props(_ref, effectiveSettings.MaxInputBufferSize, _onCompleteMessage)); @@ -305,9 +314,13 @@ public override object Create(MaterializationContext context, out NotUsed materi } } - internal sealed class LastOrDefaultStage : GraphStageWithMaterializedValue, Task> + /// + /// INTERNAL API + /// + public sealed class LastOrDefaultStage : GraphStageWithMaterializedValue, Task> { #region stage logic + private sealed class Logic : GraphStageLogic { private readonly LastOrDefaultStage _stage; @@ -318,27 +331,28 @@ public Logic(TaskCompletionSource promise, LastOrDefaultStage stage) : bas var prev = default(T); SetHandler(stage.In, onPush: () => - { - prev = Grab(stage.In); - Pull(stage.In); - }, - onUpstreamFinish: () => - { - var head = prev; - prev = default(T); - promise.TrySetResult(head); - CompleteStage(); - }, - onUpstreamFailure: cause => - { - prev = default(T); - promise.TrySetException(cause); - FailStage(cause); - }); + { + prev = Grab(stage.In); + Pull(stage.In); + }, + onUpstreamFinish: () => + { + var head = prev; + prev = default(T); + promise.TrySetResult(head); + CompleteStage(); + }, + onUpstreamFailure: cause => + { + prev = default(T); + promise.TrySetException(cause); + FailStage(cause); + }); } public override void PreStart() => Pull(_stage.In); } + #endregion public readonly Inlet In = new Inlet("LastOrDefault.in"); @@ -350,16 +364,21 @@ public LastOrDefaultStage() public override SinkShape Shape { get; } - public override ILogicAndMaterializedValue> CreateLogicAndMaterializedValue(Attributes inheritedAttributes) + public override ILogicAndMaterializedValue> CreateLogicAndMaterializedValue( + Attributes inheritedAttributes) { var promise = new TaskCompletionSource(); return new LogicAndMaterializedValue>(new Logic(promise, this), promise.Task); } } - internal sealed class FirstOrDefaultStage : GraphStageWithMaterializedValue, Task> + /// + /// INTERNAL API + /// + public sealed class FirstOrDefaultStage : GraphStageWithMaterializedValue, Task> { #region stage logic + private sealed class Logic : GraphStageLogic { private readonly FirstOrDefaultStage _stage; @@ -369,24 +388,25 @@ public Logic(TaskCompletionSource promise, FirstOrDefaultStage stage) : ba _stage = stage; SetHandler(stage.In, onPush: () => - { - promise.TrySetResult(Grab(stage.In)); - CompleteStage(); - }, - onUpstreamFinish: () => - { - promise.TrySetResult(default(T)); - CompleteStage(); - }, - onUpstreamFailure: cause => - { - promise.TrySetException(cause); - FailStage(cause); - }); + { + promise.TrySetResult(Grab(stage.In)); + CompleteStage(); + }, + onUpstreamFinish: () => + { + promise.TrySetResult(default(T)); + CompleteStage(); + }, + onUpstreamFailure: cause => + { + promise.TrySetException(cause); + FailStage(cause); + }); } public override void PreStart() => Pull(_stage.In); } + #endregion public readonly Inlet In = new Inlet("FirstOrDefault.in"); @@ -398,30 +418,34 @@ public FirstOrDefaultStage() public override SinkShape Shape { get; } - public override ILogicAndMaterializedValue> CreateLogicAndMaterializedValue(Attributes inheritedAttributes) + public override ILogicAndMaterializedValue> CreateLogicAndMaterializedValue( + Attributes inheritedAttributes) { var promise = new TaskCompletionSource(); return new LogicAndMaterializedValue>(new Logic(promise, this), promise.Task); } } - internal sealed class SeqStage : GraphStageWithMaterializedValue, Task>> + /// + /// INTERNAL API + /// + public sealed class SeqStage : GraphStageWithMaterializedValue, Task>> { #region stage logic private sealed class Logic : GraphStageLogic { private readonly SeqStage _stage; - private IImmutableList _buf = ImmutableList.Empty; + private IImmutableList _buf = ImmutableList.Empty; public Logic(SeqStage stage, TaskCompletionSource> promise) : base(stage.Shape) { _stage = stage; - SetHandler(stage._in, onPush: () => + SetHandler(stage.In, onPush: () => { - _buf = _buf.Add(Grab(stage._in)); - Pull(stage._in); + _buf = _buf.Add(Grab(stage.In)); + Pull(stage.In); }, onUpstreamFinish: () => { promise.TrySetResult(_buf); @@ -433,23 +457,24 @@ public Logic(SeqStage stage, TaskCompletionSource> promise) }); } - public override void PreStart() => Pull(_stage._in); + public override void PreStart() => Pull(_stage.In); } #endregion - private readonly Inlet _in = new Inlet("Seq.in"); - public SeqStage() { - Shape = new SinkShape(_in); + Shape = new SinkShape(In); } protected override Attributes InitialAttributes { get; } = DefaultAttributes.SeqSink; public override SinkShape Shape { get; } - public override ILogicAndMaterializedValue>> CreateLogicAndMaterializedValue(Attributes inheritedAttributes) + public readonly Inlet In = new Inlet("Seq.in"); + + public override ILogicAndMaterializedValue>> CreateLogicAndMaterializedValue( + Attributes inheritedAttributes) { var promise = new TaskCompletionSource>(); return new LogicAndMaterializedValue>>(new Logic(this, promise), promise.Task); @@ -458,15 +483,19 @@ public override ILogicAndMaterializedValue>> CreateLogicA public override string ToString() => "SeqStage"; } - internal class QueueSink : GraphStageWithMaterializedValue, ISinkQueue> + /// + /// INTERNAL API + /// + public sealed class QueueSink : GraphStageWithMaterializedValue, ISinkQueue> { #region stage logic + private sealed class Logic : GraphStageLogicWithCallbackWrapper>> { private readonly QueueSink _stage; private readonly int _maxBuffer; private IBuffer>> _buffer; - private Option>>_currentRequest; + private Option>> _currentRequest; public Logic(QueueSink stage, int maxBuffer) : base(stage.Shape) { @@ -495,7 +524,9 @@ public override void PreStart() public override void PostStop() { - StopCallback(promise => promise.SetException(new IllegalStateException("Stream is terminated. QueueSink is detached"))); + StopCallback( + promise => + promise.SetException(new IllegalStateException("Stream is terminated. QueueSink is detached"))); } private Action>> Callback() @@ -566,6 +597,7 @@ public Task> PullAsync() return promise.Task; } } + #endregion public readonly Inlet In = new Inlet("QueueSink.in"); @@ -579,7 +611,8 @@ public QueueSink() public override SinkShape Shape { get; } - public override ILogicAndMaterializedValue> CreateLogicAndMaterializedValue(Attributes inheritedAttributes) + public override ILogicAndMaterializedValue> CreateLogicAndMaterializedValue( + Attributes inheritedAttributes) { var maxBuffer = inheritedAttributes.GetAttribute(new Attributes.InputBuffer(16, 16)).Max; if (maxBuffer <= 0) @@ -591,4 +624,170 @@ public override ILogicAndMaterializedValue> CreateLogicAndMateria public override string ToString() => "QueueSink"; } + + /// + /// INTERNAL API + /// + internal sealed class LazySink : GraphStageWithMaterializedValue, Task> + { + #region Logic + + private sealed class Logic : GraphStageLogic + { + private readonly LazySink _stage; + private readonly TaskCompletionSource _completion; + private readonly Lazy _decider; + + public Logic(LazySink stage, Attributes inheritedAttributes, + TaskCompletionSource completion) : base(stage.Shape) + { + _stage = stage; + _completion = completion; + _decider = new Lazy(() => + { + var attr = inheritedAttributes.GetAttribute(null); + return attr != null ? attr.Decider : Deciders.StoppingDecider; + }); + + SetHandler(stage.In, onPush: () => + { + try + { + var element = Grab(_stage.In); + var callback = GetAsyncCallback>>(result => + { + if (result.IsSuccess) + InitInternalSource(result.Value, element); + else + Failure(result.Exception); + }); + _stage._sinkFactory(element) + .ContinueWith(t => callback(Result.FromTask(t)), + TaskContinuationOptions.ExecuteSynchronously); + } + catch (Exception ex) + { + if (_decider.Value(ex) == Directive.Stop) + Failure(ex); + else + Pull(_stage.In); + } + + }, onUpstreamFinish: () => + { + CompleteStage(); + try + { + _completion.TrySetResult(_stage._zeroMaterialised()); + } + catch (Exception ex) + { + _completion.SetException(ex); + } + }, onUpstreamFailure: Failure); + } + + public override void PreStart() => Pull(_stage.In); + + private void Failure(Exception ex) + { + FailStage(ex); + _completion.SetException(ex); + } + + private void InitInternalSource(Sink sink, TIn firstElement) + { + var sourceOut = new SubSource(this, firstElement); + _completion.TrySetResult(Source.FromGraph(sourceOut.Source) + .RunWith(sink, Interpreter.SubFusingMaterializer)); + } + + #region SubSource + + private sealed class SubSource : SubSourceOutlet + { + private readonly Logic _logic; + private readonly LazySink _stage; + private bool _completed; + + public SubSource(Logic logic, TIn firstElement) : base(logic, "LazySink") + { + _logic = logic; + _stage = logic._stage; + + SetHandler(new LambdaOutHandler(onPull: () => + { + Push(firstElement); + if (_completed) + SourceComplete(); + else + SwitchToFinalHandler(); + }, onDownstreamFinish: SourceComplete)); + + logic.SetHandler(_stage.In, new LambdaInHandler( + onPush: () => Push(logic.Grab(_stage.In)), + onUpstreamFinish: () => + { + logic.SetKeepGoing(true); + _completed = true; + }, + onUpstreamFailure: SourceFailure)); + } + + private void SourceFailure(Exception ex) + { + Fail(ex); + _logic.FailStage(ex); + } + + private void SwitchToFinalHandler() + { + SetHandler(new LambdaOutHandler( + onPull: () => _logic.Pull(_stage.In), + onDownstreamFinish: SourceComplete)); + + _logic.SetHandler(_stage.In, new LambdaInHandler( + onPush: () => Push(_logic.Grab(_stage.In)), + onUpstreamFinish: SourceComplete, + onUpstreamFailure: SourceFailure)); + } + + private void SourceComplete() + { + Complete(); + _logic.CompleteStage(); + } + } + + #endregion + } + + #endregion + + private readonly Func>> _sinkFactory; + private readonly Func _zeroMaterialised; + + public LazySink(Func>> sinkFactory, Func zeroMaterialised) + { + _sinkFactory = sinkFactory; + _zeroMaterialised = zeroMaterialised; + + Shape = new SinkShape(In); + } + + protected override Attributes InitialAttributes { get; } = DefaultAttributes.LazySink; + + public Inlet In { get; } = new Inlet("lazySink.in"); + + public override SinkShape Shape { get; } + + public override ILogicAndMaterializedValue> CreateLogicAndMaterializedValue(Attributes inheritedAttributes) + { + var completion = new TaskCompletionSource(); + var stageLogic = new Logic(this, inheritedAttributes, completion); + return new LogicAndMaterializedValue>(stageLogic, completion.Task); + } + + public override string ToString() => "LazySink"; + } } \ No newline at end of file diff --git a/src/core/Akka.Streams/Implementation/Sources.cs b/src/core/Akka.Streams/Implementation/Sources.cs index cffada9ed9f..b4b8783f624 100644 --- a/src/core/Akka.Streams/Implementation/Sources.cs +++ b/src/core/Akka.Streams/Implementation/Sources.cs @@ -19,11 +19,11 @@ namespace Akka.Streams.Implementation /// /// INTERNAL API /// - internal sealed class QueueSource : GraphStageWithMaterializedValue, ISourceQueueWithComplete> + public sealed class QueueSource : GraphStageWithMaterializedValue, ISourceQueueWithComplete> { #region internal classes - internal interface IInput { } + public interface IInput { } internal sealed class Offer : IInput { @@ -313,7 +313,7 @@ public override ILogicAndMaterializedValue> Creat /// /// INTERNAL API /// - internal sealed class UnfoldResourceSource : GraphStage> + public sealed class UnfoldResourceSource : GraphStage> { #region Logic @@ -426,7 +426,7 @@ public UnfoldResourceSource(Func create, Func> re /// /// INTERNAL API /// - internal sealed class UnfoldResourceSourceAsync : GraphStage> + public sealed class UnfoldResourceSourceAsync : GraphStage> { #region Logic diff --git a/src/core/Akka.Streams/Implementation/Stages/Stages.cs b/src/core/Akka.Streams/Implementation/Stages/Stages.cs index 5068aba04e4..7f541d6a74c 100644 --- a/src/core/Akka.Streams/Implementation/Stages/Stages.cs +++ b/src/core/Akka.Streams/Implementation/Stages/Stages.cs @@ -9,14 +9,12 @@ using System.Collections.Generic; using System.Threading.Tasks; using Akka.Event; -using Akka.Streams.Dsl; using Akka.Streams.Stage; using Akka.Streams.Supervision; -using Reactive.Streams; namespace Akka.Streams.Implementation.Stages { - internal static class DefaultAttributes + public static class DefaultAttributes { public static readonly Attributes IODispatcher = ActorAttributes.CreateDispatcher("akka.stream.default-blocking-io-dispatcher"); @@ -115,6 +113,7 @@ internal static class DefaultAttributes public static readonly Attributes ActorRefWithAck = Attributes.CreateName("actorRefWithAckSink"); public static readonly Attributes ActorSubscriberSink = Attributes.CreateName("actorSubscriberSink"); public static readonly Attributes QueueSink = Attributes.CreateName("queueSink"); + public static readonly Attributes LazySink = Attributes.CreateName("lazySink"); public static readonly Attributes InputStreamSink = Attributes.CreateName("inputStreamSink").And(IODispatcher); public static readonly Attributes OutputStreamSink = Attributes.CreateName("outputStreamSink").And(IODispatcher); public static readonly Attributes FileSink = Attributes.CreateName("fileSink").And(IODispatcher); @@ -124,21 +123,21 @@ internal static class DefaultAttributes /// /// Stage that is backed by a GraphStage but can be symbolically introspected /// - internal sealed class SymbolicGraphStage : PushPullGraphStage + public sealed class SymbolicGraphStage : PushPullGraphStage { public SymbolicGraphStage(ISymbolicStage symbolicStage) : base(symbolicStage.Create, symbolicStage.Attributes) { } } - internal interface ISymbolicStage : IStage + public interface ISymbolicStage : IStage { Attributes Attributes { get; } IStage Create(Attributes effectiveAttributes); } - internal abstract class SymbolicStage : ISymbolicStage + public abstract class SymbolicStage : ISymbolicStage { protected SymbolicStage(Attributes attributes) { @@ -153,7 +152,7 @@ protected Decider Supervision(Attributes attributes) => attributes.GetAttribute(new ActorAttributes.SupervisionStrategy(Deciders.StoppingDecider)).Decider; } - internal sealed class Select : SymbolicStage + public sealed class Select : SymbolicStage { private readonly Func _mapper; @@ -166,68 +165,7 @@ public override IStage Create(Attributes effectiveAttributes) => new Fusing.Select(_mapper, Supervision(effectiveAttributes)); } - internal sealed class Log : SymbolicStage - { - private readonly string _name; - private readonly Func _extract; - private readonly ILoggingAdapter _loggingAdapter; - - public Log(string name, Func extract, ILoggingAdapter loggingAdapter, Attributes attributes = null) : base(attributes ?? DefaultAttributes.Log) - { - _name = name; - _extract = extract; - _loggingAdapter = loggingAdapter; - } - - public override IStage Create(Attributes effectiveAttributes) - => new Fusing.Log(_name, _extract, _loggingAdapter, Supervision(effectiveAttributes)); - } - - internal sealed class Grouped : SymbolicStage> - { - private readonly int _count; - - public Grouped(int count, Attributes attributes = null) : base(attributes ?? DefaultAttributes.Grouped) - { - if (count <= 0) throw new ArgumentException("Grouped count must be greater than 0", nameof(count)); - _count = count; - } - - public override IStage> Create(Attributes effectiveAttributes) => new Fusing.Grouped(_count); - } - - internal sealed class Sliding : SymbolicStage> - { - private readonly int _count; - private readonly int _step; - - public Sliding(int count, int step, Attributes attributes = null) : base(attributes ?? DefaultAttributes.Sliding) - { - if (count <= 0) throw new ArgumentException("Sliding count must be greater than 0", nameof(count)); - if (step <= 0) throw new ArgumentException("Sliding step must be greater than 0", nameof(step)); - _count = count; - _step = step; - } - - public override IStage> Create(Attributes effectiveAttributes) => new Fusing.Sliding(_count, _step); - } - - internal sealed class Aggregate : SymbolicStage - { - private readonly TOut _zero; - private readonly Func _aggregate; - - public Aggregate(TOut zero, Func aggregate, Attributes attributes = null) : base(attributes ?? DefaultAttributes.Aggregate) - { - _zero = zero; - _aggregate = aggregate; - } - - public override IStage Create(Attributes effectiveAttributes) - => new Fusing.Aggregate(_zero, _aggregate, Supervision(effectiveAttributes)); - } - - internal sealed class Buffer : SymbolicStage + public sealed class Buffer : SymbolicStage { private readonly int _size; private readonly OverflowStrategy _overflowStrategy; @@ -241,7 +179,7 @@ public Buffer(int size, OverflowStrategy overflowStrategy, Attributes attributes public override IStage Create(Attributes effectiveAttributes) => new Fusing.Buffer(_size, _overflowStrategy); } - internal sealed class FirstOrDefault : GraphStageWithMaterializedValue, Task> + public sealed class FirstOrDefault : GraphStageWithMaterializedValue, Task> { #region internal classes @@ -305,7 +243,7 @@ public override ILogicAndMaterializedValue> CreateLogicAndMaterialized public override string ToString() => "FirstOrDefaultStage"; } - internal sealed class LastOrDefault : GraphStageWithMaterializedValue, Task> + public sealed class LastOrDefault : GraphStageWithMaterializedValue, Task> { #region internal classes diff --git a/src/core/Akka.Streams/Implementation/StreamLayout.cs b/src/core/Akka.Streams/Implementation/StreamLayout.cs index eb413dc9130..e30f232fb28 100644 --- a/src/core/Akka.Streams/Implementation/StreamLayout.cs +++ b/src/core/Akka.Streams/Implementation/StreamLayout.cs @@ -1442,7 +1442,10 @@ public void RegisterPublisher(IPublisher publisher) } } - internal abstract class MaterializerSession + /// + /// INTERNAL API + /// + public abstract class MaterializerSession { public static readonly bool IsDebug = false; @@ -1503,7 +1506,7 @@ protected MaterializerSession(IModule topLevel, Attributes initialAttributes) /// of the same module. /// We don't store the enclosing CopiedModule itself as state since we don't use it anywhere else than exit and enter /// - private void EnterScope(CopiedModule enclosing) + protected void EnterScope(CopiedModule enclosing) { if(IsDebug) Console.WriteLine($"entering scope [{GetHashCode()}%08x]"); @@ -1519,7 +1522,7 @@ private void EnterScope(CopiedModule enclosing) /// leading to port identity collisions) /// We don't store the enclosing CopiedModule itself as state since we don't use it anywhere else than exit and enter /// - private void ExitScope(CopiedModule enclosing) + protected void ExitScope(CopiedModule enclosing) { var scopeSubscribers = Subscribers; var scopePublishers = Publishers; @@ -1765,7 +1768,10 @@ internal interface IProcessorModule Tuple CreateProcessor(); } - internal sealed class ProcessorModule : AtomicModule, IProcessorModule + /// + /// INTERNAL API + /// + public sealed class ProcessorModule : AtomicModule, IProcessorModule { private readonly Func, TMat>> _createProcessor; diff --git a/src/core/Akka.Streams/Implementation/Throttle.cs b/src/core/Akka.Streams/Implementation/Throttle.cs index 184d5b9bec9..a0acbc149fe 100644 --- a/src/core/Akka.Streams/Implementation/Throttle.cs +++ b/src/core/Akka.Streams/Implementation/Throttle.cs @@ -13,7 +13,10 @@ namespace Akka.Streams.Implementation { - internal class Throttle : SimpleLinearGraphStage + /// + /// INTERNAL API + /// + public class Throttle : SimpleLinearGraphStage { #region stage logic diff --git a/src/core/Akka.Streams/Implementation/Timers.cs b/src/core/Akka.Streams/Implementation/Timers.cs index f3e51b18fdc..e7c446b6d68 100644 --- a/src/core/Akka.Streams/Implementation/Timers.cs +++ b/src/core/Akka.Streams/Implementation/Timers.cs @@ -23,7 +23,7 @@ namespace Akka.Streams.Implementation /// - if the timer fires before the event happens, these stages all fail the stream /// - otherwise, these streams do not interfere with the element flow, ordinary completion or failure /// - internal static class Timers + public static class Timers { public static TimeSpan IdleTimeoutCheckInterval(TimeSpan timeout) => new TimeSpan(Math.Min(Math.Max(timeout.Ticks/8, 100*TimeSpan.TicksPerMillisecond), timeout.Ticks/2)); @@ -31,7 +31,10 @@ public static TimeSpan IdleTimeoutCheckInterval(TimeSpan timeout) public const string GraphStageLogicTimer = "GraphStageLogicTimer"; } - internal sealed class Initial : SimpleLinearGraphStage + /// + /// INTERNAL API + /// + public sealed class Initial : SimpleLinearGraphStage { #region Logic @@ -77,7 +80,10 @@ public Initial(TimeSpan timeout) public override string ToString() => "InitialTimeoutTimer"; } - internal sealed class Completion : SimpleLinearGraphStage + /// + /// INTERNAL API + /// + public sealed class Completion : SimpleLinearGraphStage { #region stage logic @@ -114,7 +120,10 @@ public Completion(TimeSpan timeout) public override string ToString() => "CompletionTimeout"; } - internal sealed class Idle : SimpleLinearGraphStage + /// + /// INTERNAL API + /// + public sealed class Idle : SimpleLinearGraphStage { #region stage logic @@ -162,7 +171,10 @@ public Idle(TimeSpan timeout) public override string ToString() => "IdleTimeout"; } - internal sealed class BackpressureTimeout : SimpleLinearGraphStage + /// + /// INTERNAL API + /// + public sealed class BackpressureTimeout : SimpleLinearGraphStage { #region stage logic @@ -216,7 +228,10 @@ public BackpressureTimeout(TimeSpan timeout) public override string ToString() => "BackpressureTimeout"; } - internal sealed class IdleTimeoutBidi : GraphStage> + /// + /// INTERNAL API + /// + public sealed class IdleTimeoutBidi : GraphStage> { #region Logic @@ -289,7 +304,10 @@ public IdleTimeoutBidi(TimeSpan timeout) public override string ToString() => "IdleTimeoutBidi"; } - internal sealed class DelayInitial : GraphStage> + /// + /// INTERNAL API + /// + public sealed class DelayInitial : GraphStage> { #region stage logic @@ -346,7 +364,10 @@ public DelayInitial(TimeSpan delay) public override string ToString() => "DelayTimer"; } - internal sealed class IdleInject : GraphStage> where TIn : TOut + /// + /// INTERNAL API + /// + public sealed class IdleInject : GraphStage> where TIn : TOut { #region Logic diff --git a/src/core/Akka.Streams/Implementation/Transfer.cs b/src/core/Akka.Streams/Implementation/Transfer.cs index 67bf60e45cb..121e651a7c5 100644 --- a/src/core/Akka.Streams/Implementation/Transfer.cs +++ b/src/core/Akka.Streams/Implementation/Transfer.cs @@ -11,7 +11,7 @@ namespace Akka.Streams.Implementation { - internal class SubReceive + public class SubReceive { private Receive _currentReceive; @@ -78,7 +78,7 @@ public static TransferState NeedsDemandOrCancel(IOutputs outputs) => new LambdaTransferState(() => outputs.IsDemandAvailable || outputs.IsClosed, () => false); } - internal abstract class TransferState + public abstract class TransferState { public abstract bool IsReady { get; } public abstract bool IsCompleted { get; } @@ -158,7 +158,7 @@ private Always() public override bool IsCompleted => false; } - internal struct TransferPhase + public struct TransferPhase { public readonly TransferState Precondition; public readonly Action Action; @@ -170,7 +170,7 @@ public TransferPhase(TransferState precondition, Action action) : this() } } - internal interface IPump + public interface IPump { TransferState TransferState { get; set; } Action CurrentAction { get; set; } diff --git a/src/core/Akka.Streams/Implementation/Unfold.cs b/src/core/Akka.Streams/Implementation/Unfold.cs index 9316ed8c875..8b1874c916c 100644 --- a/src/core/Akka.Streams/Implementation/Unfold.cs +++ b/src/core/Akka.Streams/Implementation/Unfold.cs @@ -12,7 +12,10 @@ namespace Akka.Streams.Implementation { - internal class Unfold : GraphStage> + /// + /// INTERNAL API + /// + public class Unfold : GraphStage> { #region internal classes private sealed class Logic : GraphStageLogic @@ -55,7 +58,10 @@ public Unfold(TState state, Func> unfoldFunc) protected override GraphStageLogic CreateLogic(Attributes inheritedAttributes) => new Logic(this); } - internal class UnfoldAsync : GraphStage> + /// + /// INTERNAL API + /// + public class UnfoldAsync : GraphStage> { #region stage logic private sealed class Logic : GraphStageLogic diff --git a/src/core/Akka.Streams/Implementation/UntypedPublisher.cs b/src/core/Akka.Streams/Implementation/UntypedPublisher.cs index 15245490f02..c897e6836c1 100644 --- a/src/core/Akka.Streams/Implementation/UntypedPublisher.cs +++ b/src/core/Akka.Streams/Implementation/UntypedPublisher.cs @@ -10,7 +10,7 @@ namespace Akka.Streams { - internal interface IUntypedPublisher + public interface IUntypedPublisher { void Subscribe(IUntypedSubscriber subscriber); } diff --git a/src/core/Akka.Streams/Implementation/UntypedSubscriber.cs b/src/core/Akka.Streams/Implementation/UntypedSubscriber.cs index 37f50819d5e..41bb57c445b 100644 --- a/src/core/Akka.Streams/Implementation/UntypedSubscriber.cs +++ b/src/core/Akka.Streams/Implementation/UntypedSubscriber.cs @@ -11,7 +11,7 @@ namespace Akka.Streams { - internal interface IUntypedSubscriber + public interface IUntypedSubscriber { void OnSubscribe(ISubscription subscription); void OnNext(object element); diff --git a/src/core/Akka.Streams/Stage/GraphStage.cs b/src/core/Akka.Streams/Stage/GraphStage.cs index e2257c2d439..db5fb639f40 100644 --- a/src/core/Akka.Streams/Stage/GraphStage.cs +++ b/src/core/Akka.Streams/Stage/GraphStage.cs @@ -86,6 +86,7 @@ protected GraphStageWithMaterializedValue() } protected virtual Attributes InitialAttributes => Attributes.None; + public abstract TShape Shape { get; } public IGraph WithAttributes(Attributes attributes) => new Graph(Shape, Module, attributes); @@ -1186,7 +1187,7 @@ protected StageActorRef GetStageActorRef(StageActorRef.Receive receive) { if (_stageActorRef == null) { - var actorMaterializer = ActorMaterializer.Downcast(Interpreter.Materializer); + var actorMaterializer = ActorMaterializerHelper.Downcast(Interpreter.Materializer); var provider = ((IInternalActorRef)actorMaterializer.Supervisor).Provider; var path = actorMaterializer.Supervisor.Path / StageActorRef.Name.Next(); _stageActorRef = new StageActorRef(provider, actorMaterializer.Logger, r => GetAsyncCallback>(tuple => r(tuple)), receive, path);