public abstract Associate ( Akka.Actor.Address remoteAddress ) : Task |
||
remoteAddress | Akka.Actor.Address | The address of the remote transport entity. |
return | Task |
protected override void Ready(object message) { if (message is InboundAssociation) { var ia = message as InboundAssociation; var wrappedHandle = WrapHandle(ia.Association, associationListener, true); wrappedHandle.ThrottlerActor.Tell(new Handle(wrappedHandle)); } else if (message is AssociateUnderlying) { var ua = message as AssociateUnderlying; // Slight modification of PipeTo, only success is sent, failure is propagated to a separate Task var associateTask = WrappedTransport.Associate(ua.RemoteAddress); var self = Self; associateTask.ContinueWith(tr => { if (tr.IsFaulted) { ua.StatusPromise.SetException(tr.Exception ?? new Exception("association failed")); } else { self.Tell(new AssociateResult(tr.Result, ua.StatusPromise)); } }, TaskContinuationOptions.AttachedToParent & TaskContinuationOptions.ExecuteSynchronously); } else if (message is AssociateResult) // Finished outbound association and got back the handle { var ar = message as AssociateResult; var wrappedHandle = WrapHandle(ar.AssociationHandle, associationListener, false); var naked = NakedAddress(ar.AssociationHandle.RemoteAddress); var inMode = GetInboundMode(naked); wrappedHandle.OutboundThrottleMode.Value = GetOutboundMode(naked); wrappedHandle.ReadHandlerSource.Task.ContinueWith(tr => new ListenerAndMode(tr.Result, inMode), TaskContinuationOptions.AttachedToParent & TaskContinuationOptions.ExecuteSynchronously) .PipeTo(wrappedHandle.ThrottlerActor); _handleTable.Add(Tuple.Create(naked, wrappedHandle)); ar.StatusPromise.SetResult(wrappedHandle); } else if (message is SetThrottle) { var st = message as SetThrottle; var naked = NakedAddress(st.Address); _throttlingModes[naked] = new Tuple <ThrottleMode, ThrottleTransportAdapter.Direction>(st.Mode, st.Direction); var ok = Task.FromResult(SetThrottleAck.Instance); var modes = new List <Task <SetThrottleAck> >() { ok }; foreach (var handle in _handleTable) { if (handle.Item1 == naked) { modes.Add(SetMode(handle.Item2, st.Mode, st.Direction)); } } var sender = Sender; Task.WhenAll(modes).ContinueWith(tr => { return(SetThrottleAck.Instance); }, TaskContinuationOptions.AttachedToParent & TaskContinuationOptions.ExecuteSynchronously) .PipeTo(sender); } else if (message is ForceDisassociate) { var fd = message as ForceDisassociate; var naked = NakedAddress(fd.Address); foreach (var handle in _handleTable) { if (handle.Item1 == naked) { handle.Item2.Disassociate(); } } /* * NOTE: Important difference between Akka.NET and Akka here. * In canonical Akka, ThrottleHandlers are never removed from * the _handleTable. The reason is because Ask-ing a terminated ActorRef * doesn't cause any exceptions to be thrown upstream - it just times out * and propagates a failed Future. * * In the CLR, a CancellationException gets thrown and causes all * parent tasks chaining back to the EndPointManager to fail due * to an Ask timeout. * * So in order to avoid this problem, we remove any disassociated handles * from the _handleTable. * * Questions? Ask @Aaronontheweb */ _handleTable.RemoveAll(tuple => tuple.Item1 == naked); Sender.Tell(ForceDisassociateAck.Instance); } else if (message is ForceDisassociateExplicitly) { var fde = message as ForceDisassociateExplicitly; var naked = NakedAddress(fde.Address); foreach (var handle in _handleTable) { if (handle.Item1 == naked) { handle.Item2.DisassociateWithFailure(fde.Reason); } } /* * NOTE: Important difference between Akka.NET and Akka here. * In canonical Akka, ThrottleHandlers are never removed from * the _handleTable. The reason is because Ask-ing a terminated ActorRef * doesn't cause any exceptions to be thrown upstream - it just times out * and propagates a failed Future. * * In the CLR, a CancellationException gets thrown and causes all * parent tasks chaining back to the EndPointManager to fail due * to an Ask timeout. * * So in order to avoid this problem, we remove any disassociated handles * from the _handleTable. * * Questions? Ask @Aaronontheweb */ _handleTable.RemoveAll(tuple => tuple.Item1 == naked); Sender.Tell(ForceDisassociateAck.Instance); } else if (message is Checkin) { var chkin = message as Checkin; var naked = NakedAddress(chkin.Origin); _handleTable.Add(new Tuple <Address, ThrottlerHandle>(naked, chkin.ThrottlerHandle)); SetMode(naked, chkin.ThrottlerHandle); } }