Akka: Can an actor of some class become an actor of a diferent class? - akka

As a course project, I am trying to implement a (simulation) of the Raft protocol.
In this post, I will not use Raft terminology at all; instead, I will use a simplified one.
The protocol is run by a number of servers (for example, 5) which can be in three different states (A, B, C).
The servers inherit some state variables and behavior from a "base" kind, but they all also have many unique state variables and methods, and respond to different messages.
At some point of the protocol, a server in some state (for example, A) is required to become the other state (for example, B).
In other words, the server should:
Lose the state variables and methods of state A, acquire those of state B, but maintain the variables of the "base" kind.
Stop responding to messages destined for state A, start responding to messages destined for state B.
In Akka, Point 1 can be implemented using Receives and become().
Point 2 is needed because, for example, an actor of class B should not have access to state variables and methods of an actor of class A. This aims at separating concerns, and achieving a better code organization.
The issues I am facing in implementing these Point 2 are the following:
Right now, my implementation has only one actor, which contains both A and B state variables and methods.
The protocol I am trying to implement requires each server has to keep a reference to the others (i.e., the ActorRef of the others).
I can't simply spawn an actor in state B, transfer the values of the state variables of the "base" kind to it, and stop the old actor, because the newly spawned actor has a new ActorRef, and the other servers are in the dark about it, and they will continue sending messages using the old ActorRef (therefore, the new actor would not receive anything, and both parties time out).
A way to circumvent the issue is that the newly spawned actor "advertises" itself by sending a message to the other actors, including its old ActorRef.
However, again due to the protocol, the other servers may be temporarily not available (i.e., they are crashed), thus they might not receive and process the advertisement.
In the project, I must use extensions of AbstractActor, and not FSM (final state machines), and have to use Java.
Is there any Akka pattern or functionality that solves this use case? Thank you for any insight. Below is a simplified example.
public abstract class BaseActor extends AbstractActor {
protected int x = 0;
// some state variables and methods that make sense for both A and B
#Override
public Receive createReceive() {
return new ReceiveBuilder()
.matchEquals("x", msg -> {
System.out.println(x);
x++;
})
.build();
}
}
public class A extends BaseActor {
protected int a = 10;
// many other state variables and methods that are own of A and do NOT make sense to B
#Override
public Receive createReceive() {
return new ReceiveBuilder()
.matchEquals("a", msg -> {
System.out.println(a);
})
.matchEquals("change", msg -> {
// here I want A to become B, but maintain value of x
})
.build()
.orElse(super.createReceive());
}
}
public class B extends BaseActor {
protected int b = 20;
// many other state variables and methods that are own of B and do NOT make sense to A
#Override
public AbstractActor.Receive createReceive() {
return new ReceiveBuilder()
.matchEquals("b", msg -> {
System.out.println(b);
})
.matchEquals("change", msg -> {
// here I want B to become A, but maintain value of x
})
.build()
.orElse(super.createReceive());
}
}
public class Example {
public static void main(String[] args) {
var system = ActorSystem.create("example");
// actor has class A
var actor = system.actorOf(Props.create(A.class));
actor.tell("x", ActorRef.noSender()); // prints "0"
actor.tell("a", ActorRef.noSender()); // prints "10"
// here, the actor should become of class B,
// preserving the value of x, a variable of the "base" kind
actor.tell("change", ActorRef.noSender());
// actor has class B
actor.tell("x", ActorRef.noSender()); // should print "1"
actor.tell("b", ActorRef.noSender()); // should print "20"
}
}

This is a sketch implementation of how this could look like.
You model each of the states a separate class:
public class BaseState {
//base state fields/getters/setters
}
public class StateA {
BaseState baseState;
//state A fields/getters/setters
..
//factory methods
public static StateA fromBase(BaseState baseState) {...}
//if you need to go from StateB to StateA:
public static StateA fromStateB(StateB stateB) {...}
}
public class StateB {
BaseState baseState;
//state B fields/getters/setters
//factory methods
public static StateB fromBase(BaseState baseState) {...}
//if you need to go from StateA to StateB:
public static StateB fromStateA(StateA stateA) {...}
}
Then in your Actor you can have receive functions defined for both A and B and initialize it to A or B depending which one is the initial one
private static class MyActor extends AbstractActor
{
private AbstractActor.Receive receive4StateA(StateA stateA)
{
return new ReceiveBuilder()
.matchEquals("a", msg -> stateA.setSomeProperty(msg))
.matchEquals("changeToB", msg -> getContext().become(
receive4StateB(StateB.fromStateA(stateA))))
.build();
}
private AbstractActor.Receive receive4StateB(StateB stateB)
{
return new ReceiveBuilder()
.matchEquals("b", msg -> stateB.setSomeProperty(msg))
.matchEquals("changeToA", msg -> getContext().become(
receive4StateA(StateA.fromStateB(stateB))))
.build();
}
//assuming stateA is the initial state
#Override
public AbstractActor.Receive createReceive()
{
return receive4StateA(StateA.fromBase(new BaseState()));
}
}

