Lightweight Java actor framework using fibers.
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
build-tools Primed project for continued development Nov 22, 2017
core Upgraded to coroutines 1.5.0 Jun 9, 2018
jdbc-storage Upgraded to coroutines 1.5.0 Jun 9, 2018
redis-storage Upgraded to coroutines 1.5.0 Jun 9, 2018
servlet-gateway Added servlet gateway Dec 7, 2017
.gitignore Added servlet gateway Dec 7, 2017
LICENSE Added license text Jul 12, 2014
README.md Updated README Dec 11, 2017
logo.png Added logo Apr 1, 2017
logo.svg Added logo Apr 1, 2017
nbactions.xml
pom.xml Upgraded to coroutines 1.5.0 Jun 9, 2018

README.md

Actors (pre-alpha)

Actors logo

The Actors project is a lightweight Java actor framework that greatly simplifies the design and development of horizontally scalable software. Why use Actors over other actor frameworks?

  • Actors as lightweight fibers/coroutines
  • Seamless distribution of actors
  • Seamless checkpointing of actors
  • Seamless versioning of actors

What does all this mean? Distribution means your actors will seamlessly execute across a cluster of servers. You can add and remove servers at will, and server crashes won't effect the execution of your actors. Checkpointing makes sure that if your actors enter into a bad state, they will automatically revert to the last known good state (as specified by you) and be notified of the problem. Versioning allows you to change your actor's logic on the fly, without breaking compatibility with older versions of that actor. Fix bugs and add features without stopping your service. You can even have your servers running different versions of the same actor.

The Actors project gives you everything you need to write highly resilient/elastic/scalable systems, but without all the headaches.

Example

This is a simple "Hello World" style example. It doesn't show many of the core features that make the Actors project what it is, but more in-depth material and screencasts are in the works.

First, create your actor. The Actors project uses the Coroutines project, so you'll need to use the coroutines plugin to instrument your actors.

public final class SimpleActor implements Coroutine {    
    @Override
    public void run(Continuation cnt) throws Exception {
        Context ctx = (Context) cnt.getContext();
        Object msg;
        
        // Display the priming message that's initially sent to this actor
        msg = ctx.in();
        ctx.logInfo("Priming message: {}", msg);
        
        // Allow any address to communicate with this actor
        ctx.allow();
        
        while (true) {
            // Add a checkpoint -- if no activity in 60 seconds send a message notifying as such.
            ctx.checkpoint("ACTOR HASN'T BEEN HIT IN OVER 60 SECONDS -- CHECKPOINT TRIGGERED", 60 * 1000L);
            // Add a 1000L timer to echo a message back after 1 second.
            ctx.timer(1000L, "timer!");
            
            // Wait for next message
            cnt.suspend();
            
            // Print message
            msg = ctx.in();
            ctx.logInfo("Got message: {}", msg);
        }
    }
}

Next, set up a server to run instances of your actor. You can spawn as many instances of the server as you want.

public final class SimpleRedisStoreTest {
    private static final int WORKER_COUNT = 1000;
    private static final int THREAD_COUNT = 100;
    private static final int REDIS_POOL_COUNT = THREAD_COUNT;
    private static final int REDIS_QUEUE_COUNT = 10;
    
    public static void main(String[] args) throws Exception {
        // Start actor system backed by Redis
        RedisStore store = RedisStore.create(
                "actor",
                "192.168.56.101",
                6379,
                REDIS_POOL_COUNT,
                REDIS_QUEUE_COUNT);

        ActorSystem actorSystem = ActorSystem.builder()
                .withLogGateway()
                .withActorGateway(THREAD_COUNT, store)
                .build();
        
        // Add 1000 new actors into the system
        ActorGateway actorGateway = actorSystem.getActorGateway();
        for (int i = 0; i < WORKER_COUNT; i++) {
            String name = InetAddress.getLocalHost().getHostName() + "_" + i;
            Coroutine coroutine = new SimpleActor();

            actorGateway.addActor(name, coroutine, "start");
        }
        
        // Block
        actorSystem.join();
    }
}