Beispiel #1
0
        private ServiceRegistrator(Props serviceProps, string serviceName)
        {
            this.serviceName = serviceName;

            service = Context.ActorOf(serviceProps, serviceName);
            Context.Watch(service);

            registry = Context.ActorOf(ClusterSingletonProxy.Props(
                                           "/user/singleton",
                                           new ClusterSingletonProxySettings("service-registry-manager", null, TimeSpan.FromSeconds(3), 8192)
                                           ));

            ReceiveAsync <Terminated>(async m =>
            {
                var e = await registry.Ask(new Unregister(serviceName));

                log.Debug("Unregistered");
                Context.Stop(Self);
            }, m => m.ActorRef.Equals(service));

            ReceiveAsync <string>(async m =>
            {
                var meta = new ServiceMeta(serviceName, Self);

                var e = await registry.Ask(new Register(meta));

                log.Debug("Registered");
            }, s => s == "Register");

            // TODO Configure report health interval
            Context.System.Scheduler.ScheduleTellRepeatedly(TimeSpan.Zero, TimeSpan.FromSeconds(30), Self, "Register", null);
        }
Beispiel #2
0
        public SystemSupervisor()
        {
            /*** Recovery section **/
            Recover <SnapshotOffer>(offer => ProcessSnapshot(offer));
            Recover <PortfolioAddedToSupervision>(command => ReplayEvent(command.PortfolioNumber));

            /** Core commands **/
            Command <SimulateBoardingOfAccounts>(client => RunSimulator(client));
            Command <SuperviseThisPortfolio>(command => ProcessSupervision(command));
            Command <StartPortfolios>(command => StartPortfolios());
            Command <MySystemStatus>(cmd => Console.WriteLine(cmd.Message));

            /* Commonly used commands */
            Command <TellMeYourStatus>(asking => GetMyStatus());
            Command <BootUp>(me => DoBootUp(me));

            Command <TellMeYourPortfolioStatus>(msg => _log.Debug("[TellMeYourPortfolioStatus]: " + msg.Message));
            Command <string>(noMessage => { });


            Command <ReportBillingProgress>(cmd => GetBillingProgress());
            Command <RegisterPortolioBilling>(cmd => RegisterPortfolioBilling(cmd));

            /** Special handlers below; we can decide how to handle snapshot processin outcomes. */
            Command <SaveSnapshotSuccess>(success => PurgeOldSnapShots(success));

            Command <DeleteSnapshotsSuccess>(msg => { });
            Command <SaveSnapshotFailure>(
                failure => _log.Error(
                    $"[SaveSnapshotFailure]: Actor {Self.Path.Name} was unable to save a snapshot. {failure.Cause.Message}"));
            Command <DeleteMessagesSuccess>(
                msg => _log.Info($"[DeleteMessagesSuccess]: Successfully cleared log after snapshot ({msg.ToString()})"));
            CommandAny(msg => _log.Error($"[CommandAny]: Unhandled message in {Self.Path.Name}. Message:{msg.ToString()}"));
        }
Beispiel #3
0
        public EventStoreSnapshotStore()
        {
            _log       = Context.GetLogger();
            _extension = EventStorePersistence.Instance.Apply(Context.System);
            var serialization = Context.System.Serialization;

            _serializer = serialization.FindSerializerForType(typeof(SnapshotRepresentation));

            _connection = new Lazy <Task <IEventStoreConnection> >(async() =>
            {
                IEventStoreConnection connection = EventStoreConnection.Create(
                    _extension.EventStoreSnapshotSettings.ConnectionString,
                    _extension.EventStoreSnapshotSettings.ConnectionName);
                //connection.Settings.Log = Logger.EventStoreLogger.Create(_log);

                connection.ErrorOccurred += (object sender, ClientErrorEventArgs e) =>
                {
                    _log.Debug("Event Store Connected Error", e.Exception.Message);
                };

                connection.Reconnecting += (object sender, ClientReconnectingEventArgs e) =>
                {
                    _log.Debug("Event Store Reconnecting");
                };
                await connection.ConnectAsync();
                return(connection);
            });
        }
        public PingBlockingActor(IPingPongService service)
        {
            _logger.Debug(GetType().FullName + " Running ...");

            Receive <bool>(message =>
            {
                _logger.Debug(GetType().FullName + " response from async service ...");

                Sender.Tell(new PongBlockingMessage());
            });

            Receive <PingMessage>(message =>
            {
                _logger.Debug(GetType().FullName + " making async call ...");

                service.ExecuteAsync().PipeTo(Self, Sender);
            });

            /*
             * Receive<PingMessage>(async message =>
             * {
             *  var sender = Sender;
             *  await service.ExecuteAsync();
             *  sender.Tell(new PongBlockingMessage());
             * });
             */
        }
