Esempio n. 1
0
 private void Complete()
 {
     // No need to complete if had already been cancelled, or we closed earlier
     if (!(_upstreamCompleted || _downstreamCompleted))
     {
         _upstreamCompleted = true;
         if (!ReferenceEquals(_exposedPublisher, null))
         {
             _exposedPublisher.Shutdown(null);
         }
         if (!ReferenceEquals(_subscriber, null))
         {
             ReactiveStreamsCompliance.TryOnComplete(_subscriber);
         }
     }
 }
Esempio n. 2
0
            public void Fail(Exception reason)
            {
                // No need to fail if had already been cancelled, or we closed earlier
                if (!(_downstreamCompleted || _upstreamCompleted))
                {
                    _upstreamCompleted = true;
                    _upstreamFailed    = reason;

                    if (!ReferenceEquals(_exposedPublisher, null))
                    {
                        _exposedPublisher.Shutdown(reason);
                    }
                    if (!ReferenceEquals(_subscriber, null) && !(reason is ISpecViolation))
                    {
                        ReactiveStreamsCompliance.TryOnError(_subscriber, reason);
                    }
                }
            }
Esempio n. 3
0
 public void SubscribePending()
 {
     foreach (var subscriber in _exposedPublisher.TakePendingSubscribers())
     {
         if (ReferenceEquals(_subscriber, null))
         {
             _subscriber = subscriber;
             ReactiveStreamsCompliance.TryOnSubscribe(_subscriber, new BoundarySubscription(_actor, _shell, _id));
             if (GraphInterpreter.IsDebug)
             {
                 Console.WriteLine($"{Interpreter.Name} Subscribe subscriber={subscriber}");
             }
         }
         else
         {
             ReactiveStreamsCompliance.RejectAdditionalSubscriber(subscriber, GetType().FullName);
         }
     }
 }
Esempio n. 4
0
            private object Dequeue()
            {
                var element = _inputBuffer[_nextInputElementCursor];

                if (element == null)
                {
                    throw new IllegalStateException("Internal queue must never contain a null");
                }
                _inputBuffer[_nextInputElementCursor] = null;

                _batchRemaining--;
                if (_batchRemaining == 0 && !_upstreamCompleted)
                {
                    ReactiveStreamsCompliance.TryRequest(_upstream, _requestBatchSize);
                    _batchRemaining = _requestBatchSize;
                }

                _inputBufferElements--;
                _nextInputElementCursor = (_nextInputElementCursor + 1) & _indexMask;
                return(element);
            }
Esempio n. 5
0
 public void OnSubscribe(ISubscription subscription)
 {
     if (subscription == null)
     {
         throw new ArgumentException("Subscription cannot be null");
     }
     if (_upstreamCompleted)
     {
         ReactiveStreamsCompliance.TryCancel(subscription);
     }
     else if (_downstreamCanceled)
     {
         _upstreamCompleted = true;
         ReactiveStreamsCompliance.TryCancel(subscription);
     }
     else
     {
         _upstream = subscription;
         // prefetch
         ReactiveStreamsCompliance.TryRequest(_upstream, _inputBuffer.Length);
     }
 }
Esempio n. 6
0
 /// <summary>
 /// <para>
 /// Complete the stream. After that you are not allowed to
 /// call <see cref="OnNext"/>, <see cref="OnError"/> and <see cref="OnComplete"/>.
 /// </para>
 /// <para>
 /// After signalling completion the Actor will then stop itself as it has completed the protocol.
 /// When <see cref="OnComplete"/> is called before any <see cref="ISubscriber{T}"/> has had the chance to subscribe
 /// to this <see cref="ActorPublisher{T}"/> the completion signal (and therefore stopping of the Actor as well)
 /// will be delayed until such <see cref="ISubscriber{T}"/> arrives.
 /// </para>
 /// </summary>
 public void OnCompleteThenStop()
 {
     switch (_lifecycleState)
     {
         case LifecycleState.Active:
         case LifecycleState.PreSubscriber:
             _lifecycleState = LifecycleState.CompleteThenStop;
             _onError = null;
             if (_subscriber != null)
             {
                 // otherwise onComplete will be called when the subscription arrives
                 try
                 {
                     ReactiveStreamsCompliance.TryOnComplete(_subscriber);
                 }
                 finally
                 {
                     Context.Stop(Self);
                 }
             }
             break;
         default: OnComplete(); break;
     }
 }
Esempio n. 7
0
 public void OnNext(T element)
 {
     ReactiveStreamsCompliance.RequireNonNullElement(element);
     _parent.Tell(new OnNext(_shell, _id, element));
 }
Esempio n. 8
0
 public void OnError(Exception cause)
 {
     ReactiveStreamsCompliance.RequireNonNullException(cause);
     _parent.Tell(new OnError(_shell, _id, cause));
 }
