예제 #1
0
        /// <summary>
        /// Dispatches a <see cref="SystemMessage"/> from a mailbox to an <see cref="ActorCell"/>
        /// </summary>
        public virtual void SystemDispatch(ActorCell cell, SystemMessage message)
        {
            var mbox = cell.Mailbox;

            mbox.SystemEnqueue(cell.Self, message);
            RegisterForExecution(mbox, false, true);
        }
예제 #2
0
        /// <summary>
        /// Dispatches a user-defined message from a mailbox to an <see cref="ActorCell"/>
        /// </summary>
        public virtual void Dispatch(ActorCell cell, Envelope envelope)
        {
            var mbox = cell.Mailbox;

            mbox.Enqueue(cell.Self, envelope);
            RegisterForExecution(mbox, true, false);
        }
예제 #3
0
 /// <summary>
 /// INTERNAL API
 ///
 /// If you override it, you must still call the base method. But only ever once. See <see cref="Attach"/> for only invocation.
 /// </summary>
 /// <param name="actor">The actor we're registering</param>
 internal virtual void Register(ActorCell actor)
 {
     if (DebugDispatcher)
     {
         Actors.Value.Put(this, (IInternalActorRef)actor.Self);
     }
     AddInhabitants(1);
 }
예제 #4
0
        /// <summary>
        /// TBD
        /// </summary>
        /// <returns>TBD</returns>
        protected override ActorCell NewCell()
        {
            ActorCell cell = Props.RouterConfig is Pool pool && pool.Resizer != null
                ? new ResizablePoolCell(System, this, Props, Dispatcher, _routeeProps, Supervisor, pool)
                : new RoutedActorCell(System, this, Props, Dispatcher, _routeeProps, Supervisor);

            cell.Init(false, MailboxType);
            return(cell);
        }
예제 #5
0
        /// <summary>
        /// After the call to this method, the dispatcher mustn't begin any new message processing for the specified reference
        /// </summary>
        /// <param name="actorCell">The cell of the actor whose mailbox will be suspended.</param>
        internal virtual void Suspend(ActorCell actorCell)
        {
            var mbox = actorCell.Mailbox;

            if (mbox.Actor == actorCell && mbox.Dispatcher == this) //make sure everything is referring to the same instance
            {
                mbox.Suspend();
            }
        }
예제 #6
0
        /// <summary>
        /// After the call to this method, the dispatcher must begin any new message processing for the specified reference
        /// </summary>
        /// <param name="actorCell">The cell of the actor whose mailbox will be resumed.</param>
        internal virtual void Resume(ActorCell actorCell)
        {
            var mbox = actorCell.Mailbox;

            if (mbox.Actor == actorCell && mbox.Dispatcher == this && mbox.Resume()) //make sure everything is referring to the same instance
            {
                RegisterForExecution(mbox, false, false);                            // force the mailbox to re-run after resume
            }
        }
예제 #7
0
            public override void Attach(ActorCell cell)
            {
                if (cell.Props.Type == typeof(FastActor))
                {
                    _latch = cell.Props.Arguments[0] as TestLatch;
                }

                base.Attach(cell);
            }
예제 #8
0
        /// <summary>
        /// TBD
        /// </summary>
        /// <param name="actor">TBD</param>
        /// <exception cref="InvalidOperationException">
        /// This exception is thrown if the registering <paramref name="actor"/> is not the <see cref="_owner">owner</see>.
        /// </exception>
        internal override void Register(ActorCell actor)
        {
            var current = _owner;

            if (current != null && actor != current)
            {
                throw new InvalidOperationException($"Cannot register to anyone but {_owner}");
            }
            _owner = actor;
            base.Register(actor);
        }
예제 #9
0
 /// <summary>
 /// Detaches the dispatcher to the <see cref="ActorCell"/>
 ///
 /// <remarks>
 /// Only really used in dispatchers with 1:1 relationship with dispatcher.
 /// </remarks>
 /// </summary>
 /// <param name="cell">The ActorCell belonging to the actor who's detaching from this dispatcher.</param>
 public virtual void Detach(ActorCell cell)
 {
     try
     {
         Unregister(cell);
     }
     finally
     {
         IfSensibleToDoSoThenScheduleShutdown();
     }
 }
