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