private void ForwardOrDelay(ByteString payload)
 {
     if (InboundThrottleMode is Blackhole)
     {
         // Do nothing
     }
     else
     {
         if (!ThrottledMessages.Any())
         {
             var tokens    = payload.Length;
             var res       = InboundThrottleMode.TryConsumeTokens(SystemNanoTime.GetNanos(), tokens);
             var newBucket = res.Item1;
             var success   = res.Item2;
             if (success)
             {
                 InboundThrottleMode = newBucket;
                 UpstreamListener.Notify(new InboundPayload(payload));
             }
             else
             {
                 ThrottledMessages.Enqueue(payload);
                 ScheduleDequeue(InboundThrottleMode.TimeToAvailable(SystemNanoTime.GetNanos(), tokens));
             }
         }
         else
         {
             ThrottledMessages.Enqueue(payload);
         }
     }
 }
 private Task <SetThrottleAck> SetMode(ThrottlerHandle handle, ThrottleMode mode,
                                       ThrottleTransportAdapter.Direction direction)
 {
     if (direction == ThrottleTransportAdapter.Direction.Both ||
         direction == ThrottleTransportAdapter.Direction.Send)
     {
         handle.OutboundThrottleMode.Value = mode;
     }
     if (direction == ThrottleTransportAdapter.Direction.Both ||
         direction == ThrottleTransportAdapter.Direction.Receive)
     {
         return(AskModeWithDeathCompletion(handle.ThrottlerActor, mode, ActorTransportAdapter.AskTimeout));
     }
     else
     {
         return(Task.FromResult(SetThrottleAck.Instance));
     }
 }
        private Task <SetThrottleAck> AskModeWithDeathCompletion(IActorRef target, ThrottleMode mode, TimeSpan timeout)
        {
            if (target.IsNobody())
            {
                return(Task.FromResult(SetThrottleAck.Instance));
            }
            else
            {
                return(target.Ask <SetThrottleAck>(mode, timeout));

                //TODO: use PromiseActorRef here when implemented
                //var internalTarget = target.AsInstanceOf<InternalActorRef>();
                //var promiseRef = PromiseActorRef.Apply(internalTarget.Provider, timeout, target, mode.GetType().Name);
                //internalTarget.Tell(new Watch(internalTarget, promiseRef));
                //target.Tell(mode, promiseRef);
                //return promiseRef.Result.Task.ContinueWith(tr =>
                //{
                //    if (tr.Result is Status.Success)
                //    {
                //        var resultMsg = tr.Result as Status.Success;
                //        if (resultMsg.Status is Terminated &&
                //            resultMsg.Status.AsInstanceOf<Terminated>().ActorRef.Path == target.Path)
                //            return SetThrottleAck.Instance;
                //        if (resultMsg.Status is SetThrottleAck)
                //        {
                //            internalTarget.Tell(new Unwatch(target, promiseRef));
                //        }
                //        return SetThrottleAck.Instance;
                //    }
                //    else
                //    {
                //        internalTarget.Tell(new Unwatch(target, promiseRef));
                //       return SetThrottleAck.Instance;
                //    }
                //}, TaskContinuationOptions.AttachedToParent & TaskContinuationOptions.ExecuteSynchronously);
            }
        }
