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); } } }
/// <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); }
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); }