Admittedly, my Java is rusty, but for example, this actor (or something very much like it...) will take strings until it receives a Lock message, after which it can be queried for how many distinct strings it received before being locked. So in the first Receive it gets, it tracks a Set of the strings received in order to dedupe. On a Lock it transitions to a second Receive which does not contain the Set (just an Integer field) and ignores String and Lock messages.
import akka.japi.JavaPartialFunction;
import java.util.HashSet;
import scala.runtime.BoxedUnit;
public class StringCounter extends AbstractActor {
public StringCounter() {}
public static class Lock {
private Lock() {}
public static final Lock INSTANCE = new Lock();
}
public static class Query {
private Query() {}
public static final Query INSTANCE = new Query();
}
/** The taking in Strings state */
public class AcceptingStrings extends JavaPartialFunction<Object, BoxedUnit> {
private HashSet<String> strings;
public AcceptingStrings() {
strings = new HashSet<String>();
}
public BoxedUnit apply(Object msg, boolean isCheck) {
if (msg instanceof String) {
if (!isCheck) {
strings.add(msg);
}
} else if (msg instanceof Lock) {
if (!isCheck) {
context().become(new Queryable(strings.size()), true);
}
} else {
// not handling any other message
throw noMatch();
}
return BoxedUnit.UNIT;
}
}
/** The responding to queries state */
public class Queryable extends JavaPartialFunction<Object, BoxedUnit> {
private Integer ans;
public Queryable(int answer) {
ans = Integer.valueOf(answer);
}
public BoxedUnit apply(Object msg, boolean isCheck) {
if (msg instanceof Query) {
if (!isCheck) {
getSender().tell(ans, getSelf());
}
} else {
// not handling any other message
throw noMatch();
}
return BoxedUnit.UNIT;
}
}
#Override
public Receive createReceive() {
return new Receive(new AcceptingStrings());
}
}
Note that in Queryable the set is long gone. One thing to be careful of is that the JavaPartialFunction will typically have apply called once with isCheck set to true and if that call doesn't throw the exception returned by noMatch(), it will be called again "for real" with isCheck set to false. You therefore need to be careful to not do anything but throw noMatch() or return in the case that isCheck is true.
This pattern is exceptionally similar to what happens in Akka Typed (especially in the functional API) under the hood.
Hopefully this illuminates this approach. There's a chance, of course, that your instructors will not accept this, though in that case it might be worth pushing back with the argument that:
in the actor model state and behavior are effectively the same thing
all the functionality is contained within an AbstractActor
I'd also not necessarily recommend using this approach normally in Java Akka code (the AbstractActor with state in its fields feels a lot more Java-y).

Related

Fake internal calls of a SUT with FakeItEasy

