This document describes cell 0.0. For development docs, go here.

Hello World

Here we will demonstrate the main cell features starting with a simple Hello World example. To understand what is going on, we will break the example into pieces.

Defining an actor

Actors are implemented by extending the Actor class and then defining a series of supported methods. The supported methods should be encapsulated in the Actor’s internal state class. Our first actor implements one method called greet.

from cell.actors import Actor

class GreetingActor(Actor):
    class state:
        def greet(self, who='world'):
            print 'Hello %s' % who

Starting an actor

Cell targets distributed actors management. Therefore, creating an actor means spawning an actor consumer remotely by sending a command to a celery worker agent. That is why before spawning an actor, you need to have a celery worker running:

$ celery worker

Actors are created via spawn() method, called on an instance of dAgent (distributed agent). Agents are components responsible for creating and stopping actors on celery workers. Each celery worker has embedded agent component dAgent (distributed agent) listening for commands. spawn() is invoked with a class of type Actor or its derivative and starts an actor of that type remotely (in the celery worker). The method returns a proxy (an instance of ActorProxy) for the remotely started actor. The proxy holds the unique identifier, which ensures the messages can be delivered unambiguously to the same remote actor.

The code below starts a GreetingActor and then invokes its py:meth:greeting method.

from cell.agents import dAgent
from kombu import Connection

connection = Connection()
# STEP 1: Create an agent
agent = dAgent(connection)
# STEP 2: Pass the actor type to spawn method
greeter = agent.spawn(GreetingActor)

# STEP 3: Use actor proxy to call methods on the remote actor
greeter.send('greet')

Calling a method

The cell actor model comes with few build-in delivery policies. Here we demonstrate direct delivery - the message is send to a particular actor instance. (Look at the end of the section for the other delivery options.)

actor.send('greet')

The greet() method has been executed and you can verify that by looking at the workers console output. The remote actor of type GreetingActor you created earlier handle the method. The message ‘Hello world’ should be printed on the celery worker console. Note that the call is asynchronous and since ‘great’ is a void method no result will be returned. For getting results back and invoking methods synchronously check Getting a result back section

The basic Actor API expose three more methods for sending a message:
  • send() - sends to a particular actor instance
  • throw() - sends to an actor instance of the same type
  • scatter() - sends to all actor instances of the same type

For more information on the above options, see the Delivery options section

Calling a method with parameters

Here is an example how to call the method greet() with an argument who

actor.send('greet', {'who':'everyone'})

Getting a result back

Let’s add another method to the GreetingActor class how_are_you() that returns a result.

from cell.actors import Actor

class GreetingActor(Actor):
    class state:
        def greet(self, who='world'):
            print 'Hello %s' % who

        def how_are_you(self):
            return 'Fine!'

We can get the result in two ways:

  • using a blocking call (set the nowait parameter to True), it blocks the execution until a result is delivered or a timeout is reached:
result = actor.send('greet', {'who':'everyone'}, nowait=True)

d.. warning:: If you are using blocking calls, greenlets should be enabled in the celery worker:

Greenlets can be enabled either by using eventlet or using gevent:

>>> celery worker -P eventlet -c 100

or

>>> celery worker -P gevent -c 100

You can read more about concurrency in celery in here

  • using a non-blocking call (set the nowait parameter to False, the default), it returns an an AsyncResult instance.

AsyncResult can be used to check the state of the result, get the return value or if the method failed, the exception and traceback).

result = actor.send('greet', {'who':'everyone'}, nowait=False)

The result() returns the result if it is ready or wait for the result to complete

result = actor.send('greet', {'who':'everyone'}, nowait=False)
print result.result

See cell.result for the complete result object reference.

Stopping an actor

We can stop an actor if we know its id.

agent.kill(actor.id)

agents.dAgent.kill() is a broadcast command sent to all agents. If an agents doesn’t have in its registry the given actor.id, it will dismiss the command, otherwise it will gently kill the actor and delete it from its registry.

Where to go from here

If you want to learn more you should explore the examples in the examples module in the cell codebase and/or study the User Guide.