Esempio n. 9
0
        protected override bool AroundReceive(Receive receive, object message)
        {
            if (message is Request)
            {
                var req = (Request)message;
                if (req.Count < 1)
                {
                    if (_lifecycleState == LifecycleState.Active)
                    {
                        OnError(new ArgumentException("Number of requested elements must be positive. Rule 3.9"));
                    }
                    else
                    {
                        base.AroundReceive(receive, message);
                    }
                }
                else
                {
                    _demand += req.Count;
                    if (_demand < 0)
                    {
                        _demand = long.MaxValue;              // long overflow: effectively unbounded
                    }
                    base.AroundReceive(receive, message);
                }
            }
            else if (message is Subscribe <T> )
            {
                var sub        = (Subscribe <T>)message;
                var subscriber = sub.Subscriber;
                switch (_lifecycleState)
                {
                case LifecycleState.PreSubscriber:
                    _scheduledSubscriptionTimeout.Cancel();
                    _subscriber     = subscriber;
                    _lifecycleState = LifecycleState.Active;
                    ReactiveStreamsCompliance.TryOnSubscribe(subscriber, new ActorPublisherSubscription(Self));
                    break;

                case LifecycleState.ErrorEmitted:
                    if (_onError.Stop)
                    {
                        Context.Stop(Self);
                    }
                    ReactiveStreamsCompliance.TryOnSubscribe(subscriber, CancelledSubscription.Instance);
                    ReactiveStreamsCompliance.TryOnError(subscriber, _onError.Cause);
                    break;

                case LifecycleState.Completed:
                    ReactiveStreamsCompliance.TryOnSubscribe(subscriber, CancelledSubscription.Instance);
                    ReactiveStreamsCompliance.TryOnComplete(subscriber);
                    break;

                case LifecycleState.CompleteThenStop:
                    Context.Stop(Self);
                    ReactiveStreamsCompliance.TryOnSubscribe(subscriber, CancelledSubscription.Instance);
                    ReactiveStreamsCompliance.TryOnComplete(subscriber);
                    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"));
                    break;
                }
            }
            else if (message is Cancel)
            {
                CancelSelf();
                base.AroundReceive(receive, message);
            }
            else if (message is SubscriptionTimeoutExceeded)
            {
                if (!_scheduledSubscriptionTimeout.IsCancellationRequested)
                {
                    CancelSelf();
                    base.AroundReceive(receive, message);
                }
            }
            else
            {
                return(base.AroundReceive(receive, message));
            }
            return(true);
        }