I have a small C# class that handles printing.
I want to create (n)unit tests for this class, using
fakeItEasy. How can I fake the internal calls of this
class without faking the whole SUT ?
For example:
public class MyPrintHandler: IMyPrintHandler
{
public MyPrintHandler(ILogger<MyPrintHandler> logger)
{
}
// function I want to (unit test
public async Task<bool> PrintAsync(string ipaddress)
{
try
{
if (!string.IsNullOrWhiteSpace(ipaddress) )
{
return await StartPrint(ipaddress); // This cannot be called in a unit test, because it really start printing on a printer.
}
}
catch (Exception e)
{
}
return false;
}
private async Task<bool> StartPrint(string ipaddress)
{
// prints on the printer
}
[TestFixture]
public class MyPrintHandlerTests
{
[Test]
public void Succes_PrintAsync()
{
using (var fake = new AutoFake())
{
// Arrange - configure the fake
var sut = fake.Resolve<MyPrintHandler>();
// Act
await sut.PrintAsync("0.0.0.0"); // I want to prevent StartPrint() from being called..
}
}
}
How can I achieve this, or is this not possible at all?
Thanks in advance!
I would typically say that faking the SUT is an anti-pattern, to be avoided whenever possible, as it causes confusion. If you can refactor to introduce a collaborator that handles the StartPrinting method, I would strongly consider doing so. If this is not possible, you can try this, however
any method that you want to fake must be virtual or abstract, otherwise FakeItEasy cannot intercept it
any method that you want to fake must be public (or internal, if you can grant dynamic proxy access to production code's internals)
you would then fake the SUT, specifying that it should call the original (base) methods, and finally
explicitly override the behaviour for the method that you want to intercept

C++ class design with polymorphism

I am doing some networking stuff, but the question is not related to networking. I have a generic network event handler, where I can register an network connection ("NwConnection" class) and idea is whenever a message arrives on the connection, it will call me back.
class NwEventManager {
public:
using CallBack = std::function<void(std::shared_ptr<NwConnection>)>;
registerCallback(
std::shared_ptr<NwConnection> con,
CallBack rdCallback,
CallBack errorCallBack);
};
So the application will create a NwConnection and register with Event Manager.
(NwConnection is an abstract class, which internally can be a TCP/Unix domain socket etc.)
Anyway, I need to keep some per-connection information, say some statisctics.
Currently what I am doing is:
class TcpNwConnection : public NwConnection {...}
class MyNwConnection : public TcpNwConnection {
using NwConnection::NwConnection;
....
MyStatistics& getStats ()
{
return myStats_;
}
private:
MyStatistics myStats_;
};
And in the callback, which will call me back with the NwConnection Abstract class I static cast the pointer to my type and access the stats.
// read callback
[] (std::shared_ptr<NwConnection> con)
{
auto myConn = static_cast<MyNwConnection *>(con.get());
auto& stats = myConn->getStats();
}
Is this a good approach?
Obviously the problem is, if my code has to be independant of the NwConnection type, say I want to deal with TcpConnection and UnixConnection, I cannot follow this approach (unless I do with templates).
One solution is to re-write things with connection type inside the NwConnection:
class TcpStream : public AbstractStream {}
class UnixStream : public AbstractStream {}
class NwConnection {
Message read (...)
{
return stream->read(...);
}
private:
AbstractStream *stream;
};
Now I can do my static_cast and the type of connection doesnt matter.
But what is a better way to design this thing, while allowing applications to keep the per-connection data? (I am free to rewrite any part of the code.)

Spying with mockito on Akka actor

I would like to spy on my actor instance, but it cannot be simply created with new keyword. I figured out following solution:
val testActorSpy = spy(TestActorRef(new TestActor).underlyingActor)
val testActorRef = TestActorRef(testActorSpy )
but this way I create one unnecessary actor. Is there any cleaner solution?
So my understanding of the Akka Actor system is that you should be doing this through properties then right?
Thus create the actor through Props and when under testing just return a spy to the actor.
thus this should give you a result:
val testActorRef = TestActorRef(spy(new TestActor))
val testActorSpy = testActorRef.underlyingActor
Be aware that the underlyingActor gets destroyed when the actor is restarted. so mocking this might not be the best option.
If using the actor directly rather going through the system you might be able to test things as well and bypassing the threaded underlying system.
See this (code paste below for java).
static class MyActor extends UntypedActor {
public void onReceive(Object o) throws Exception {
if (o.equals("say42")) {
getSender().tell(42, getSelf());
} else if (o instanceof Exception) {
throw (Exception) o;
}
}
public boolean testMe() { return true; }
}
#Test
public void demonstrateTestActorRef() {
final Props props = Props.create(MyActor.class);
final TestActorRef<MyActor> ref = TestActorRef.create(system, props, "testA");
final MyActor actor = ref.underlyingActor();
assertTrue(actor.testMe());
}

How to unit test domain models with axon-framework

I'm learning CQRS recently, so I started a sample project with axon-framework(A java CRQS framework).
According to the quick start, I got this below:
public class CreditEntryUnitTests {
private FixtureConfiguration fixture;
#Before
public void setUp() throws Exception {
fixture = Fixtures.newGivenWhenThenFixture(CreditEntry.class);
}
#Test
public void creditEntryCreated() throws Throwable {
final Long entryId = 1L;
final int amount = 100;
fixture.given().when(new CreateCreditEntryCommand(entryId, amount))
.expectEvents(new CreditEntryCreatedEvent(entryId, amount));
}
#Test
public void creditEntryMadeEffective() throws Throwable {
final Long entryId = 1L;
final int amount = 100;
final Date start = nov(2011, 12);
final Date end = nov(2012, 12);// a year effective period
fixture.given(new CreditEntryCreatedEvent(entryId, amount))
.when(new MakeCreditEntryEffectiveCommand(entryId, start, end))
.expectEvents(new CreditEntryMadeEffectiveEvent(entryId, start, end));
}
//omitted support methods
}
public class CreditEntry extends AbstractAnnotatedAggregateRoot {
#AggregateIdentifier
private Long id;
private int amount;
private Date effectiveDateRangeStart;
private Date effectiveDateRangeEnd;
private Status status;
#CommandHandler
public CreditEntry(CreateCreditEntryCommand command) {
apply(new CreditEntryCreatedEvent(
command.getEntryId(), command.getAmount()));
}
#EventHandler
public void on(CreditEntryCreatedEvent event) {
this.id = event.getEntryId();
this.amount = event.getAmount();
this.status = Status.NEW;
}
#CommandHandler
public void markCompleted(MakeCreditEntryEffectiveCommand command) {
apply(new CreditEntryMadeEffectiveEvent(
command.getEntryId(), command.getStart(), command.getEnd()));
}
#EventHandler
public void on(CreditEntryMadeEffectiveEvent event) {
this.effectiveDateRangeStart = event.getStart();
this.effectiveDateRangeEnd = event.getEnd();
this.status = Status.EFFECTIVE;
}
public CreditEntry() {}
public enum Status {
NEW, EFFECTIVE, EXPIRED
}
}
The test code drives me written the domain model and integration code with axon-framework but it doesn't cover what side effect the event made. Where did I test them? e.g. when made effective the credit entry's status should be effective. Should I create a CreditEntry instance in other test methods and test by calling specific on(...Event event) method?
And one more question is: where should I put business validation logic? In command handler method? Assuming if the CreditEntry can not be made effective again given it is effective already.
#CommandHandler
public void markCompleted(MakeCreditEntryEffectiveCommand command) {
if (is(NEW)) {
apply(new CreditEntryMadeEffectiveEvent(
command.getEntryId(), command.getStart(), command.getEnd()));
} else {
throw new IllegalStateException(.......);
}
}
Any idea is appreciate, thank you.
On your first question:
Do you mean by side effect the internal state of your aggregate object? The Given-When-Then fixture test treat the aggregate as a kind of black box. So indeed, there is no real need to test the internal state. It is only important that the right events are applied.
So for example, you might even end up with aggregates without any fields (expect the ID) as your decision logic does not depend on any internal state. As a rule of thumb, I only save data transported in an event in the aggregate object if I need it later to decide which events to apply or if it changes the data applied in an event.
If you keep that in mind, you don't really have to test the internal state. You simply configure an aggregate with specific events in the given clause (build up some state) and then apply a command. If the correct events come out... you're done.
On your second question:
Business validation should go in the command handler. So everything should be validated before the applymethod is called. One reason for this: Imagine a system in which the validation logic changes over the life time, but you have to deal with old data which was entered when the system was introduced. If the validation would be in the event handler and the validation is not the same as when the event was first introduced, loading your aggregate from the events might fail as the "old" data does not match to the current validation logic.

How to unit test an interceptor?

I want to write some unit tests for an interceptor that intercepts the Loggable base class (which implements ILoggable).
The Loggable base class has no methods to call and it is used only to be initialized by the logging facility.
To my understanding I should:
Mock an ILoggable and an ILogger
Initialize the logging facility
Register my interceptor on it
Invoke some method of the mocked ILoggable
The problem is that my ILoggable interface has no methods to call and thus nothing will be intercepted.
What is the right way to act here?
Should I mock ILoggable manually and add a stub method to call?
Also, should I be mocking the container as well?
I am using Moq and NUnit.
EDIT:
Here's my interceptor implementation for reference:
public class LoggingWithDebugInterceptor : IInterceptor
{
#region IInterceptor Members
public void Intercept(IInvocation invocation)
{
var invocationLogMessage = new InvocationLogMessage(invocation);
ILoggable loggable = invocation.InvocationTarget as ILoggable;
if (loggable == null)
throw new InterceptionFailureException(invocation, string.Format("Class {0} does not implement ILoggable.", invocationLogMessage.InvocationSource));
loggable.Logger.DebugFormat("Method {0} called with arguments {1}", invocationLogMessage.InvokedMethod, invocationLogMessage.Arguments);
Stopwatch stopwatch = new Stopwatch();
try
{
stopwatch.Start();
invocation.Proceed();
stopwatch.Stop();
}
catch (Exception e)
{
loggable.Logger.ErrorFormat(e, "An exception occured in {0} while calling method {1} with arguments {2}", invocationLogMessage.InvocationSource, invocationLogMessage.InvokedMethod, invocationLogMessage.Arguments);
throw;
}
finally
{
loggable.Logger.DebugFormat("Method {0} returned with value {1} and took exactly {2} to run.", invocationLogMessage.InvokedMethod, invocation.ReturnValue, stopwatch.Elapsed);
}
}
#endregion IInterceptor Members
}
If it's just the interceptor that uses the Logger Property on your class than why have in there at all? You might just as well have it on the interceptor. (like Ayende explained in his post here).
Other than that - interceptor is just a class which interacts with an interface - everything highly testable.
I agree with Krzysztof, if you're looking to add Logging through AOP, the responsibility and implementation details about logging should be transparent to the caller. Thus it's something that the Interceptor can own. I'll try to outline how I would test this.
If I follow the question correctly, your ILoggable is really just a naming container to annotate the class so that the interceptor can determine if it should perform logging. It exposes a property that contains the Logger. (The downside to this is that the class still needs to configure the Logger.)
public interface ILoggable
{
ILogger { get; set; }
}
Testing the interceptor should be a straight-forward process. The only challenge I see that you've presented is how to manually construct the IInvocation input parameter so that it resembles runtime data. Rather than trying to reproduce this through mocks, etc, I would suggest you test it using classic State-based verification: create a proxy that uses your interceptor and verify that your log reflects what you expect.
This might seem like a bit more work, but it provides a really good example of how the interceptor works independently from other parts of your code-base. Other developers on your team benefit from this as they can reference this example as a learning tool.
public class TypeThatSupportsLogging : ILoggable
{
public ILogger { get; set; }
public virtual void MethodToIntercept()
{
}
public void MethodWithoutLogging()
{
}
}
public class TestLogger : ILogger
{
private StringBuilder _output;
public TestLogger()
{
_output = new StringBuilder();
}
public void DebugFormat(string message, params object[] args)
{
_output.AppendFormat(message, args);
}
public string Output
{
get { return _output.ToString(); }
}
}
[TestFixture]
public class LoggingWithDebugInterceptorTests
{
protected TypeThatSupportsLogging Input;
protected LoggingWithDebugInterceptor Subject;
protected ILogger Log;
[Setup]
public void Setup()
{
// create your interceptor
Subject = new LoggingWithDebugInterceptor();
// create your proxy
var generator = new Castle.DynamicProxy.ProxyGenerator();
Input = generator.CreateClassProxy<TypeThatSupportLogging>( Subject );
// setup the logger
Log = new TestLogger();
Input.Logger = Log;
}
[Test]
public void DemonstrateThatTheInterceptorLogsInformationAboutVirtualMethods()
{
// act
Input.MethodToIntercept();
// assert
StringAssert.Contains("MethodToIntercept", Log.Output);
}
[Test]
public void DemonstrateNonVirtualMethodsAreNotLogged()
{
// act
Input.MethodWithoutLogging();
// assert
Assert.AreEqual(String.Empty, Log.Output);
}
}
No methods? What are you testing?
Personally, this sounds like it goes too far. I realize that TDD and code coverage is dogma, but if you mock an interface with no methods and prove that the mocking framework does what you instructed it to do, what have you really proven?
There's another misdirection going on here: logging is the "hello world" of aspect oriented programming. Why aren't you doing logging in an interceptor/aspect? If you did it that way, there'd be no reason for all your classes to implement ILoggable; you could decorate them with logging capability declaratively. I think it's a less invasive design and a better use of interceptors.