예제 #10
0
        /// <summary>
        /// INTERNAL API
        ///
        /// If you override it, you must call it. But only ever once. See <see cref="Detach"/> for the only invocation
        /// </summary>
        /// <param name="actor">The actor who is unregistering</param>
        internal virtual void Unregister(ActorCell actor)
        {
            if (DebugDispatcher)
            {
                Actors.Value.Remove(this, (IInternalActorRef)actor.Self);
            }
            AddInhabitants(-1);
            var mailbox = actor.SwapMailbox(Mailboxes.DeadLetterMailbox);

            mailbox.BecomeClosed();
            mailbox.CleanUp();
        }
예제 #11
0
        private IInternalActorRef GetChild(string name)
        {
            var nameAndUid = ActorCell.SplitNameAndUid(name);
            IInternalActorRef child;

            if (TryGetChild(nameAndUid.Name, out child))
            {
                if (nameAndUid.Uid != ActorCell.UndefinedUid && nameAndUid.Uid != child.Path.Uid)
                {
                    return(ActorRefs.Nobody);
                }
            }
            return(child);
        }
        public void Notify(NotificationMessage notificationMessage)
        {
            var notificationId = ++_lastNotificationId;

            if (notificationId <= 0)
            {
                notificationId = _lastNotificationId = 1;
            }

            notificationMessage.NotificationId = notificationId;

            var sender = ActorCell.GetCurrentSelfOrNoSender();

            Receiver.Tell(notificationMessage, sender);
        }
예제 #13
0
        /// <summary>
        ///     Request a connection to the local docker API.
        /// </summary>
        /// <param name="dockerApi">
        ///     The Docker API extension for Akka.NET.
        /// </param>
        /// <param name="replyTo">
        ///     The actor to which the reply will be sent.
        /// </param>
        /// <param name="correlationId">
        ///     A message correlation Id that will be returned with the response.
        /// </param>
        /// <remarks>
        ///     If successful, a reference to the <see cref="Client"/> actor will be delivered via a <see cref="Connected"/> message.
        ///     Otherwise, a <see cref="ConnectFailed"/> message will be delivered.
        /// </remarks>
        public static void RequestConnectLocal(this DockerApi dockerApi, IActorRef replyTo = null, string correlationId = null)
        {
            if (dockerApi == null)
            {
                throw new ArgumentNullException(nameof(dockerApi));
            }

            replyTo = replyTo ?? ActorCell.GetCurrentSenderOrNoSender();
            if (replyTo.IsNobody())
            {
                throw new InvalidOperationException("Cannot determine the actor to receive the reply.");
            }

            dockerApi.Manager.Tell(
                Connect.Local(correlationId),
                sender: replyTo
                );
        }
예제 #14
0
        /// <summary>
        /// TBD
        /// </summary>
        /// <returns>TBD</returns>
        protected override ActorCell NewCell()
        {
            var       pool = Props.RouterConfig as Pool;
            ActorCell cell = null;

            if (pool != null)
            {
                if (pool.Resizer != null)
                {
                    cell = new ResizablePoolCell(System, this, Props, Dispatcher, _routeeProps, Supervisor, pool);
                }
            }
            if (cell == null)
            {
                cell = new RoutedActorCell(System, this, Props, Dispatcher, _routeeProps, Supervisor);
            }
            cell.Init(false, MailboxType);
            return(cell);
        }
 public SynergyPersistenceStashRabbitMq(IActorContext context, List <KeyValuePair <string, string> > config)
 {
     _actorCell       = (ActorCell)context;
     _context         = context;
     BootstrapServers = config.First(kvp => kvp.Key == "bootstrapserver").Value;
     Topic            = config.First(kvp => kvp.Key == "topic").Value;
     _factory         = new ConnectionFactory()
     {
         HostName = this.BootstrapServers
     };
     _connection = _factory.CreateConnection();
     _model      = _connection.CreateModel();
     _model.ExchangeDeclare(this.Topic, ExchangeType.Direct);
     _model.QueueDeclare(queue: this.Topic,
                         durable: false,
                         exclusive: false,
                         autoDelete: false,
                         arguments: null);
     _model.QueueBind(this.Topic, this.Topic, "directexchange_key");
 }
