samedi 2 mai 2015

Akka: Testing Supervisor Recommendations

I am very new to Akka and using Java to program my system.

Problem definition
- I have a TenantMonitor which when receives TenantMonitorMessage(), starts a new actor DiskMonitorActor.
- The DiskMonitorActor may fail for various reasons and may throw DiskException. The DiskMonitorActor has been Unit Tested.

What I need?
- I want to test behavior TenantMonitorActor, so that when DiskException happens, it takes correct action like stop(), resume() or any (depending upon what my application may need)

What I tried?
Based on the documentation, the closest I could perform is the section called Expecting Log Messages.

Where I need help?
- While I understand the expecting the correct error log is important, it just asserts first part, that exception is thrown and is logged correctly, but does not help in asserting that right strategy is called

Code?
TenantMonitorActor

public class TenantMonitorActor extends UntypedActor {

  public static final String DISK_MONITOR = "diskMonitor";
  private static final String assetsLocationKey = "tenant.assetsLocation";
  private static final String schedulerKey = "monitoring.tenant.disk.schedule.seconds";
  private static final String thresholdPercentKey = "monitoring.tenant.disk.threshold.percent";

  private final LoggingAdapter logging = Logging.getLogger(getContext().system(), this);
  private final Config config;

  private TenantMonitorActor(final Config config) {
    this.config = config;
  }

  private static final SupervisorStrategy strategy =
      new OneForOneStrategy(1, Duration.create(1, TimeUnit.SECONDS),
                            new Function<Throwable, Directive>() {

                              public Directive apply(final Throwable param) throws Exception {
                                if (param instanceof DiskException) {
                                  return stop();
                                }
                                return restart();
                              }
                            });

  public static Props props(final Config config) {
    return Props.create(new Creator<TenantMonitorActor>(){
      public TenantMonitorActor create() throws Exception {
        return new TenantMonitorActor(config);
      }
    });
  }

  @Override
  public void onReceive(final Object message) throws Exception {
    if (message instanceof TenantMonitorMessage) {
      logging.info("Tenant Monitor Setup");
      setupDiskMonitoring();
    }
  }

  @Override
  public SupervisorStrategy supervisorStrategy() {
    return strategy;
  }



  private void setupDiskMonitoring() {
    final ActorRef diskMonitorActorRef = getDiskMonitorActorRef(config);

    final FiniteDuration start = Duration.create(0, TimeUnit.SECONDS);
    final FiniteDuration recurring = Duration.create(config.getInt(schedulerKey),
                                                     TimeUnit.SECONDS);

    final ActorSystem system = getContext().system();
    system.scheduler()
        .schedule(start, recurring, diskMonitorActorRef,
                  new DiskMonitorMessage(), system.dispatcher(), null);
  }

  private ActorRef getDiskMonitorActorRef(final Config monitoringConf) {
    final Props diskMonitorProps =
        DiskMonitorActor.props(new File(monitoringConf.getString(assetsLocationKey)),
                               monitoringConf.getLong(thresholdPercentKey));
    return getContext().actorOf(diskMonitorProps, DISK_MONITOR);

  }
}

Test

  @Test
  public void testActorForNonExistentLocation() throws Exception {
    final Map<String, String> configValues =
        Collections.singletonMap("tenant.assetsLocation", "/non/existentLocation");
    final Config config = mergeConfig(configValues);

    new JavaTestKit(system) {{
      assertEquals("system", system.name());

      final Props props = TenantMonitorActor.props(config);
      final ActorRef supervisor = system.actorOf(props, "supervisor");
      new EventFilter<Void>(DiskException.class) {

        @Override
        protected Void run() {
          supervisor.tell(new TenantMonitorMessage(), ActorRef.noSender());
          return null;
        }
      }.from("akka://system/user/supervisor/diskMonitor").occurrences(1).exec();

    }};
  }

Aucun commentaire:

Enregistrer un commentaire