protected bool DefaultReceive(object message) { if (message is Subscribe) { var subscribe = (Subscribe)message; Context.Watch(subscribe.Ref); Subscribers.Add(subscribe.Ref); PruneDeadline = null; Context.Parent.Tell(new Subscribed(new SubscribeAck(subscribe), Sender)); } else if (message is Unsubscribe) { var unsubscribe = (Unsubscribe)message; Context.Unwatch(unsubscribe.Ref); Remove(unsubscribe.Ref); Context.Parent.Tell(new Unsubscribed(new UnsubscribeAck(unsubscribe), Sender)); } else if (message is Terminated) { var terminated = (Terminated)message; Remove(terminated.ActorRef); } else if (message is Prune) { if (PruneDeadline != null && PruneDeadline.IsOverdue) { PruneDeadline = null; Context.Parent.Tell(NoMoreSubscribers.Instance); } } else if (message is TerminateRequest) { if (Subscribers.Count == 0 && !Context.GetChildren().Any()) { Context.Stop(Self); } else { Context.Parent.Tell(NewSubscriberArrived.Instance); } } else { foreach (var subscriber in Subscribers) subscriber.Forward(message); } return true; }
/// <summary> /// Marking an endpoint as failed means that we will not try to connect to the remote system within /// the gated period but it is ok for the remote system to try to connect with us (inbound-only.) /// </summary> /// <param name="endpoint">TBD</param> /// <param name="timeOfRelease">TBD</param> public void MarkAsFailed(IActorRef endpoint, Deadline timeOfRelease) { if (IsWritable(endpoint)) { var address = _writableToAddress[endpoint]; if (_addressToWritable.TryGetValue(address, out var policy)) { if (policy is EndpointManager.Quarantined) { // don't overwrite Quarantined with Gated } else if (policy is EndpointManager.Pass) { _addressToWritable[address] = new EndpointManager.Gated(timeOfRelease, policy.AsInstanceOf <EndpointManager.Pass>().RefuseUid); _writableToAddress.Remove(endpoint); } else if (policy is EndpointManager.WasGated) { _addressToWritable[address] = new EndpointManager.Gated(timeOfRelease, policy.AsInstanceOf <EndpointManager.WasGated>().RefuseUid); _writableToAddress.Remove(endpoint); } else if (policy is EndpointManager.Gated) { // already gated } } else { _addressToWritable[address] = new EndpointManager.Gated(timeOfRelease, null); _writableToAddress.Remove(endpoint); } } else if (IsReadOnly(endpoint)) { _addressToReadonly.Remove(_readonlyToAddress[endpoint]); _readonlyToAddress.Remove(endpoint); } }
protected bool DefaultReceive(object message) { if (message is Subscribe) { var subscribe = (Subscribe)message; Context.Watch(subscribe.Ref); Subscribers.Add(subscribe.Ref); PruneDeadline = null; Context.Parent.Tell(new Subscribed(new SubscribeAck(subscribe), Sender)); } else if (message is Unsubscribe) { var unsubscribe = (Unsubscribe)message; Context.Unwatch(unsubscribe.Ref); Remove(unsubscribe.Ref); Context.Parent.Tell(new Unsubscribed(new UnsubscribeAck(unsubscribe), Sender)); } else if (message is Terminated) { var terminated = (Terminated)message; Remove(terminated.ActorRef); } else if (message is Prune) { if (PruneDeadline != null && PruneDeadline.IsOverdue) Context.Stop(Self); } else { foreach (var subscriber in Subscribers) subscriber.Forward(message); } return true; }
private void Reset() { _resendBuffer = new AckedSendBuffer<EndpointManager.Send>(_settings.SysMsgBufferSize); _seqCounter = 0L; _bailoutAt = null; _bufferWasInUse = false; }
private bool WriteSend(EndpointManager.Send send) { try { if (_handle == null) throw new EndpointException( "Internal error: Endpoint is in state Writing, but no association handle is present."); if (_provider.RemoteSettings.LogSend) { var msgLog = string.Format("RemoteMessage: {0} to [{1}]<+[{2}] from [{3}]", send.Message, send.Recipient, send.Recipient.Path, send.SenderOption ?? _system.DeadLetters); _log.Debug(msgLog); } var pdu = _codec.ConstructMessage(send.Recipient.LocalAddressToUse, send.Recipient, SerializeMessage(send.Message), send.SenderOption, send.Seq, _lastAck); //todo: RemoteMetrics https://github.com/akka/akka/blob/dc0547dd73b54b5de9c3e0b45a21aa865c5db8e2/akka-remote/src/main/scala/akka/remote/Endpoint.scala#L742 //todo: max payload size validation var ok = _handle.Write(pdu); if (ok) { _ackDeadline = NewAckDeadline(); _lastAck = null; return true; } return false; } catch (SerializationException ex) { _log.Error(ex, "Transient association error (association remains live)"); return true; } catch (EndpointException ex) { PublishAndThrow(ex, LogLevel.ErrorLevel); } catch (Exception ex) { PublishAndThrow(new EndpointException("Failed to write message to the transport", ex), LogLevel.ErrorLevel); } return false; }
public Quarantined(int uid, Deadline deadline) : base(true) { Uid = uid; Deadline = deadline; }
public Quarantined(long uid, Deadline deadline) : base(true) { Uid = uid; Deadline = deadline; }
private void Remove(IActorRef actorRef) { Subscribers.Remove(actorRef); if (Subscribers.Count == 0 && !Context.GetChildren().Any()) { PruneDeadline = Deadline.Now + EmptyTimeToLive; } }
public void MarkAsQuarantined(Address address, int uid, Deadline timeOfRelease) { addressToWritable.AddOrSet(address, new EndpointManager.Quarantined(uid, timeOfRelease)); }
public FirstSeedNodeProcess(ImmutableList<Address> seeds) { _cluster = Cluster.Get(Context.System); _selfAddress = _cluster.SelfAddress; if (seeds.Count <= 1 || seeds.Head() != _selfAddress) throw new ArgumentException("Join seed node should not be done"); _remainingSeeds = seeds.Remove(_selfAddress); _timeout = Deadline.Now + _cluster.Settings.SeedNodeTimeout; _retryTaskToken = Context.System.Scheduler.ScheduleTellRepeatedlyCancelable(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1), Self, new InternalClusterAction.JoinSeenNode(), Self); Self.Tell(new InternalClusterAction.JoinSeenNode()); }
/// <summary> /// Record a "refused" UID for a remote system that has been quarantined. /// </summary> /// <param name="remoteAddress">The remote address of the quarantined system.</param> /// <param name="refuseUid">The refused UID of the remote system.</param> /// <param name="timeOfRelease">The timeframe for releasing quarantine.</param> public void RegisterWritableEndpointRefuseUid(Address remoteAddress, int refuseUid, Deadline timeOfRelease) { _addressToRefuseUid[remoteAddress] = Tuple.Create(refuseUid, timeOfRelease); }
/// <summary> /// Mark the current remote address as quarantined. /// </summary> /// <param name="address">The address to quarantine.</param> /// <param name="uid">The UID of the current address.</param> /// <param name="timeOfRelease">The timeframe to release the quarantine.</param> public void MarkAsQuarantined(Address address, int uid, Deadline timeOfRelease) { _addressToWritable[address] = new EndpointManager.Quarantined(uid, timeOfRelease); _addressToRefuseUid[address] = Tuple.Create(uid, timeOfRelease); }
public Quarantined(long uid, Deadline deadline) { Uid = uid; Deadline = deadline; }
/// <summary> /// Marking an endpoint as failed means that we will not try to connect to the remote system within /// the gated period but it is ok for the remote system to try to connect with us (inbound-only.) /// </summary> public void MarkAsFailed(IActorRef endpoint, Deadline timeOfRelease) { if (IsWritable(endpoint)) { var address = _writableToAddress[endpoint]; EndpointManager.EndpointPolicy policy; if (_addressToWritable.TryGetValue(address, out policy)) { if (policy is EndpointManager.Quarantined) { } // don't overwrite Quarantined with Gated if (policy is EndpointManager.Pass) { _addressToWritable[address] = new EndpointManager.Gated(timeOfRelease, policy.AsInstanceOf<EndpointManager.Pass>().RefuseUid); _writableToAddress.Remove(endpoint); } else if (policy is EndpointManager.WasGated) { _addressToWritable[address] = new EndpointManager.Gated(timeOfRelease, policy.AsInstanceOf<EndpointManager.WasGated>().RefuseUid); _writableToAddress.Remove(endpoint); } else if (policy is EndpointManager.Gated) { } // already gated } else { _addressToWritable[address] = new EndpointManager.Gated(timeOfRelease, null); _writableToAddress.Remove(endpoint); } } else if (IsReadOnly(endpoint)) { _addressToReadonly.Remove(_readonlyToAddress[endpoint]); _readonlyToAddress.Remove(endpoint); } }
public Gated(Deadline deadline, int?refuseUid) : base(true) { TimeOfRelease = deadline; RefuseUid = refuseUid; }
protected void Receiving() { Receive<EndpointWriter.FlushAndStop>(flush => { //Trying to serve until our last breath ResendAll(); _writer.Tell(EndpointWriter.FlushAndStop.Instance); Become(FlushWait); }); Receive<IsIdle>(idle => { }); // Do not reply, we will Terminate soon, or send a GotUid Receive<EndpointManager.Send>(send => HandleSend(send)); Receive<Ack>(ack => { // If we are not sure about the UID just ignore the ack. Ignoring is fine. if (UidConfirmed) { try { _resendBuffer = _resendBuffer.Acknowledge(ack); } catch (Exception ex) { throw new HopelessAssociation(_localAddress, _remoteAddress, Uid, new IllegalStateException($"Error encountered while processing system message acknowledgement buffer: {_resendBuffer} ack: {ack}", ex)); } ResendNacked(); } }); Receive<AttemptSysMsgRedelivery>(sysmsg => { if (UidConfirmed) ResendAll(); }); Receive<Terminated>(terminated => { _currentHandle = null; Context.Parent.Tell(new EndpointWriter.StoppedReading(Self)); if (_resendBuffer.NonAcked.Any() || _resendBuffer.Nacked.Any()) Context.System.Scheduler.ScheduleTellOnce(_settings.SysResendTimeout, Self, new AttemptSysMsgRedelivery(), Self); GoToIdle(); }); Receive<GotUid>(g => { _bailoutAt = null; Context.Parent.Tell(g); //New system that has the same address as the old - need to start from fresh state UidConfirmed = true; if (Uid.HasValue && Uid.Value != g.Uid) Reset(); Uid = g.Uid; ResendAll(); }); Receive<EndpointWriter.StopReading>(stopped => { _writer.Forward(stopped); //forward the request }); }
/// <summary> /// Marking an endpoint as failed means that we will not try to connect to the remote system within /// the gated period but it is ok for the remote system to try to connect with us (inbound-only.) /// </summary> public void MarkAsFailed(IActorRef endpoint, Deadline timeOfRelease) { if (IsWritable(endpoint)) { addressToWritable.AddOrSet(writableToAddress[endpoint], new EndpointManager.Gated(timeOfRelease)); writableToAddress.Remove(endpoint); } else if (IsReadOnly(endpoint)) { addressToReadonly.Remove(readonlyToAddress[endpoint]); readonlyToAddress.Remove(endpoint); } }
private void TryingToJoin(object message, Address joinWith, Deadline deadline) { if (_logInfo && !(message is InternalClusterAction.ITick)) { _log.Debug("[TryingToJoin] Received {0}", message); } if (message is InternalClusterAction.Welcome) { var w = message as InternalClusterAction.Welcome; Welcome(joinWith, w.From, w.Gossip); } else if (message is InternalClusterAction.InitJoin) { Sender.Tell(new InternalClusterAction.InitJoinNack(_cluster.SelfAddress)); } else if (message is ClusterUserAction.JoinTo) { var jt = message as ClusterUserAction.JoinTo; BecomeUninitialized(); Join(jt.Address); } else if (message is InternalClusterAction.ISubscriptionMessage) { var isub = message as InternalClusterAction.ISubscriptionMessage; _publisher.Forward(isub); } else if (message is InternalClusterAction.ITick) { if (deadline != null && deadline.IsOverdue) { BecomeUninitialized(); if (_cluster.Settings.SeedNodes.Any()) JoinSeedNodes(_cluster.Settings.SeedNodes); else Join(joinWith); } } else { Unhandled(message); } }
/// <summary> /// Marking an endpoint as failed means that we will not try to connect to the remote system within /// the gated period but it is ok for the remote system to try to connect with us (inbound-only.) /// </summary> public void MarkAsFailed(IActorRef endpoint, Deadline timeOfRelease) { if (IsWritable(endpoint)) { _addressToWritable[_writableToAddress[endpoint]] = new EndpointManager.Gated(timeOfRelease); _writableToAddress.Remove(endpoint); } else if (IsReadOnly(endpoint)) { _addressToReadonly.Remove(_readonlyToAddress[endpoint]); _readonlyToAddress.Remove(endpoint); } }
public void MarkAsQuarantined(Address address, int uid, Deadline timeOfRelease) { _addressToWritable[address] = new EndpointManager.Quarantined(uid, timeOfRelease); }
public Gated(Deadline deadline) : base(true) { TimeOfRelease = deadline; }
public GossipEnvelope(UniqueAddress from, UniqueAddress to, Gossip gossip, Deadline deadline = null) { _from = from; _to = to; Gossip = gossip; Deadline = deadline; }
private bool WriteSend(EndpointManager.Send send) { try { if (_handle == null) throw new EndpointException( "Internal error: Endpoint is in state Writing, but no association handle is present."); if (_provider.RemoteSettings.LogSend) { _log.Debug("RemoteMessage: {0} to [{1}]<+[{2}] from [{3}]", send.Message, send.Recipient, send.Recipient.Path, send.SenderOption ?? _system.DeadLetters); } var pdu = _codec.ConstructMessage(send.Recipient.LocalAddressToUse, send.Recipient, SerializeMessage(send.Message), send.SenderOption, send.Seq, _lastAck); _remoteMetrics.LogPayloadBytes(send.Message, pdu.Length); if (pdu.Length > Transport.MaximumPayloadBytes) { var reason = new OversizedPayloadException( string.Format("Discarding oversized payload sent to {0}: max allowed size {1} bytes, actual size of encoded {2} was {3} bytes.", send.Recipient, Transport.MaximumPayloadBytes, send.Message.GetType(), pdu.Length)); _log.Error(reason, "Transient association error (association remains live)"); return true; } else { var ok = _handle.Write(pdu); if (ok) { _ackDeadline = NewAckDeadline(); _lastAck = null; return true; } } return false; } catch (SerializationException ex) { _log.Error(ex, "Transient association error (association remains live)"); return true; } catch (EndpointException ex) { PublishAndThrow(ex, LogLevel.ErrorLevel); } catch (Exception ex) { PublishAndThrow(new EndpointException("Failed to write message to the transport", ex), LogLevel.ErrorLevel); } return false; }
private void TrySendPureAck() { if (_handle != null && _lastAck != null) { if (_handle.Write(_codec.ConstructPureAck(_lastAck))) { _ackDeadline = NewAckDeadline(); _lastAck = null; } } }
protected override SupervisorStrategy SupervisorStrategy() { return new OneForOneStrategy(ex => { if (ex is IAssociationProblem) return Directive.Escalate; _log.Warning("Association with remote system {0} has failed; address is now gated for {1} ms. Reason is: [{2}]", _remoteAddress, _settings.RetryGateClosedFor.TotalMilliseconds, ex); UidConfirmed = false; // Need confirmation of UID again if (_bufferWasInUse) { if ((_resendBuffer.Nacked.Any() || _resendBuffer.NonAcked.Any()) && _bailoutAt == null) _bailoutAt = Deadline.Now + _settings.InitialSysMsgDeliveryTimeout; Become(() => Gated(writerTerminated: false, earlyUngateRequested: false)); _currentHandle = null; Context.Parent.Tell(new EndpointWriter.StoppedReading(Self)); return Directive.Stop; } return Directive.Escalate; }); }
public void MarkAsQuarantined(Address address, int uid, Deadline timeOfRelease) { _addressToWritable.AddOrSet(address, new EndpointManager.Quarantined(uid, timeOfRelease)); }
private void TryingToJoin(object message, Address joinWith, Deadline deadline) { message.Match() .With<InternalClusterAction.Welcome>(m => Welcome(joinWith, m.From, m.Gossip)) .With<InternalClusterAction.InitJoin>( m => Sender.Tell(new InternalClusterAction.InitJoinAck(_cluster.SelfAddress))) .With<ClusterUserAction.JoinTo>(m => { BecomeUnitialized(); Join(m.Address); }) .With<InternalClusterAction.JoinSeedNodes>(m => { BecomeUnitialized(); JoinSeedNodes(m.SeedNodes); }) .With<InternalClusterAction.ISubscriptionMessage>(msg => _publisher.Forward(msg)) .Default(m => { if (deadline != null && deadline.IsOverdue) { BecomeUnitialized(); if (_cluster.Settings.SeedNodes.Any()) JoinSeedNodes(_cluster.Settings.SeedNodes); else Join(joinWith); } }); }