예제 #16
0
        protected override ActorCell NewCell()
        {
            var       pool = _routerProps.RouterConfig as Pool;
            ActorCell cell = null;

            if (pool != null)
            {
                if (pool.Resizer != null)
                {
                    //if there is a resizer, use ResizablePoolCell
                    cell = new ResizablePoolCell(_system, this, _routerProps, _routerDispatcher, _routeeProps, _supervisor, pool);
                }
            }
            if (cell == null)
            {
                cell = new RoutedActorCell(_system, this, _routerProps, _routerDispatcher, _routeeProps, _supervisor);
            }
            cell.Init(sendSupervise: false, createMailbox: _createMailbox);
            return(cell);
        }
예제 #17
0
        /// <summary>INTERNAL
        /// Abstract base class for stash support
        /// <remarks>Note! Part of internal API. Breaking changes may occur without notice. Use at own risk.</remarks>
        /// </summary>
        /// <exception cref="NotSupportedException">This exception is thrown if the actor's mailbox isn't deque-based (e.g. <see cref="UnboundedDequeBasedMailbox"/>).</exception>
        protected AbstractStash(IActorContext context, int capacity = 100)
        {
            var actorCell = (ActorCell)context;
            Mailbox = actorCell.Mailbox.MessageQueue as IDequeBasedMessageQueueSemantics;
            if(Mailbox == null)
            {
                string message = $@"DequeBasedMailbox required, got: {actorCell.Mailbox.GetType().Name}
An (unbounded) deque-based mailbox can be configured as follows:
    my-custom-mailbox {{
        mailbox-type = ""Akka.Dispatch.UnboundedDequeBasedMailbox""
    }}";
                throw new NotSupportedException(message);
            }
            _theStash = new LinkedList<Envelope>();
            _actorCell = actorCell;

            // TODO: capacity needs to come from dispatcher or mailbox config
            // https://github.com/akka/akka/blob/master/akka-actor/src/main/scala/akka/actor/Stash.scala#L126
            _capacity = capacity;
        }
예제 #18
0
        /// <summary>INTERNAL
        /// Abstract base class for stash support
        /// <remarks>Note! Part of internal API. Breaking changes may occur without notice. Use at own risk.</remarks>
        /// </summary>
        protected AbstractStash(IActorContext context, int capacity = 100)
        {
            var actorCell = (ActorCell)context;
            var mailbox   = actorCell.Mailbox as IDequeBasedMailbox;

            if (mailbox == null)
            {
                string message = @"DequeBasedMailbox required, got: " + actorCell.Mailbox.GetType().Name + @"
An (unbounded) deque-based mailbox can be configured as follows:
    my-custom-mailbox {
        mailbox-type = ""Akka.Dispatch.UnboundedDequeBasedMailbox""
    }";
                throw new NotSupportedException(message);
            }
            _theStash  = new LinkedList <Envelope>();
            _actorCell = actorCell;

            // TODO: capacity needs to come from dispatcher or mailbox config
            // https://github.com/akka/akka/blob/master/akka-actor/src/main/scala/akka/actor/Stash.scala#L126
            _capacity = capacity;
        }
 public override ActorRef ResolveActorRef(ActorPath actorPath)
 {
     if (HasAddress(actorPath.Address))
     {
         if (actorPath.Elements.Head() == "remote")
         {
             if (actorPath.ToStringWithoutAddress() == "/remote")
             {
                 return(RemoteDaemon);
             }
             //skip ""/"remote",
             string[] parts = actorPath.Elements.Drop(1).ToArray();
             return(RemoteDaemon.GetChild(parts));
         }
         if (actorPath.Elements.Head() == "temp")
         {
             //skip ""/"temp",
             string[] parts = actorPath.Elements.Drop(1).ToArray();
             return(TempContainer.GetChild(parts));
         }
         //standard
         ActorCell currentContext = RootCell;
         if (actorPath.ToStringWithoutAddress() == "/")
         {
             return(currentContext.Self);
         }
         foreach (string part in actorPath.Elements)
         {
             currentContext = ((LocalActorRef)currentContext.Child(part)).Cell;
         }
         return(currentContext.Self);
     }
     return(new RemoteActorRef(Transport,
                               Transport.LocalAddressForRemote(actorPath.Address),
                               actorPath,
                               ActorRef.Nobody,
                               Props.None,
                               Deploy.None));
 }
