Hi Harit,
On Mon, Apr 27, 2015 at 12:04 AM, Harit Himanshu <
[email protected]> wrote:
> I am very new to akka and trying to model a solution for a problem.
>
> Consider I have a DiskMonitorActor which looks like
>
> public final class DiskMonitorActor extends UntypedActor {
> private final File assetsDirectory;
> private final long thresholdPercentage;
> private final LoggingAdapter logging =
> Logging.getLogger(getContext().system(), this);
>
> public DiskMonitorActor(final File assetsDirectory, final long
> thresholdPercentage) {
> this.assetsDirectory = assetsDirectory;
> this.thresholdPercentage = thresholdPercentage;
> }
>
> public static Props props(final File assetsDirectory, final long
> thresholdPercentage) {
> return Props.create(new Creator<DiskMonitorActor>(){
> private static final long serialVersionUID = 1L;
>
> public DiskMonitorActor create() throws Exception {
> return new DiskMonitorActor(assetsDirectory, thresholdPercentage);
> }
> });
> }
>
> @Override
> public void onReceive(final Object message) throws Exception {
> if (message instanceof DiskMonitorMessage) {
> logging.info("disk: {}, total space: {}, usable space: {}",
> assetsDirectory.getAbsolutePath(),
> assetsDirectory.getTotalSpace(),
> assetsDirectory.getUsableSpace());
> if (isThresholdExceeded()) {
> logging.error("Disk full. Available Space {}",
> assetsDirectory.getFreeSpace());
> throw new DiskException("disk capacity reached threshold.");
> }
>
> } else {
> unhandled(message);
> }
> }
>
> private boolean isThresholdExceeded() {
> final long usedBytes = assetsDirectory.getTotalSpace() -
> assetsDirectory.getUsableSpace();
> final long thresholdBytes = assetsDirectory.getTotalSpace() *
> thresholdPercentage / 100;
> return usedBytes >= thresholdBytes;
> }
> }
>
> I am able to unit test this as
>
> public class DiskMonitorActorTest {
>
> @Mock
> private File assetsDirectory;
>
> @Rule
> public TestName testName = new TestName();
>
> @Rule
> public ExpectedException expectedException = ExpectedException.none();
>
> @Before
> public void setUp() throws Exception {
> MockitoAnnotations.initMocks(this);
> }
>
> @Test
> public void testDiskMonitorWhenThresholdReached() throws Exception {
> when(assetsDirectory.getAbsolutePath()).thenReturn("test/file/path");
> when(assetsDirectory.getTotalSpace()).thenReturn(100L);
> when(assetsDirectory.getUsableSpace()).thenReturn(10L);
>
> final Props props = DiskMonitorActor.props(assetsDirectory, 10L);
> final ActorSystem system = ActorSystem.create("system");
>
> final TestActorRef<DiskMonitorActor> actorRef =
> TestActorRef.create(system, props, testName.getMethodName());
>
> final DiskMonitorActor diskMonitorActor = actorRef.underlyingActor();
>
> expectedException.expect(DiskException.class);
> expectedException.expectMessage("disk capacity reached threshold.");
> diskMonitorActor.onReceive(new DiskMonitorMessage());
> }
> }
>
> I have a TenantMonitor which is supposed to monitor DiskMonitor (for any
> exception) and take preventive actions, if necessary. It looks like
> public class TenantMonitorActor extends UntypedActor {
>
> private static final String TENANT_MONITORING_CONF =
> "tenant.monitoring.conf";
> private final LoggingAdapter logging =
> Logging.getLogger(getContext().system(), this);
>
> 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();
> }
> });
>
> @Override
> public void onReceive(final Object message) throws Exception {
> if (message instanceof TenantMonitorMessage) {
> logging.info("Tenant Monitor Setup");
> setUpMonitoring();
> }
> }
>
> @Override
> public SupervisorStrategy supervisorStrategy() {
> return strategy;
> }
>
> private void setUpMonitoring() {
> final Config monitoringConf =
> ConfigFactory.load(TENANT_MONITORING_CONF);
> setupDiskMonitoring(monitoringConf);
> }
>
> private void setupDiskMonitoring(final Config monitoringConf) {
> final String diskLocationKey = "tenant.monitoring.disk.location";
> final String thresholdPercentKey =
> "tenant.monitoring.disk.error.threshold.percent";
>
> final Props diskMonitorProps =
> DiskMonitorActor.props(getAssetsDirectory(monitoringConf,
> diskLocationKey),
>
> monitoringConf.getLong(thresholdPercentKey));
>
> final ActorRef diskMonitorActorRef =
> getContext().actorOf(diskMonitorProps, "diskMonitor");
>
> final FiniteDuration start = Duration.create(0, TimeUnit.SECONDS);
> final String schedulerKey = "tenant.monitoring.disk.schedule.seconds";
>
> final FiniteDuration recurring =
> Duration.create(monitoringConf.getInt(schedulerKey),
> TimeUnit.SECONDS);
>
> final ActorSystem system = getContext().system();
> system.scheduler()
> .schedule(start, recurring, diskMonitorActorRef,
> new DiskMonitorMessage(), system.dispatcher(), null);
> }
>
> protected File getAssetsDirectory(final Config monitoringConf, final
> String diskLocationKey) {
> return new File(monitoringConf.getString(diskLocationKey));
> }
> }
>
> The part where I am stuck is how do I inject failures when testing it?
> Specifically I am looking for help on
>
>
> 1. How do I test this Monitor for specific failures and make sure
> correct action is called
>
> The only way to interact with an actor, even when testing is via messages.
If you want to be test supervision events, then you should either test that
actor indirectly whether it produced some message or not, or query its
state with an appropriate domain message, or alternatively, you can
subclass the actor under test, and add hooks that send messages to a
monitor actor on the interesting actions.
-Endre
>
> 1. How could I have written this code in a better way
>
>
> Thanks a lot
> + Harit Himanshu
>
> --
> >>>>>>>>>> Read the docs: http://akka.io/docs/
> >>>>>>>>>> Check the FAQ:
> http://doc.akka.io/docs/akka/current/additional/faq.html
> >>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user
> ---
> You received this message because you are subscribed to the Google Groups
> "Akka User List" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To post to this group, send email to [email protected].
> Visit this group at http://groups.google.com/group/akka-user.
> For more options, visit https://groups.google.com/d/optout.
>
--
Akka Team
Typesafe - Reactive apps on the JVM
Blog: letitcrash.com
Twitter: @akkateam
--
>>>>>>>>>> Read the docs: http://akka.io/docs/
>>>>>>>>>> Check the FAQ:
>>>>>>>>>> http://doc.akka.io/docs/akka/current/additional/faq.html
>>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user
---
You received this message because you are subscribed to the Google Groups "Akka
User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.