Howto resend message after actor is restarted by supervisor strategy - akka

I have parent actor (A) with two child actors (B).
I made a supervisor strategy in A, so in case a specific exception happens in B, B will be restarted.
How can I resend the message which caused the exception in B to B again?

What I've done in B is to send the message again to B in preRestart, see code below.
#Override
public void preRestart(final Throwable reason, final scala.Option<Object> message) throws Exception
{
getSelf().tell(message.get(), getSender());
};
To ensure I don't end in an endless loop, I configure the supervisor strategy in A as follows:
private final SupervisorStrategy strategy = new OneForOneStrategy(3, Duration.Inf(),
new Function<Throwable, SupervisorStrategy.Directive>()
{
#Override
public Directive apply(final Throwable t) throws Exception
{
if (t instanceof SpecificException)
{
return SupervisorStrategy.restart();
}
return SupervisorStrategy.escalate();
}
});
This should gurarantee, that the problematic message is resent only three times. Could somebody give me an advice if this is good practice or link me to a better solution?

Related

Waiting for an external event before continue in unit test

Context:
I'm writing unit test for a gRPC service. I want to verify that the method of the mock on the server side is called. I'm using easy mock. To be sure we get the response of gRPC (whatever it is) I need to suspend the thread before easy mock verify the calls.
So I tried something like this using LockSupport:
#Test
public void alphaMethodTest() throws Exception
{
Dummy dummy = createNiceMock(Dummy.class);
dummy.alphaMethod(anyBoolean());
expectLastCall().once();
EasyMock.replay(dummy);
DummyServiceGrpcImpl dummyServiceGrpc = new DummyServiceGrpcImpl();
bcreuServiceGrpc.setDummy(dummy);
DummyServiceGrpc.DummyServiceStub stub = setupDummyServiceStub();
Thread thread = Thread.currentThread();
stub.alphaMethod(emptyRequest, new StreamObserver<X>(){
#Override
public void onNext(X value) {
LockSupport.unpark(thread);
}
}
Instant expirationTime = Instant.now().plus(pDuration);
LockSupport.parkUntil(expirationTime.toEpochMilli());
verify(dummy);
}
But I have many tests like this one (around 40) and I suspect threading issue. I usually get one or two failing the verify step, sometime all of them pass. I try to use a ReentrantLock with Condition instead. But again some are failing (IllegalMonitorStateException on the signalAll):
#Test
public void alphaMethodTest() throws Exception
{
Dummy dummy = createNiceMock(Dummy.class);
dummy.alphaMethod(anyBoolean());
expectLastCall().once();
EasyMock.replay(dummy);
DummyServiceGrpcImpl dummyServiceGrpc = new DummyServiceGrpcImpl();
bcreuServiceGrpc.setDummy(dummy);
DummyServiceGrpc.DummyServiceStub stub = setupDummyServiceStub();
ReentrantLock lock = new ReentrantLock();
Condition conditionPromiseTerminated = lock.newCondition();
stub.alphaMethod(emptyRequest, new StreamObserver<X>(){
#Override
public void onNext(X value) {
conditionPromiseTerminated.signalAll();
}
}
Instant expirationTime = Instant.now().plus(pDuration);
conditionPromiseTerminated.awaitUntil(new Date(expirationTime.toEpochMilli()));
verify(dummy);
}
I'm sorry not providing runnable example for you, my current code is using a private API :/.
Do you think LockSupport may cause trouble because of the multiple tests running? Am I missing something using lock support or reentrant lock. Do you think of any other class of the concurrent API that would suit better my needs?
LockSupport is a bit dangerous, you will need to read the documentation closely and find out that:
The call spuriously (that is, for no reason) returns.
So when you think your code will do some "waiting", it might simply return immediately. The simplest reason for that would be this for example, but there could be other reasons too.
When using ReentrantLock, all of them should fail with IllegalMonitorStateException, because you never acquire the lock via ReentrantLock::lock. And stop using new Date(...), it is deprecated for a reason.
I think you are over-complicating things, you could do the same signaling with a plain lock, a simplified example:
public static void main(String[] args) {
Object lock = new Object();
Thread first = new Thread(() -> {
synchronized (lock) {
System.out.println("Locked");
try {
System.out.println("Sleeping");
lock.wait();
System.out.println("Waked up");
} catch (InterruptedException e) {
// these are your tests, no one should interrupt
// unless it's yourself
throw new RuntimeException(e);
}
}
});
first.start();
sleepOneSecond();
Thread second = new Thread(() -> {
synchronized (lock) {
System.out.println("notifying waiting threads");
lock.notify();
}
});
second.start();
}
private static void sleepOneSecond() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Notice the output:
Locked
Sleeping
notifying waiting threads
Waked up
It should be obvious how the "communication" (signaling) between threads happens.

NSubstitute conditions for throwing exception other than parameters

I'm using NSubstitute to mock a class that my method under test uses. This mocked class may throw a particular exception under certain conditions.
The method that I'm testing has some "retry" logic that it executes when it catches this exception. I'm trying to test this retry logic. So, I need a particular method of this mocked class to throw the exception sometimes, but not other times. Unfortunately, the method that throws this exception has no parameters, so I can't base the throw logic on parameters.
How can I make the mocked object's method throw the exception either:
A) ...the first N times it's called
or
B) ...based on the parameters some other method that's called before it
or
C) ...under any other condition other than the parameters passed in
To give you a clearer picture of what I'm trying to do, my code is something like:
IDataSender myDataSender = GetDataSender();
int ID = GetNextAvailableID();
myDataSender.ClearData();
myDataSender.Add(ID,"DataToSend");
bool sendSuccess = false;
while (!sendSuccess)
{
try
{
myDataSender.SendData();
sendSuccess = true;
}
catch (IDCollisionException)
{
ID++;
MyDataSender.ClearData();
myDataSender.Add(ID,"DataToSend");
}
}
So, I need to test my retry logic, and I need to simulate that IDCollisionException. However, I can't have the SendData() throwing the exception every single time, or the retry loop will never succeed.
What can I do here?
If I understand the question correctly, you can use When..Do and close over a local variable to get this behaviour.
const int throwUntil = 3;
var callsToSendData = 0;
var dataSender = Substitute.For<IDataSender>();
dataSender
.When(x => x.SendData())
.Do(x =>
{
callsToSendData++;
if (callsToSendData < throwUntil)
{
throw new DbCollisionException();
}
});
Similarly, you can also use callbacks to locally capture parameters passed to other methods, and access them within the Do block (rather than just using a counter).