Esempio n. 10
0
 public void Receive(ActorGraphInterpreter.IBoundaryEvent e)
 {
     if (_waitingForShutdown)
     {
         if (e is ActorGraphInterpreter.ExposedPublisher)
         {
             var exposedPublisher = (ActorGraphInterpreter.ExposedPublisher)e;
             _outputs[exposedPublisher.Id].ExposedPublisher(exposedPublisher.Publisher);
             _publishersPending--;
             if (CanShutdown)
             {
                 IsTerminated = true;
             }
         }
         else if (e is ActorGraphInterpreter.OnSubscribe)
         {
             var onSubscribe = (ActorGraphInterpreter.OnSubscribe)e;
             ReactiveStreamsCompliance.TryCancel(onSubscribe.Subscription);
             _subscribersPending--;
             if (CanShutdown)
             {
                 IsTerminated = true;
             }
         }
         else if (e is ActorGraphInterpreter.Abort)
         {
             TryAbort(new TimeoutException(
                          $"Streaming actor has been already stopped processing (normally), but not all of its inputs or outputs have been subscribed in [{_settings.SubscriptionTimeoutSettings.Timeout}]. Aborting actor now."));
         }
     }
     else
     {
         // Cases that are most likely on the hot path, in decreasing order of frequency
         if (e is ActorGraphInterpreter.OnNext)
         {
             var onNext = (ActorGraphInterpreter.OnNext)e;
             if (GraphInterpreter.IsDebug)
             {
                 Console.WriteLine($"{Interpreter.Name}  OnNext {onNext.Event} id={onNext.Id}");
             }
             _inputs[onNext.Id].OnNext(onNext.Event);
             RunBatch();
         }
         else if (e is ActorGraphInterpreter.RequestMore)
         {
             var requestMore = (ActorGraphInterpreter.RequestMore)e;
             if (GraphInterpreter.IsDebug)
             {
                 Console.WriteLine($"{Interpreter.Name}  Request {requestMore.Demand} id={requestMore.Id}");
             }
             _outputs[requestMore.Id].RequestMore(requestMore.Demand);
             RunBatch();
         }
         else if (e is ActorGraphInterpreter.Resume)
         {
             if (GraphInterpreter.IsDebug)
             {
                 Console.WriteLine($"{Interpreter.Name}  Resume");
             }
             _resumeScheduled = false;
             if (Interpreter.IsSuspended)
             {
                 RunBatch();
             }
         }
         else if (e is ActorGraphInterpreter.AsyncInput)
         {
             var asyncInput = (ActorGraphInterpreter.AsyncInput)e;
             Interpreter.RunAsyncInput(asyncInput.Logic, asyncInput.Event, asyncInput.Handler);
             RunBatch();
         }
         // Initialization and completion messages
         else if (e is ActorGraphInterpreter.OnError)
         {
             var onError = (ActorGraphInterpreter.OnError)e;
             if (GraphInterpreter.IsDebug)
             {
                 Console.WriteLine($"{Interpreter.Name}  OnError id={onError.Id}");
             }
             _inputs[onError.Id].OnError(onError.Cause);
             RunBatch();
         }
         else if (e is ActorGraphInterpreter.OnComplete)
         {
             var onComplete = (ActorGraphInterpreter.OnComplete)e;
             if (GraphInterpreter.IsDebug)
             {
                 Console.WriteLine($"{Interpreter.Name}  OnComplete id={onComplete.Id}");
             }
             _inputs[onComplete.Id].OnComplete();
             RunBatch();
         }
         else if (e is ActorGraphInterpreter.OnSubscribe)
         {
             var onSubscribe = (ActorGraphInterpreter.OnSubscribe)e;
             if (GraphInterpreter.IsDebug)
             {
                 Console.WriteLine($"{Interpreter.Name}  OnSubscribe id={onSubscribe.Id}");
             }
             _subscribersPending--;
             _inputs[onSubscribe.Id].OnSubscribe(onSubscribe.Subscription);
             RunBatch();
         }
         else if (e is ActorGraphInterpreter.Cancel)
         {
             var cancel = (ActorGraphInterpreter.Cancel)e;
             if (GraphInterpreter.IsDebug)
             {
                 Console.WriteLine($"{Interpreter.Name}  Cancel id={cancel.Id}");
             }
             _outputs[cancel.Id].Cancel();
             RunBatch();
         }
         else if (e is ActorGraphInterpreter.SubscribePending)
         {
             var subscribePending = (ActorGraphInterpreter.SubscribePending)e;
             _outputs[subscribePending.Id].SubscribePending();
         }
         else if (e is ActorGraphInterpreter.ExposedPublisher)
         {
             var exposedPublisher = (ActorGraphInterpreter.ExposedPublisher)e;
             _publishersPending--;
             _outputs[exposedPublisher.Id].ExposedPublisher(exposedPublisher.Publisher);
         }
     }
 }
Esempio n. 11
0
 /// <summary>
 /// TBD
 /// </summary>
 /// <param name="task">TBD</param>
 public TaskSource(Task <T> task)
 {
     ReactiveStreamsCompliance.RequireNonNullElement(task);
     _task = task;
     Shape = new SourceShape <T>(Outlet);
 }
Esempio n. 12
0
 /// <summary>
 /// TBD
 /// </summary>
 /// <param name="element">TBD</param>
 public SingleSource(T element)
 {
     ReactiveStreamsCompliance.RequireNonNullElement(element);
     _element = element;
     Shape    = new SourceShape <T>(Outlet);
 }
