In my actor, I do something like:
//upon receiving a message
Future myFuture = Futures.succesful(doSomething());
myFuture.onSuccess(new OnSuccess<Object>() {
#Override
public void onSuccess(Object object) throws Throwable {
doSomethingLong(object);
}
}, dispatcher);
Patterns.pipe(myFuture).to(sender());
Will my sender receive the message response at the time where "doSomething()" completes, i.e. as soon as the first future completes, or after the "doSomethingLong()" completes, i.e. after the onSuccess handler operations have completed?
Note that onSuccess is deprecated since Scala 2.12.0. Consider moving to foreach or onComplete
onSuccess attaches a function to be executed when the target future is completed with a value. Therefore the callback and the message send to the actor is going to happen concurrently.
If you want a sequential behaviour, use map instead of onSuccess.
In your example, the onSuccess and the pipe will happen concurrently.
If you don't want a possibly failed invocation of doSomethingLong() to affect the outcome, and you want it to have executed before piping it to sender, then I'd suggest the following:
Future myFuture = Futures.successful(doSomething());
Patterns.pipe(myFuture.andThen(new OnComplete<Object>() {
public void onComplete(Throwable failure, Object result) {
if (failure != null)
doSomethingLong(result);
}
}, dispatcher)).to(sender());
Related
as we know, this method try 20 attempts at 5sec interval, so my question is for every fail retry, does it go err block? here is sample code snnipet
s3.waitFor('objectExists', params, function(err, data) {
if (err){
console.log(err);
}
else{
console.log(data);
}
});
The documentation states:
The final callback or 'complete' event will be fired only when the resource is either in its final state or the waiter has timed out and stopped polling for the final state.
In other words, the callback will only be called once, so the answer to your question is no. Either console.log(err) or console.log(data) will run, and only once.
I stumbled upon a weird testScheduler behavior that I cannot wrap my head around. The code below is greatly simplified, but it origins in a real life issue.
Consider this test:
#Test
fun testSchedulerFun(){
val testScheduler = TestScheduler()
val stringsProcessor = PublishProcessor.create<String>()
val completable = Completable.complete()
completable
.doOnComplete { stringsProcessor.onNext("onComplete") }
.subscribeOn(testScheduler)
.subscribe()
val testSubscriber = stringsProcessor
.subscribeOn(testScheduler) //this line of code messes the test
.test()
testScheduler.triggerActions()
testSubscriber
.assertValues("onComplete")
}
**When I subscribe the tested stringsProcessor on testScheduler, the test fails. When I remove that line it succeeds. **
The flow of events as I see it is:
triggerActions
completable and stringsProcessor are being subscribed and propagate their events downstream.
And apparently the stringsProcessor.onNext("onComplete") is evaluated after the testSubscriber has finished.
I want to know why
The reason the test fails is because stringProcessor has no subscriber the time you call onNext on it. That subscriber only comes after because you added the "this line messes up" subscribeOn.
There is no race condition involved because everything runs on the same thread in a deterministic order:
when the code executes completable ... subscribe() part, a task is queued with testScheduler that will perform the doOnComplete call.
when the code executes the test part, another task is queued with testScheduler that will observe the processor.
triggerActions executes task 1, which emits the value to no subscribers, then executes task 2 and now ready to observe the processor, but nothing comes.
I have an actor which is orchestrating database updates. I need to ensure that each operation gets executed only after the previous one gets completed.
This because operation B will reuse the result of operation A.
Here the code I wrote for the actor.
class DbUpdateActor(databaseOperations: DBProvider) extends Actor {
implicit val ec:ExecutionContext = context.system.dispatcher
def receive: Receive = {
case newInfo : UpdateDb =>
val future = Future {
// gets the current situation from DB
val status = databaseOperations.getSituation()
// do db update
databaseOperations.save(something)
}
future onComplete {
case Success(result: List[Int]) =>
//
case Failure(err: Throwable) =>
//
}
}
}
The code works fine for a single operation. If I fire two updates then the second one is executed asynchronously so it gets started before the first one has completed.
I was reading about different types of mailbox, not sure if having a different one would help.
Any suggestion?
One option you can explore would be to remove that Future and allow that blocking db code to be run within the actor. Then, use a separate dispatcher (perhaps a PinnedDispatcher) to fire-wall this blocking code off from the main actor system's dispatcher, giving it its own thread to run on. By blocking in the body and removing that Future, you will ensure proper sequential execution of the actor's mailbox. A rough sketch of the changes to make that work are as follows:
object DbUpdateActor{
def props(databaseOperations:DBProvider) =
Props(classOf[DbUpdateActor], databaseOperations).
withDispatcher("db-update-dispatcher")
}
class DbUpdateActor(databaseOperations: DBProvider) extends Actor {
def receive: Receive = {
case newInfo : UpdateDb =>
val status = databaseOperations.getSituation()
databaseOperations.save(something)
}
}
Then, as long as you had the following dispatcher configured in your actor system config:
db-update-dispatcher {
executor = "thread-pool-executor"
type = PinnedDispatcher
}
And you started up the db update actor like so:
val updater = system.actorOf(DbUpdateActor.props(databaseOperations))
Then you should be all set setting this actor up to run that blocking code in a way that won't negatively affect the throughput of the main dispatcher.
How about this: start operation A in a child; when the child is complete it sends the parent a message saying it completed. Then you can start operation B, either in the existing or a new child.
From: https://www.chrisstucchio.com/blog/2013/actors_vs_futures.html
suggests that this is safe:
class FooCounter extends Actor {
var count: Long = 0
def receive = {
case Foo => { count += 1}
case FooCountRequest => { sender ! count }
}
}
Isn't it possible that there will be multiple simultaneous calls to receive, making the value of count uncertain.
My understanding is that the only way this could ever be safe would be if the receive call on this object was made mutex with itself.
The receive method is never called simultaneously by multiple threads. Messages residing in an Actor's mailbox are processed one-at-a-time by the receive method. Multiple other Actors, or functions outside of the ActorSystem, can concurrently enqueue messages to the Actor's mailbox but the ActorSystem eventually orders the messages. From the docs:
Enqueuing happens in the time-order of send operations, which means
that messages sent from different actors may not have a defined order
at runtime due to the apparent randomness of distributing actors
across threads.
The receive method's serial processing is guaranteed by the fact that you never actually get an Actor value (which has a receive) from the ActorSystem. Rather, you only get an ActorRef which does not have receive method:
val actorSystem = akka.actor.ActorSystem()
//not an Actor but an ActorRef
val actorRef : ActorRef = actorSystem actorOf Props[FooCounter]
actorRef.receive(Foo) //COMPILE TIME ERROR!
The only way to "invoke" the receive method is to send a message to the ActorRef:
actorRef ! Foo //non-blocking, enqueues a Foo object in the mailbox
Relating back to your question: the ActorSystem acts as a pseudo-mutex for all Actor instances.
Therefore, the code in your example is absolutely safe and the state will only be accessed by one message at any given time.
Totally agree with Ramon. You can think of it have a mail box outside your house(Actor) and mail are coming to your mail box though your address (ActorRef) and you only have 1 single person at your home to take care your mail one at a time.
Besides, for more functional style and maintain immutability of code. I would do the following instead:
class FooCounter extends Actor {
def _receive(count: Long): Receive = {
case Foo =>
context.become(_receive(count + 1))
case FooCountRequest =>
sender() ! count
}
def receive = _receive(0L)
}
For this simple example, there are no difference between mine and yours. But when system become more complex, my code are less error prone.
I have a Scala unit test for an Akka actor. The actor is designed to poll a remote system and update a local cache. Part of the actor's design is that it doesn't attempt to poll while it's still processing or awaiting the result of the last poll, to avoid flooding the remote system when it experiences a slowdown.
I have a test case (shown below) which uses Mockito to simulate a slow network call, and checks that when the actor is told to update, it won't make another network call until the current one is complete. It checks the actor has not made another call by verifying a lack of interactions with the remote service.
I want to eliminate the call to Thread.sleep. I want to test the functionality of the actor without relying on waiting for a hardcoded time, in every test run, which is brittle, and wastes time. The test can poll or block, waiting for a condition, with a timeout. This will be more robust, and will not waste time when the test is passing. I also have the added constraint that I want to keep the state used to prevent extra polling var allowPoll limited in scope, to the internals of the PollingActor.
is there a way force a wait until the actor is finished messaging itself? If there's a way I can wait until then before trying to assert.
is it necessary to send the internal message at all? Couldn't I maintain the internal state with a threadsafe datastructure, such as java.util.concurrent.AtomicBoolean. I have done this and the code appears to work, but I'm not knowledgeable enough about Akka to know if it's discouraged -- a colleague recommended the self message style.
is there better, out-of-the-box functionality with the same semantics? Then I would opt for an integration test instead of a unit test, though I'm not sure if it would solve this problem.
The current actor looks something like this:
class PollingActor(val remoteService: RemoteServiceThingy) extends ActWhenActiveActor {
private var allowPoll: Boolean = true
def receive = {
case PreventFurtherPolling => {
allowPoll = false
}
case AllowFurtherPolling => {
allowPoll = true
}
case UpdateLocalCache => {
if (allowPoll) {
self ! PreventFurtherPolling
remoteService.makeNetworkCall.onComplete {
result => {
self ! AllowFurtherPolling
// process result
}
}
}
}
}
}
trait RemoteServiceThingy {
def makeNetworkCall: Future[String]
}
private case object PreventFurtherPolling
private case object AllowFurtherPolling
case object UpdateLocalCache
And the unit test, in specs2, looks like this:
"when request has finished a new requests can be made" ! {
val remoteService = mock[RemoteServiceThingy]
val actor = TestActorRef(new PollingActor(remoteService))
val slowRequest = new DefaultPromise[String]()
remoteService.makeNetworkCall returns slowRequest
actor.receive(UpdateLocalCache)
actor.receive(UpdateLocalCache)
slowRequest.complete(Left(new Exception))
// Although the test calls the actor synchronously, the actor calls *itself* asynchronously, so we must wait.
Thread.sleep(1000)
actor.receive(UpdateLocalCache)
there was two(remoteService).makeNetworkCall
}
The way we have chosen to solve this for now is to inject the equivalent of an observer into the actor (piggybacking on an existing logger which wasn't included in the listing in the question). The actor can then tell the observer when it has transitioned from various states. In the test code we perform an action then wait for the relevant notification from the actor, before continuing and making assertions.
In the test we have something like this:
actor.receive(UpdateLocalCache)
observer.doActionThenWaitForEvent(
{ actor.receive(UpdateLocalCache) }, // run this action
"IgnoredUpdateLocalCache" // then wait for the actor to emit an event
}
// assert on number of calls to remote service
I don't know if there's a more idiomatic way, this seems like a reasonable suggestion to me.