Beispiel #5
0
        protected override void OnReceive(object message)
        {
            PersistenceRequest pr = message as PersistenceRequest;

            if (pr != null)
            {
                switch (pr.Type)
                {
                case PersistenceType.OPEN:
                    _log.Debug("初始化,并打开Session");
                    // _init();
                    // _openSession();
                    break;

                case PersistenceType.SAVE:
                    _save(pr.Body);
                    break;

                case PersistenceType.LOAD:
                    break;

                case PersistenceType.CLOSE:
                    _log.Debug("关闭Session");
                    // _closeSession();
                    break;

                default:
                    break;
                }
            }
        }
Beispiel #6
0
        private LightningEnvironment GetLightningEnvironment()
        {
            var t0  = Stopwatch.StartNew();
            var env = new LightningEnvironment(_dir)
            {
                MapSize      = _mapSize,
                MaxDatabases = 1
            };

            env.Open(EnvironmentOpenFlags.NoLock);

            using (var tx = env.BeginTransaction())
                using (tx.OpenDatabase(DatabaseName, new DatabaseConfiguration {
                    Flags = DatabaseOpenFlags.Create
                }))
                {
                    tx.Commit();
                }

            t0.Stop();
            if (_log.IsDebugEnabled)
            {
                _log.Debug($"Init of LMDB in directory [{_dir}] took [{t0.ElapsedMilliseconds} ms]");
            }

            return(env);
        }
        protected override bool ReceiveRecover(object message)
        {
            if (message.CanHandle <RecoveryCompleted>(x =>
            {
                _log.Debug("Recovered state to version {0}", LastSequenceNr);
            }))
            {
                return(true);
            }

            var snapshot = message.ReadMessage <SnapshotOffer>();

            if (snapshot.HasValue)
            {
                var offer = snapshot.Value;
                _log.Debug("State loaded from snapshot");
                LastSnapshottedVersion = offer.Metadata.SequenceNr;
                return(RecoverState(offer.Snapshot, LastSnapshottedVersion));
            }

            if (message.CanHandle <IEvent>(@event =>
            {
                Apply(@event);
            }))
            {
                return(true);
            }

            return(false);
        }
        public bool ShouldDropInbound(Address remoteAddress, object instance, string debugMessage)
        {
            var mode = ChaosMode(remoteAddress);

            if (mode is PassThru)
            {
                return(false);
            }
            if (mode is Drop)
            {
                var drop = mode as Drop;
                if (Rng.NextDouble() <= drop.InboundDropP)
                {
                    var logString = string.Format("Dropping inbound [{0}] for [{1}] {2}", instance.GetType(),
                                                  remoteAddress, debugMessage);
                    if (_shouldDebugLog)
                    {
                        _log.Debug(logString);
                    }
                    return(true);
                }
            }

            return(false);
        }
        private void DeinstallFeatureDefinition(DeinstallationRequest message)
        {
            _log.Debug("Entered LoadFarmFeatures");

            if (!TaskCanceled)
            {
                var errorMsg = dataService.Uninstall(message.FeatureDefinition);

                if (string.IsNullOrEmpty(errorMsg))
                {
                    Sender.Tell(new Core.Messages.Completed.DeinstallationCompleted(
                                    message.TaskId,
                                    message.FeatureDefinition.UniqueIdentifier));
                }
                else
                {
                    var cancelationMsg = new CancelMessage(
                        message.TaskId,
                        errorMsg,
                        true
                        );

                    Sender.Tell(cancelationMsg);
                }
            }
        }
            public ChaosDestination(IActorRef probe)
            {
                Probe               = probe;
                State               = new List <int>();
                _config             = Context.System.Settings.Config.GetConfig("akka.persistence.destination.chaos");
                _confirmFailureRate = _config.GetDouble("confirm-failure-rate");

                Receive <Msg>(m =>
                {
                    if (ChaosSupportExtensions.ShouldFail(_confirmFailureRate))
                    {
                        Log.Error(string.Format("[destination] confirm message failed (message = {0}, {1})", m.DeliveryId, m.I));
                    }
                    else if (State.Contains(m.I))
                    {
                        Log.Debug(string.Format("[destination] ignored duplicate (message = {0}, {1})", m.DeliveryId, m.I));
                        Sender.Tell(new Confirm(m.DeliveryId, m.I));
                    }
                    else
                    {
                        this.Add(m.I);
                        Sender.Tell(new Confirm(m.DeliveryId, m.I));
                        Log.Debug(string.Format("[destination] received and confirmed (message = {0}, {1})", m.DeliveryId, m.I));
                    }
                });
            }