예제 #20
0
        public void Durable_CRDT_should_be_durable_after_gossip_update()
        {
            var r = NewReplicator();

            RunOn(() =>
            {
                Log.Debug("sending message with sender: {}", ActorCell.GetCurrentSelfOrNoSender());
                r.Tell(Dsl.Update(_keyC, ORSet <string> .Empty, WriteLocal.Instance, c => c.Add(_cluster, Myself.Name)));
                ExpectMsg(new UpdateSuccess(_keyC, null));
            }, _first);

            RunOn(() =>
            {
                r.Tell(Dsl.Subscribe(_keyC, TestActor));
                ExpectMsg <Changed>().Get(_keyC).Elements.ShouldBe(ImmutableHashSet.Create(_first.Name));

                // must do one more roundtrip to be sure that it keyB is stored, since Changed might have
                // been sent out before storage
                TellUpdate(r, _keyA, WriteLocal.Instance, new PocoObject("Id_1", 3));
                ExpectMsg(new UpdateSuccess(_keyA, null));

                Watch(r);
                Sys.Stop(r);
                ExpectTerminated(r);

                var r2 = default(IActorRef);
                AwaitAssert(() => r2 = NewReplicator()); // try until name is free
                AwaitAssert(() =>
                {
                    r2.Tell(Dsl.GetKeyIds);
                    ExpectMsg <GetKeysIdsResult>().Keys.ShouldNotBe(ImmutableHashSet <string> .Empty);
                });

                r2.Tell(Dsl.Get(_keyC, ReadLocal.Instance));
                ExpectMsg <GetSuccess>().Get(_keyC).Elements.ShouldBe(ImmutableHashSet.Create(_first.Name));
            }, _second);

            EnterBarrierAfterTestStep();
        }
예제 #21
0
 /// <summary>
 /// Detaches the dispatcher to the <see cref="ActorCell"/>
 ///
 /// <remarks>
 /// Only really used in dispatchers with 1:1 relationship with dispatcher.
 /// </remarks>
 /// </summary>
 /// <param name="cell">The ActorCell belonging to the actor who's deatching from this dispatcher.</param>
 public virtual void Detach(ActorCell cell)
 {
 }
예제 #22
0
 /// <summary>
 /// Dispatches a <see cref="ISystemMessage"/> from a mailbox to an <see cref="ActorCell"/>
 /// </summary>
 public virtual void SystemDispatch(ActorCell cell, Envelope envelope)
 {
     cell.SystemInvoke(envelope);
 }
예제 #23
0
 /// <summary>
 /// Dispatches a user-defined message from a mailbox to an <see cref="ActorCell"/>
 /// </summary>
 public virtual void Dispatch(ActorCell cell, Envelope envelope)
 {
     cell.Invoke(envelope);
 }
예제 #24
0
 /// <summary>
 ///     Attaches an ActorCell to the Mailbox.
 /// </summary>
 /// <param name="actorCell"></param>
 public void SetActor(ActorCell actorCell)
 {
     _actorCell = actorCell;
 }
예제 #25
0
 internal ActorTaskScheduler(ActorCell actorCell)
 {
     _actorCell = actorCell;
 }
예제 #26
0
 /// <summary>
 /// Attaches the dispatcher to the <see cref="ActorCell"/>
 ///
 /// <remarks>
 /// Practically, doesn't do very much right now - dispatchers aren't responsible for creating
 /// mailboxes in Akka.NET
 /// </remarks>
 /// </summary>
 /// <param name="cell">The ActorCell belonging to the actor who's attaching to this dispatcher.</param>
 public virtual void Attach(ActorCell cell)
 {
     Register(cell);
     RegisterForExecution(cell.Mailbox, false, true);
 }