Esempio n. 13
0
        /// <summary>
        /// TBD
        /// </summary>
        /// <param name="receive">TBD</param>
        /// <param name="message">TBD</param>
        /// <returns>TBD</returns>
        protected internal override bool AroundReceive(Receive receive, object message)
        {
            if (message is Request)
            {
                var req = (Request)message;
                if (req.IsProcessed)
                {
                    // it's an unstashed Request, demand is already handled
                    base.AroundReceive(receive, req);
                }
                else
                {
                    if (req.Count < 1)
                    {
                        if (_lifecycleState == LifecycleState.Active)
                        {
                            OnError(new ArgumentException("Number of requested elements must be positive. Rule 3.9"));
                        }
                    }
                    else
                    {
                        _demand += req.Count;
                        if (_demand < 0)
                        {
                            _demand = long.MaxValue; // long overflow: effectively unbounded
                        }
                        req.MarkProcessed();
                        base.AroundReceive(receive, message);
                    }
                }
            }
            else if (message is Subscribe <T> )
            {
                var sub        = (Subscribe <T>)message;
                var subscriber = sub.Subscriber;
                switch (_lifecycleState)
                {
                case LifecycleState.PreSubscriber:
                    _scheduledSubscriptionTimeout.Cancel();
                    _subscriber     = subscriber;
                    _lifecycleState = LifecycleState.Active;
                    ReactiveStreamsCompliance.TryOnSubscribe(subscriber, new ActorPublisherSubscription(Self));
                    break;

                case LifecycleState.ErrorEmitted:
                    if (_onError.Stop)
                    {
                        Context.Stop(Self);
                    }
                    ReactiveStreamsCompliance.TryOnSubscribe(subscriber, CancelledSubscription.Instance);
                    ReactiveStreamsCompliance.TryOnError(subscriber, _onError.Cause);
                    break;

                case LifecycleState.Completed:
                    ReactiveStreamsCompliance.TryOnSubscribe(subscriber, CancelledSubscription.Instance);
                    ReactiveStreamsCompliance.TryOnComplete(subscriber);
                    break;

                case LifecycleState.CompleteThenStop:
                    Context.Stop(Self);
                    ReactiveStreamsCompliance.TryOnSubscribe(subscriber, CancelledSubscription.Instance);
                    ReactiveStreamsCompliance.TryOnComplete(subscriber);
                    break;

                case LifecycleState.Active:
                case LifecycleState.Canceled:
                    if (_subscriber == subscriber)
                    {
                        ReactiveStreamsCompliance.RejectDuplicateSubscriber(subscriber);
                    }
                    else
                    {
                        ReactiveStreamsCompliance.RejectAdditionalSubscriber(subscriber, "ActorPublisher");
                    }
                    break;
                }
            }
            else if (message is Cancel)
            {
                if (_lifecycleState != LifecycleState.Canceled)
                {
                    // possible to receive again in case of stash
                    CancelSelf();
                    base.AroundReceive(receive, message);
                }
            }
            else if (message is SubscriptionTimeoutExceeded)
            {
                if (!_scheduledSubscriptionTimeout.IsCancellationRequested)
                {
                    CancelSelf();
                    base.AroundReceive(receive, message);
                }
            }
            else
            {
                return(base.AroundReceive(receive, message));
            }
            return(true);
        }
Esempio n. 14
0
 public TaskFlattenSource(Task <Source <T, M> > taskSource)
 {
     ReactiveStreamsCompliance.RequireNonNullElement(taskSource);
     _taskSource = taskSource;
     Shape       = new SourceShape <T>(Outlet);
 }
Esempio n. 15
0
 private void OnNext(T element)
 {
     _downstreamDemand--;
     ReactiveStreamsCompliance.TryOnNext(_subscriber, element);
 }
Esempio n. 16
0
            public TcpStreamLogic(FlowShape <ByteString, ByteString> shape, ITcpRole role, EndPoint remoteAddress) : base(shape)
            {
                _role          = role;
                _remoteAddress = remoteAddress;
                _bytesIn       = shape.Inlet;
                _bytesOut      = shape.Outlet;

                _readHandler = new LambdaOutHandler(
                    onPull: () => _connection.Tell(Tcp.ResumeReading.Instance, StageActorRef),
                    onDownstreamFinish: () =>
                {
                    if (!IsClosed(_bytesIn))
                    {
                        _connection.Tell(Tcp.ResumeReading.Instance, StageActorRef);
                    }
                    else
                    {
                        _connection.Tell(Tcp.Abort.Instance, StageActorRef);
                        CompleteStage();
                    }
                });

                // No reading until role have been decided
                SetHandler(_bytesOut, onPull: DoNothing);
                SetHandler(_bytesIn,
                           onPush: () =>
                {
                    var elem = Grab(_bytesIn);
                    ReactiveStreamsCompliance.RequireNonNullElement(elem);
                    _connection.Tell(Tcp.Write.Create(elem, WriteAck.Instance), StageActorRef);
                },
                           onUpstreamFinish: () =>
                {
                    // Reading has stopped before, either because of cancel, or PeerClosed, so just Close now
                    // (or half-close is turned off)
                    if (IsClosed(_bytesOut) || !_role.HalfClose)
                    {
                        _connection.Tell(Tcp.Close.Instance, StageActorRef);
                    }
                    // We still read, so we only close the write side
                    else if (_connection != null)
                    {
                        _connection.Tell(Tcp.ConfirmedClose.Instance, StageActorRef);
                    }
                    else
                    {
                        CompleteStage();
                    }
                },
                           onUpstreamFailure: ex =>
                {
                    if (_connection != null)
                    {
                        if (Interpreter.Log.IsDebugEnabled)
                        {
                            Interpreter.Log.Debug(
                                $"Aborting tcp connection to {_remoteAddress} because of upstream failure: {ex.Message}\n{ex.StackTrace}");
                        }
                        _connection.Tell(Tcp.Abort.Instance, StageActorRef);
                    }
                    else
                    {
                        FailStage(ex);
                    }
                });
            }
Esempio n. 17
0
 public void OnSubscribe(ISubscription subscription)
 {
     ReactiveStreamsCompliance.RequireNonNullSubscription(subscription);
     _parent.Tell(new OnSubscribe(_shell, _id, subscription));
 }