Search code examples
javaakkaactorthread-synchronization

Akka actor granularity


I am trying to wrap my head around Akka/actors for the first time, and am a bit confused over the granularity of each Actor's responsibilities.

In my app there are Widgets that can be registered/unregistered with a WidgetRegistrar. To register itself with the Registrar and Widget is passed to the registerWidget method:

interface WidgetRegistrar {
    public void register(Widget w);
}

When a Widget attempts to register, a verification process occurs. If this process passes, then the Widget presents a URL that must be constantly (once a second) polled and checked (with an HTTP GET) to make sure that URL is still healthy.

My question here is: how should this work load be spread amongst actors?

I can think of several different strategies right off the bat:

  • WidgetRegistrar actor that first somehow delegates to the WidgetVerifier actor (see below), and if verified, updates the WidgetChecker actor with the newly-registered/verified Widget
  • WidgetVerifier actor that verifies a Widget attempting to register itself
  • 1 master WidgetChecker that checks a URL for each registered/verified Widget

Or a different strategy:

  • WidgetRegistrar actor that first somehow delegates to the WidgetVerifier actor (see below), and if verified, somehow instantiates a new WidgetChecker actor (see below)
  • WidgetVerifier actor that verifies a Widget attempting to register itself
  • 1 WidgetChecker for each registered/verified Widget

Or a different strategy:

  • WidgetRegistrar actor that verifies Widgets right there on the spot (instead of delegating out to a separate actor), and if verified, updates the WidgetChecker actor with the newly-registered/verified Widget
  • 1 master WidgetChecker that checks a URL for each registered/verified Widget

...the list of variations goes on and on.

So I ask: what is the granularity of an Akka actor, and how do I know when I should break functionality out into another actor and somehow connect the two actors?


Solution

  • Akka ideology is 'let it crash', so it's best to isolate potentially dangerous functionality into a separate actor.

    How i would do that - sample actor hierarchy:

    /master
        /validator
            /authentication
            /capability
        /registrar
            /widget1
            /widget2
            /widget3
    

    Assuming that you may want to have more functionality in your registrar other than register/unregister for a single widget, it's would be good to separate widgets under specific root - so, for instance, if your widget has functionality like 'update', you invoke this logic in /registrar/widget1, and if update has failed, widget1 actor will die. Depending on your needs you may want to require either to reregister the widget, or set the supervisor hierarchy to restart the widget actor automatically.

    With validators/verifiers and other logic - you can build either pipeline (sequential processing) or scatter-gather (parallel) on your validators, for instance:

    • /master sends to /validator a message AttemptRegister(WidgetInfo)
    • /validator sends this message to all of its children (e.g. through ask pattern), and is expecting Accept(WidgetInfo) or Reject(WidgetInfo) - if there are no rejections - it will send RegisterWidget to /registrar and registrar will spawn a new /registrar/widget2.

    Of course, it all depends on the concrete use case - for instance:

    • Can validation crash or block? Then you would need to have /validator/capability/doOrDieActor1
    • Do you need sequential processing/pipeline? you may want to implement this sequence like ../authentication will send Pass or Fail to ../authorization that will send it to capability etc - and only the final actor will send ValidationSucceeded to /validator, which will in turn send RegisterWidget event to registrar