Beispiel #11
0
        private void LogMessage(LoggerMessage message)
        {
            switch (message.MessageType)
            {
            case LoggerTypes.Log:
            {
                _logger.Info(message.Message);
                break;
            }

            case LoggerTypes.System:
            {
                _logger.Warning(message.Message);
                break;
            }

            case LoggerTypes.Trace:
            {
                _logger.Debug(message.Message);
                break;
            }

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
 protected override void OnReceive(object message)
 {
     if (message is RequestRecoveryPermit)
     {
         Context.Watch(Sender);
         if (_usedPermits >= MaxPermits)
         {
             if (pending.Count == 0)
             {
                 Log.Debug("Exceeded max-concurrent-recoveries [{0}]. First pending {1}", MaxPermits, Sender);
             }
             pending.AddLast(Sender);
             _maxPendingStats = Math.Max(_maxPendingStats, pending.Count);
         }
         else
         {
             RecoveryPermitGranted(Sender);
         }
     }
     else if (message is ReturnRecoveryPermit)
     {
         ReturnRecoveryPermit(Sender);
     }
     else if (message is Terminated terminated && !pending.Remove(terminated.ActorRef))
     {
         // pre-mature termination should be rare
         ReturnRecoveryPermit(terminated.ActorRef);
     }
 }
Beispiel #13
0
        /// <summary>
        /// at this time, there is always only one feature to be activated or deactivated in a location with same scope
        /// </summary>
        /// <param name="message"></param>
        private void HandleFeatureToggleRequest(FeatureToggleRequest message)
        {
            _log.Debug("Entered LocationActor-HandleFeatureToggleRequest");

            if (message.Activate)
            {
                ActivatedFeature af;
                var error = dataService.ActivateFeature(
                    message.FeatureDefinition
                    , message.Location
                    , message.ElevatedPrivileges
                    , message.Force
                    , out af);

                var completed = new Core.Messages.Completed.FeatureActivationCompleted(
                    message.TaskId
                    , message.Location.Id
                    , af
                    , string.Empty
                    );

                Sender.Tell(completed);
            }
            else
            {
                var completed = new Core.Messages.Completed.FeatureDeactivationCompleted(
                    message.TaskId
                    , message.Location.Id
                    , string.Empty
                    );

                Sender.Tell(completed);
            }
        }
Beispiel #14
0
 public object InterceptTimerMsg(ILoggingAdapter log, ITimerMsg timerMsg)
 {
     if (!timers.TryGetValue(timerMsg.Key, out var timer))
     {
         // it was from canceled timer that was already enqueued in mailbox
         log.Debug("Received timer [{0}] that has been removed, discarding", timerMsg.Key);
         return(null); // message should be ignored
     }
     if (!ReferenceEquals(timerMsg.Owner, this))
     {
         // after restart, it was from an old instance that was enqueued in mailbox before canceled
         log.Debug("Received timer [{0}] from old restarted instance, discarding", timerMsg.Key);
         return(null); // message should be ignored
     }
     else if (timerMsg.Generation == timer.Generation)
     {
         // valid timer
         if (!timer.Repeat)
         {
             timers.Remove(timer.Key);
         }
         return(timer.Msg);
     }
     else
     {
         // it was from an old timer that was enqueued in mailbox before canceled
         log.Debug(
             "Received timer [{0}] from old generation [{1}], expected generation [{2}], discarding",
             timerMsg.Key,
             timerMsg.Generation,
             timer.Generation);
         return(null); // message should be ignored
     }
 }
        public AbstractExternalWorkflowActor(int actorInstance = 1, int circuitBrakerMaxFailures = 5
                                             , TimeSpan circuitBrakerCallTimeout = default, TimeSpan circuitBrakerResetTimeout = default)
        {
            ActorInstance             = actorInstance;
            _circuitBrakerMaxFailures = circuitBrakerMaxFailures;
            if (circuitBrakerCallTimeout == default)
            {
                _circuitBrakerCallTimeout = TimeSpan.FromSeconds(10);
            }
            else
            {
                _circuitBrakerCallTimeout = circuitBrakerCallTimeout;
            }
            if (circuitBrakerResetTimeout == default)
            {
                _circuitBrakerResetTimeout = TimeSpan.FromMinutes(1);
            }
            else
            {
                _circuitBrakerResetTimeout = circuitBrakerResetTimeout;
            }

            Receive <DeadletterHandlingMessage>(message =>
            {
                Context.IncrementCounter(nameof(DeadletterHandlingMessage));
                Logger.Debug("{0} received message {1}", ActorId, message.ToString());
                DeadletterHandlingMessageHandler(message);
            });
        }
Beispiel #16
0
        protected void _init()
        {
            _log.Debug("加载{0}策略的仓位信息", Desc.Id);
            String path = String.Format("/user/{0}", ConstantsHelper.AKKA_PATH_PERSISTENCE);

            persistenceActor = Context.ActorSelection(path);
            PersistenceRequest req = new PersistenceRequest()
            {
                Type = PersistenceType.FIND, Body = String.Format("from EStrategy where Id={0}", Desc.Id)
            };
            var ret = persistenceActor.Ask <EStrategy>(req, TimeSpan.FromSeconds(1));

            ret.Wait();
            Desc = ret.Result;

            _log.Debug("{0}策略连接交易接口", Desc.Id);
            if (Desc.Trader != null)
            {
                String tpath = String.Format("/user/{0}/{1}", ConstantsHelper.AKKA_PATH_TRADER, Desc.Trader.Id);
                tradeActor = Context.ActorSelection(tpath);
            }
            else
            {
                // 默认的trade actor is /user/trader/ths
                tradeActor = Context.ActorSelection("/user/trader");
            }

            onInit();
        }
Beispiel #17
0
 /// <summary>
 /// Creates an <see cref="Akka.Event.LogLevel.DebugLevel"/> log entry with the specific message.
 /// </summary>
 /// <param name="message">The message being logged.</param>
 internal void LogDebug(string message)
 {
     if (_log.IsDebugEnabled)
     {
         _log.Debug("Cluster Node [{0}] - {1}", _selfAddress, message);
     }
 }
        protected override void OnReceive(object message)
        {
            Log.Debug("Dragon received: {message}");
            switch (message)
            {
            case Feed feed:
                FoodReceived(feed.Food);
                break;

            case Play play:
                PlayReceived(play.HappinessValue);
                break;

            case ReadHappiness happy:
                Sender.Tell(new RespondHappiness(happy.RequestId, happinessLevel));
                break;

            case ReadHunger hunger:
                stomach.Forward(hunger);
                break;

            case ReadStageOfLife stage:
                Sender.Tell(new RespondStageOfLife(stage.RequestId, stageOfLife));
                break;

            case Grow grow:
                Grow(grow);
                break;

                //case RespondHunger respondHunger:
                //    Sender.Forward(respondHunger);
                //    break;
            }
        }
Beispiel #19
0
        public UserService()
        {
            Receive <GetUserDetail>(c =>
            {
                _log.Debug("received GetUserDetail xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
                logger.Debug("received GetUserDetail xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");

                //no receive of any kind in testactor
                var testProps = Context.DI().Props <TestActor>();
                var test      = Context.ActorOf(testProps);
                test.Forward(c);

                //this will send properly
                //var testActor = Context.ActorOf(Props.Create(() => new TestActor()));
                //testActor.Forward(c);


                Sender.Tell(new UserDetailResult("Carlo", "DiGiacomo"));
            });

            ReceiveAny(c =>
            {
                _log.Debug($"received {c}");
            });
        }
Beispiel #20
0
        public PrinterActor(KafkaService _kafkaService)
        {
            kafkaService = _kafkaService;

            id = Guid.NewGuid().ToString();
            logger.Info($"프린터 액터 생성:{id}");

            //주소로 액터를 선택하기 : 위치투명성,참조객체를 얻기위해 DI가 복잡해질필요 없다,그리고 이것은 리모트로확장시 코드변화가없다.
            tonerActor = Context.System.ActorSelection("user/toner");

            ReceiveAsync <PrintPage>(async page =>
            {
                logger.Debug($"프린터 요청 들어옴:{page}");
                await Task.Delay(page.DelayForPrint);


                //토너를 비동기로 소모시킴
                tonerActor.Tell(1);

                //남은 토너 용량 물어봄
                var msg = await tonerActor.Ask("남은용량?");
                if (null != Sender)
                {
                    Sender.Tell(msg);
                }

                logger.Debug($"ASK결과:{msg}");
                logger.Debug($"페이지 출력 완료:{page}");
            });

            ReceiveAsync <string>(async msg =>
            {
                logger.Debug($"토너 관리액터에게 받은 메시지:{msg}");
            });
        }
Beispiel #21
0
 public SchedulingActor()
 {
     _publisher = Context.System.GetTransport();
     _logger.Debug("Scheduling actor started at path {Path}", Self.Path);
     _scheduler = Context.System.GetExtension <SchedulingExtension>().Scheduler;
     ReceiveAsync <ScheduleCommandExecution>(Schedule);
     Receive <Unschedule>(message => Unschedule(message));
 }
Beispiel #22
0
        public async void OnConnect(INode remoteAddress, IConnection responseChannel)
        {
            _log.Debug("connection from {0}", responseChannel.RemoteHost);
            //TODO: Seems wrong to create new RemoteConnection here
            var fsm = await _controller.Ask <IActorRef>(new Controller.CreateServerFSM(new RemoteConnection(responseChannel, this)), TimeSpan.FromMilliseconds(Int32.MaxValue));

            _clients.AddOrUpdate(responseChannel, fsm, (connection, @ref) => fsm);
        }
Beispiel #23
0
        private void Replay()
        {
            var limit = _maxBufferSize - _buffer.Length;

            _log.Debug("replay all events request from [{0}], limit [{1}]", _currentOffset, limit);
            _journalRef.Tell(new ReplayAllEvents(_currentOffset, limit, Self));
            Context.Become(Replaying);
        }
Beispiel #24
0
        protected override SupervisorStrategy SupervisorStrategy()
        {
            return(new OneForOneStrategy(ex =>
            {
                var directive = Directive.Stop;

                ex.Match()
                .With <InvalidAssociation>(ia =>
                {
                    log.Warning("Tried to associate with unreachable remote address [{0}]. " +
                                "Address is now gated for {1} ms, all messages to this address will be delivered to dead letters. Reason: [{2}]",
                                ia.RemoteAddress, settings.RetryGateClosedFor.TotalMilliseconds, ia.Message);
                    endpoints.MarkAsFailed(Sender, Deadline.Now + settings.RetryGateClosedFor);
                    AddressTerminatedTopic.Get(Context.System).Publish(new AddressTerminated(ia.RemoteAddress));
                    directive = Directive.Stop;
                })
                .With <ShutDownAssociation>(shutdown =>
                {
                    log.Debug("Remote system with address [{0}] has shut down. " +
                              "Address is now gated for {1}ms, all messages to this address will be delivered to dead letters.",
                              shutdown.RemoteAddress, settings.RetryGateClosedFor.TotalMilliseconds);
                    endpoints.MarkAsFailed(Sender, Deadline.Now + settings.RetryGateClosedFor);
                    AddressTerminatedTopic.Get(Context.System).Publish(new AddressTerminated(shutdown.RemoteAddress));
                    directive = Directive.Stop;
                })
                .With <HopelessAssociation>(hopeless =>
                {
                    if (settings.QuarantineDuration.HasValue && hopeless.Uid.HasValue)
                    {
                        endpoints.MarkAsQuarantined(hopeless.RemoteAddress, hopeless.Uid.Value,
                                                    Deadline.Now + settings.QuarantineDuration.Value);
                        eventPublisher.NotifyListeners(new QuarantinedEvent(hopeless.RemoteAddress,
                                                                            hopeless.Uid.Value));
                    }
                    else
                    {
                        log.Warning("Association to [{0}] with unknown UID is irrecoverably failed. " +
                                    "Address cannot be quarantined without knowing the UID, gating instead for {1} ms.",
                                    hopeless.RemoteAddress, settings.RetryGateClosedFor.TotalMilliseconds);
                        endpoints.MarkAsFailed(Sender, Deadline.Now + settings.RetryGateClosedFor);
                    }
                    AddressTerminatedTopic.Get(Context.System).Publish(new AddressTerminated(hopeless.RemoteAddress));
                    directive = Directive.Stop;
                })
                .Default(msg =>
                {
                    if (msg is EndpointDisassociatedException || msg is EndpointAssociationException)
                    {
                    }                                                                                         //no logging
                    else
                    {
                        log.Error(ex, ex.Message);
                    }
                });

                return directive;
            }));
        }
Beispiel #25
0
        protected override void PreStart()
        {
            _log.Debug("PreStart()");

            if (AccountList == null)
            {
                AccountList = new List <string>(1000000);
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="WorkerActor"/>  class
        /// </summary>
        /// <param name="executer">Executer object</param>
        public WorkerActor(ITaskExecuter executer)
        {
            _taskExecuter = executer;

            Receive <JobStartedMessage>(job => HandleJobExecute(job));
            Receive <AcknowledgementMessage>(message => HandleAcknowldgement(message));

            _logger.Debug("Worker instance created.");
        }
 private void CreateChildUserIfNotExists(int userId)
 {
     if (!_users.ContainsKey(userId))
     {
         var newChildActorRef = Context.ActorOf(Props.Create(() => new UserActor(userId)), $"User{userId}");
         _users.Add(userId, newChildActorRef);
         _logger.Debug($"UserCoordinatorActor created new child UserActor for {userId} (Total Users: {_users.Count})");
     }
 }
Beispiel #28
0
 public Controller(int initialParticipants, IPEndPoint controllerPort)
 {
     _log.Debug("Opening connection");
     _connection = RemoteConnection.CreateConnection(Role.Server, controllerPort, _settings.ServerSocketWorkerPoolSize,
                                                     new ConductorHandler(Self, Logging.GetLogger(Context.System, typeof(ConductorHandler)))).Result;
     _log.Debug("Connection bound");
     _barrier             = Context.ActorOf(Props.Create <BarrierCoordinator>(), "barriers");
     _initialParticipants = initialParticipants;
 }
Beispiel #29
0
 protected override Task DeleteAsync(SnapshotMetadata metadata)
 {
     _log.Debug("DeleteAsync() - metadata: {0}, metadata.Timestamp {1:yyyy-MMM-dd-HH-mm-ss ffff}", metadata,
                metadata.Timestamp);
     return(RunWithStreamDispatcher(() => {
         Delete(metadata);
         return new object();
     }));
 }
Beispiel #30
0
        /// <summary>
        /// TBD
        /// </summary>
        /// <param name="path">TBD</param>
        /// <returns>TBD</returns>
        public IActorRef ResolveActorRef(string path)
        {
            if (ActorPath.TryParse(path, out var actorPath) && actorPath.Address == _rootPath.Address)
            {
                return(ResolveActorRef(_rootGuardian, actorPath.Elements));
            }

            _log.Debug("Resolve of unknown path [{0}] failed. Invalid format.", path);
            return(_deadLetters);
        }
 private static void ConditionalLog(ILoggingAdapter logger, string format, params object[] args)
 {
     if (logger != null)
         logger.Debug(format, args);
 }
Beispiel #32
0
            public ChaosApp(IActorRef probe)
            {
                _probe = probe;
                _destination = Context.ActorOf(Props.Create(() => new ChaosDestination(_probe)), "destination");
                _sender = CreateSender();
                _acks = new HashSet<int>();
                _log = Context.GetLogger();

                Receive<Start>(_ =>
                {
                    for (int i = 1; i <= NumberOfMessages; i++)
                    {
                        _sender.Tell(i);
                    }
                });
                Receive<Ack>(x => _acks.Add(x.I));
                Receive<Terminated>(x =>
                {
                    // snd will be stopped if recover or persist fail
                    _log.Debug("sender stopped, starting it again");
                    _sender = CreateSender();
                    for (var i = 1; i <= NumberOfMessages; i++)
                    {
                        if (!_acks.Contains(i))
                            _sender.Tell(i);
                    }
                });
            }