Subactor (worker) still works after Main actor Timeout in Java Akka

I have implemented an application in Akka framework using Java. I have a main actor which calls sub-actor by using 'Ask' method and timeout after 60 seconds, the worker calls another java class method once it receives the message from Main Actor.
Now the problem is though my Main actor timed-out after 60 seconds still the worker is able to talk to the java class method and in-turn the method is performing the operations which is not required as the main actor cannot receive the response though the sub-actor returns that due to the timeout.
Is there anyway I can kill the worker or stop it from further processing if my Main actor timeout?
I checked the methods like RecieveTimeOut(), context.stop() and poisonpill but still no use.
Appreciate your support
Code Below
public class MainActor extends UntypedActor {
ActorRef subActorRef;
final Timeout timeout = new Timeout(Duration.create(60, TimeUnit.SECONDS));
#Override
public void preStart() {
subActorRef = getContext().actorOf(
SpringExtProvider.get(actorSystem).props(
"SubActor"), "subActor");
}
#Override
public void onReceive(Object message) throws Exception {
if (message instanceof BusinessRequestVO) {
BusinessRequestVO requestVo = (BusinessRequestVO) message;
ArrayList<Future<Object>> responseFutures = new ArrayList<Future<Object>>();
// This part of code timeout after 60seconds
responseFutures.add(ask(subActorRef,requestVo, timeout));
}
}
}
SubActor class
public class SubActor extends UntypedActor {
#Resource
#Inject
ServiceAdapter serviceAdapter;
#Override
public void onReceive(Object message) throws Exception {
try{
if (message instanceof BusinessRequestVO) {
BusinessRequestVO requestVo = (BusinessRequestVO)message
// There is no time out here so it waits synchronously
// though Main actor timeouts
ServiceResponse response = serviceAdapter.getWorkOrder(requestVo);
getSender().tell(response, ActorRef.noSender());
} catch (Exception e) {
getSender().tell(new akka.actor.Status.Failure(e), getSelf());
throw e;
}
}
}
}
Adapter Class
public class ServiceAdapterImpl implements ServiceAdapter{
public ServiceResponse getWorkOrder(BusinessRequestVO request){
// Some code here along with webservice calls
}
}
You can't as your child actor is blocking, thus cannot process any "stop" messages that the parent sends him (actors process messages one at a time before reading the next one in the mailbox).
Your best bet is to wrap the "slow" part of the child's execution inside a future that you can pipeTo the parent (see here for details).
In this way, if your timeout expires, you can have the parent send a custom "stop computing" message, and the child actor can terminate the future. See here about how to terminate a future.
But this could introduce "dirty" states in your application logic according to the specific computation that gets terminated midway through execution.
On an related note: why are you sending all n requests to the same child actor (which you made blocking)? This is equivalent to sequential execution. You should either make the child actor non-blocking or (better) create a blocking actor for each request.
EDIT: as requested by OP, added snippet. It's a pseudo code mixing scala and java, as I'm not super expert with Java syntax for futures, I mainly use it in Scala, so please adapt it a little:
if (message instanceof BusinessRequestVO) {
new Future (
BusinessRequestVO requestVo = (BusinessRequestVO)message
try {
ServiceResponse response = serviceAdapter.getWorkOrder(requestVo);
getSender().tell(response, ActorRef.noSender());
}
catch (Exception e) {
getSender().tell(new akka.actor.Status.Failure(e), getSelf());
throw e;
}
) pipeTo sender
}
And in main (see here for java's future.cancel)
if (timeout) future.cancel(true)

Returning Promise from AWS.SWF Workflow

It seems that according to swf-docs the following code:
#Workflow
#WorkflowRegistrationOptions(
defaultExecutionStartToCloseTimeoutSeconds = 60,
defaultTaskStartToCloseTimeoutSeconds = 10)
public interface MyWorkflow
{
#Execute(version = "1.0")
Promise<String> startMyWF(int a, String b);
}
Should generate MyWorkflowClientExternal that returns a Promise<String>; i.e.:
Promise<String> startMyWF(int a, String b);
However, instead a void method is generated for both MyWorkflowClientExternal and MyWorkflowClientExternalImpl:
void startMyWF(int a, String b) ...
The internal client MyWorkflowClient and MyWorkflowClientImpl does return the Promise object as expected:
Promise<String> startMyWF(int a, String b);
I would like to use ExternalClient; but it does not seem to return the Promise object. I would very much appreciate clarifications.
Thank you.
I posted this question on the AWS-SWF developer forum; and #maxim-fateev has kindly pointed several approaches:
The return value of a workflow is very useful for child workflows
because they are modeled as asynchronous calls. For standalone
workflows, you can use one of the following options to retrieve the
results:
1) Get it from the workflow history using SWF API
GetWorkflowExecutionHistory (the result is in the
WorkflowExecutionCompleted event). You can also inspect the history
using the SWF console.
2) Design your workflow to put the result somewhere, for example you
can add an activity at the end to put the result in a store and have
the application look there periodically.
3) Host an activity in the program that starts the workflow execution.
The workflow starter program now becomes part of the workflow and the
activity it hosts can be passed the result of the workflow.
You may use the first option in manually operated tools. However, it
is not recommended as a general mechanism for applications to retrieve
workflow results because it effectively requires you to poll SWF to
check for workflow completion and goes against our long polling
design.
I went with the approach #2; here is the gist of it (if you think there is a better way; please do let me know).
Created NotificationActivityImpl:
public class NotificationActivitiesImpl implements NotificationActivities {
private Object notification;
public NotificationActivitiesImpl() {
this.notification = null;
}
#Override
public void notify(Object obj) {
this.notification = obj;
}
/**
* #return notification (will block until it is available)
*/
#Override
public Object getNotification() {
while (notification == null ){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return notification;
}
}
In the WorkflowImpl added:
notificationClient.notify(obj) // obj that want to pass back to your app
In the App (which starts the workflow; and NotificationAcitivityWorker) added the following:
workflowWorker.start();
notificationWorker.start();
NotificationActivitiesImpl notificationImpl = (NotificationActivitiesImpl) notificationWorker.getActivitiesImplementations().iterator().next();
Object notification = notificationImpl.getNotification();

Clean-up code in the C++ exception's destructor

Can we use the destructor of an exception as a place to put some clean-up code?
In this manner we may allow the client to control the finalization step as opposed to RAII.
Is this a good or a bad design?
Is this a correct solution in the context of OOP and C++?
I'm currently working on an asynchronous procedure which itself starts asynchronously multiple tasks.
The pattern looks as follows:
struct IAsyncResult
{
...
virtual void EndCall() const;
}
typedef std::shared_ptr<IAsyncResult> IAsyncResultPtr;
struct IAsyncTask
{
virtual IAsyncResultPtr BeginTask() = 0;
virtual void EndTask(IAsyncResultPtr async) const = 0;
}
class CompositeTask : public IAsyncTask
{
…
}
Unfortunately I’m unable to guarantee that each subtask’s BeginTask method will not fail. So it is possible that N-1 subtasks would start successfully and the Nth fail.
In general it is vital to be sure that no background tasks are running before the client’s code finishes. But sometimes the client doesn’t care if some tasks fail.
So my current solution involves a custom exception which is thrown from the CompositeTask’s BeginAsync method in case if one task failed to start. This allows a client to control the clean-up stage:
class composite_async_exception : public std::exception
{
std::vector<IAsyncResultPtr> successfully_started_tasks;
mutable bool manage_cleanup;
public:
composite_async_exception(std::vector<IAsyncResultPtr> const& _successfully_started_tasks)
: successfully_started_tasks(_successfully_started_tasks)
, manage_cleanup(true)
{
}
virtual ~composite_async_exception() throw()
{
if(!manage_cleanup)
return;
for( auto task = successfully_started_tasks.begin(); task != successfully_started_tasks.end(); ++task)
{
task->CancelTask();
}
}
void Giveup() const throw()
{
manage_cleanup = false;
}
};
And the client uses the code as shown:
try
{
compositeTask.BeginAsync();
}
catch(composite_async_exception const& ex)
{
//prevent the exception to cancel tasks
ex.Giveup();
// some handling
}
Are there some best practices to handle such a situation?
The exception is eligible to be copied, the destructor would be called multiple times then. In your case that seem not to be a problem.
Exception handling mechanism might stop your tasks by destroying temporary exception object aborting your tasks at throw point, not at handling one.
To verify this one should read standard, which I'm too lazy to do.