예제 #27
0
 /// <summary>
 /// Creates and returns a <see cref="Mailbox"/> for the given actor.
 /// </summary>
 /// <param name="cell">Cell of the actor.</param>
 /// <param name="mailboxType">The mailbox configurator.</param>
 /// <returns>The configured <see cref="Mailbox"/> for this actor.</returns>
 internal Mailbox CreateMailbox(ActorCell cell, MailboxType mailboxType)
 {
     return(new Mailbox(mailboxType.Create(cell.Self, cell.System)));
 }
예제 #28
0
        private void Run()
        {
            if (_isClosed)
            {
                return;
            }

            var throughputDeadlineTime = dispatcher.ThroughputDeadlineTime;

            ActorCell.UseThreadContext(() =>
            {
                //if ThroughputDeadlineTime is enabled, start a stopwatch
                if (throughputDeadlineTime.HasValue && throughputDeadlineTime.Value > 0)
                {
                    if (_deadLineTimer != null)
                    {
                        _deadLineTimer.Restart();
                    }
                    else
                    {
                        _deadLineTimer = Stopwatch.StartNew();
                    }
                }

                //we are about to process all enqueued messages
                hasUnscheduledMessages = false;
                Envelope envelope;

                //start with system messages, they have the highest priority
                while (_systemMessages.TryDequeue(out envelope))
                {
                    Mailbox.DebugPrint(ActorCell.Self + " processing system message " + envelope);
                    // TODO: Add + " with " + ActorCell.GetChildren());
                    dispatcher.SystemDispatch(ActorCell, envelope);
                }

                //we should process x messages in this run
                var left = dispatcher.Throughput;

                //try dequeue a user message
                while (!IsSuspended && !_isClosed && _userMessages.TryDequeue(out envelope))
                {
                    Mailbox.DebugPrint(ActorCell.Self + " processing message " + envelope);

                    //run the receive handler
                    dispatcher.Dispatch(ActorCell, envelope);

                    //check if any system message have arrived while processing user messages
                    if (_systemMessages.TryDequeue(out envelope))
                    {
                        //handle system message
                        Mailbox.DebugPrint(ActorCell.Self + " processing system message " + envelope);
                        // TODO: Add + " with " + ActorCell.GetChildren());
                        dispatcher.SystemDispatch(ActorCell, envelope);
                        break;
                    }
                    left--;
                    if (_isClosed)
                    {
                        return;
                    }

                    //if deadline time have expired, stop and break
                    if (throughputDeadlineTime.HasValue && throughputDeadlineTime.Value > 0 &&
                        _deadLineTimer.Elapsed.Ticks > throughputDeadlineTime.Value)
                    {
                        _deadLineTimer.Stop();
                        break;
                    }

                    //we are done processing messages for this run
                    if (left == 0)
                    {
                        break;
                    }
                }

                Interlocked.Exchange(ref status, MailboxStatus.Idle);

                //there are still messages that needs to be processed
                if (_systemMessages.Count > 0 || (!IsSuspended && _userMessages.Count > 0))
                {
                    //we still need has unscheduled messages for external info.
                    //e.g. repointable actor ref uses it
                    //TODO: will this be enough for external parties to work?
                    hasUnscheduledMessages = true;

                    //this is subject of a race condition
                    //but that doesn't matter, since if the above "if" misses
                    //the "Post" that adds the new message will still schedule
                    //this specific call is just to deal with existing messages
                    //that wasn't scheduled due to dispatcher throughput being reached
                    //or system messages arriving during user message processing
                    Schedule();
                }
            });
        }
예제 #29
0
 /// <summary>
 /// TBD
 /// </summary>
 /// <param name="actor">TBD</param>
 internal override void Unregister(ActorCell actor)
 {
     base.Unregister(actor);
     _owner = null;
 }
예제 #30
0
 /// <summary>
 /// TBD
 /// </summary>
 /// <param name="cell">TBD</param>
 public ActorCellKeepingSynchronizationContext(ActorCell cell)
 {
     _cell = cell;
 }
예제 #31
0
 /// <summary>
 ///     Attaches an ActorCell to the Mailbox.
 /// </summary>
 /// <param name="actorCell">TBD</param>
 public virtual void SetActor(ActorCell actorCell)
 {
     _actor = actorCell;
 }