Beispiel #4
0
 /// <summary>
 /// TBD
 /// </summary>
 /// <param name="handleEventListener">TBD</param>
 /// <param name="mode">TBD</param>
 public ListenerAndMode(IHandleEventListener handleEventListener, ThrottleMode mode)
 {
     Mode = mode;
     HandleEventListener = handleEventListener;
 }
 public SetThrottle(Address address, ThrottleTransportAdapter.Direction direction, ThrottleMode mode)
 {
     _address = address;
     _direction = direction;
     _mode = mode;
 }
        private void InitializeFSM()
        {
            When(ThrottlerState.WaitExposedHandle, @event =>
            {
                if (@event.FsmEvent is ThrottlerManager.Handle && @event.StateData is Uninitialized)
                {
                    // register to downstream layer and wait for origin
                    OriginalHandle.ReadHandlerSource.SetResult(new ActorHandleEventListener(Self));
                    return
                    (GoTo(ThrottlerState.WaitOrigin)
                     .Using(
                         new ExposedHandle(
                             @event.FsmEvent.AsInstanceOf <ThrottlerManager.Handle>().ThrottlerHandle)));
                }
                return(null);
            });

            When(ThrottlerState.WaitOrigin, @event =>
            {
                if (@event.FsmEvent is InboundPayload && @event.StateData is ExposedHandle)
                {
                    var b = @event.FsmEvent.AsInstanceOf <InboundPayload>().Payload;
                    ThrottledMessages.Enqueue(b);
                    var origin = PeekOrigin(b);
                    if (origin != null)
                    {
                        Manager.Tell(new ThrottlerManager.Checkin(origin, @event.StateData.AsInstanceOf <ExposedHandle>().Handle));
                        return(GoTo(ThrottlerState.WaitMode));
                    }
                    return(Stay());
                }
                return(null);
            });

            When(ThrottlerState.WaitMode, @event =>
            {
                if (@event.FsmEvent is InboundPayload)
                {
                    var b = @event.FsmEvent.AsInstanceOf <InboundPayload>().Payload;
                    ThrottledMessages.Enqueue(b);
                    return(Stay());
                }

                if (@event.FsmEvent is ThrottleMode && @event.StateData is ExposedHandle)
                {
                    var mode            = @event.FsmEvent.AsInstanceOf <ThrottleMode>();
                    var exposedHandle   = @event.StateData.AsInstanceOf <ExposedHandle>().Handle;
                    InboundThrottleMode = mode;
                    try
                    {
                        if (mode is Blackhole)
                        {
                            ThrottledMessages = new Queue <ByteString>();
                            exposedHandle.Disassociate();
                            return(Stop());
                        }
                        else
                        {
                            AssociationHandler.Notify(new InboundAssociation(exposedHandle));
                            var self = Self;
                            exposedHandle.ReadHandlerSource.Task.ContinueWith(
                                r => new ThrottlerManager.Listener(r.Result),
                                TaskContinuationOptions.AttachedToParent & TaskContinuationOptions.ExecuteSynchronously)
                            .PipeTo(self);
                            return(GoTo(ThrottlerState.WaitUpstreamListener));
                        }
                    }
                    finally
                    {
                        Sender.Tell(SetThrottleAck.Instance);
                    }
                }

                return(null);
            });

            When(ThrottlerState.WaitUpstreamListener, @event =>
            {
                if (@event.FsmEvent is InboundPayload)
                {
                    var b = @event.FsmEvent.AsInstanceOf <InboundPayload>();
                    ThrottledMessages.Enqueue(b.Payload);
                    return(Stay());
                }

                if (@event.FsmEvent is ThrottlerManager.Listener)
                {
                    UpstreamListener = @event.FsmEvent.AsInstanceOf <ThrottlerManager.Listener>().HandleEventListener;
                    Self.Tell(new Dequeue());
                    return(GoTo(ThrottlerState.Throttling));
                }

                return(null);
            });

            When(ThrottlerState.WaitModeAndUpstreamListener, @event =>
            {
                if (@event.FsmEvent is ThrottlerManager.ListenerAndMode)
                {
                    var listenerAndMode = @event.FsmEvent.AsInstanceOf <ThrottlerManager.ListenerAndMode>();
                    UpstreamListener    = listenerAndMode.HandleEventListener;
                    InboundThrottleMode = listenerAndMode.Mode;
                    Self.Tell(new Dequeue());
                    return(GoTo(ThrottlerState.Throttling));
                }

                if (@event.FsmEvent is InboundPayload)
                {
                    var b = @event.FsmEvent.AsInstanceOf <InboundPayload>();
                    ThrottledMessages.Enqueue(b.Payload);
                    return(Stay());
                }

                return(null);
            });

            When(ThrottlerState.Throttling, @event =>
            {
                if (@event.FsmEvent is ThrottleMode)
                {
                    var mode            = @event.FsmEvent.AsInstanceOf <ThrottleMode>();
                    InboundThrottleMode = mode;
                    if (mode is Blackhole)
                    {
                        ThrottledMessages = new Queue <ByteString>();
                    }
                    CancelTimer(DequeueTimerName);
                    if (ThrottledMessages.Any())
                    {
                        ScheduleDequeue(InboundThrottleMode.TimeToAvailable(SystemNanoTime.GetNanos(), ThrottledMessages.Peek().Length));
                    }
                    Sender.Tell(SetThrottleAck.Instance);
                    return(Stay());
                }

                if (@event.FsmEvent is InboundPayload)
                {
                    ForwardOrDelay(@event.FsmEvent.AsInstanceOf <InboundPayload>().Payload);
                    return(Stay());
                }

                if (@event.FsmEvent is Dequeue)
                {
                    if (ThrottledMessages.Any())
                    {
                        var payload = ThrottledMessages.Dequeue();
                        UpstreamListener.Notify(new InboundPayload(payload));
                        InboundThrottleMode = InboundThrottleMode.TryConsumeTokens(SystemNanoTime.GetNanos(),
                                                                                   payload.Length).Item1;
                        if (ThrottledMessages.Any())
                        {
                            ScheduleDequeue(InboundThrottleMode.TimeToAvailable(SystemNanoTime.GetNanos(), ThrottledMessages.Peek().Length));
                        }
                    }
                    return(Stay());
                }

                return(null);
            });

            WhenUnhandled(@event =>
            {
                // we should always set the throttling mode
                if (@event.FsmEvent is ThrottleMode)
                {
                    InboundThrottleMode = @event.FsmEvent.AsInstanceOf <ThrottleMode>();
                    Sender.Tell(SetThrottleAck.Instance);
                    return(Stay());
                }

                if (@event.FsmEvent is Disassociated)
                {
                    return(Stop()); // not notifying the upstream handler is intentional: we are relying on heartbeating
                }

                if (@event.FsmEvent is FailWith)
                {
                    var reason = @event.FsmEvent.AsInstanceOf <FailWith>().FailReason;
                    if (UpstreamListener != null)
                    {
                        UpstreamListener.Notify(new Disassociated(reason));
                    }
                    return(Stop());
                }

                return(null);
            });

            if (Inbound)
            {
                StartWith(ThrottlerState.WaitExposedHandle, Uninitialized.Instance);
            }
            else
            {
                OriginalHandle.ReadHandlerSource.SetResult(new ActorHandleEventListener(Self));
                StartWith(ThrottlerState.WaitModeAndUpstreamListener, Uninitialized.Instance);
            }
        }
 public SetThrottle(Address address, ThrottleTransportAdapter.Direction direction, ThrottleMode mode)
 {
     _address   = address;
     _direction = direction;
     _mode      = mode;
 }