Akka scheduler not completing - scala

I need to send a message to an actor at specific intervals. I am using the following code:
object SendToActor extends App {
import Sender._
val system: ActorSystem = ActorSystem("sender")
try {
val senderActor: ActorRef = system.actorOf(Sender.props, "sendActor")
val sendSchedule =
system.scheduler.schedule(0 milliseconds, 5 minutes, senderActor, doSomething())
} finally {
system.terminate()
}
}
Unfortunately, the scheduler doesn't seem to run unless I do one of the following:
Put a readLine() right after it:
val sendSchedule = system.scheduler.schedule(0 milliseconds, 5 minutes, senderActor, doSomething())
readLine()
Put a Thread.sleep() right after it:
val sendSchedule = system.scheduler.schedule(0 milliseconds, 5 minutes, senderActor, doSomething())
Thread.sleep(10000)
Is there a reason why the scheduler won't run as coded above? Why does it require the sleep in order to work?

Probably because you're terminating the actor system immediately after defining the scheduler.

Related

Testing delayed messages with the help of akka-testkit

There are two actors - ProducerActor and ConsumerActor. Producer has a scheduler which sends "Tick" message to itself each 2000 ms. After that the producer sends "Hello" message to consumer:
class ProducerActor(consumer: ActorRef) extends Actor {
override def receive: Receive = {
case "Tick" =>
...
// some code which takes < 1 ms
...
consumer ! "Hello"
}
override def preStart: Unit =
context.system
.scheduler
.schedule(2000 milliseconds, 2000 milliseconds, self, "Tick")
}
Is it possible to test the case when the consumer actor receives a "Hello" message each 2000 ms? So, if message is received in period < 2000 ms or > 2000 ms then test will assert error.
For example:
"Consumer test" should {
"receive message each 2000 ms" in {
...
val consumer = TestProbe()
val producer = system.actorOf(Props(new ProducerActor(consumer.ref))
...
consumer.howToExpectDelayedMessage(minDelay = 2000 millis, "Hello")
}
}
--- UPD ---
I have figured out the following solution which works fine for me:
"Consumer test" should {
"receive message each 2000 ms" in {
val consumer = TestProbe()
val producer = system.actorOf(Props(new ProducerActor(consumer.ref))
// check the first ten periods
(0 to 10) foreach { _ =>
consumer.expectNoMsg(2000 millis)
consumer.expectMsg("Hello")
}
}
}
But if there is a better solution for this task it would be great if you could share.
You can use Timing Assessions to do that.
certain events must not happen immediately (like a timer), others need to happen before a deadline. Therefore, all examination methods accept an upper time limit within the positive or negative result must be obtained.
import akka.actor.Props
import scala.concurrent.duration._
val worker = system.actorOf(Props[Worker]())
within(200 millis) {
worker ! "some work"
expectMsg("some result")
expectNoMessage() // will block for the rest of the 200ms
Thread.sleep(300) // will NOT make this block fail
}
The block given to within must complete after a duration which is between min and max, where the former defaults to zero.

Akka Thread Tuning

I have 100 threads, need to process only 12 threads at a time not more than that. After completion of these threads other 12 have to be processed and so on but it's processing only first 12 set threads then it terminates after that.
Here is my Logic :
class AkkaProcessing extends Actor {
def receive = {
case message: List[Any] =>
var meterName = message(0) // It Contains only 12 threads , it process them and terminates. Am unable to get remaining threads
val sqlContext = message(1).asInstanceOf[SQLContext]
val FlagDF = message(2).asInstanceOf[DataFrame]
{
All the business logic here
}
context.system.shutdown()
}
}
}
object Processing {
def main(args: Array[String]) = {
val rawBuff = new ArrayBuffer[Any]()
val actorSystem = ActorSystem("ActorSystem") // Creating ActorSystem
val actor = actorSystem.actorOf(Props[AkkaProcessing].withRouter(RoundRobinPool(200)), "my-Actor")
implicit val executionContext = actorSystem.dispatchers.lookup("akka.actor.my-dispatcher")
for (i <- 0 until meter_list.length) {
var meterName = meter_list(i) // All 100 Meters here
rawBuff.append(meterName, sqlContext, FlagDF)
actor ! rawBuff.toList
}
}
}
Any Inputs highly appreciated
I think you might be best to create 2 actor types : consumer (which run in parallel) and coordinator (which takes the 12 thread tasks and passes them to the consumers). The coordinator would wait for the consumers to finish and then run the next batch.
See this answer for a code example: Can Scala actors process multiple messages simultaneously?
Failing that, you could just use Futures in a similar manner.

Scala future sequence and timeout handling

There are some good hints how to combine futures with timeouts.
However I'm curious how to do this with Future sequence sequenceOfFutures
My first approach looks like this
import scala.concurrent._
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits._
object FutureSequenceScala extends App {
println("Creating futureList")
val timeout = 2 seconds
val futures = List(1000, 1500, 1200, 800, 2000) map { ms =>
val f = future {
Thread sleep ms
ms toString
}
Future firstCompletedOf Seq(f, fallback(timeout))
}
println("Creating waitinglist")
val waitingList = Future sequence futures
println("Created")
val results = Await result (waitingList, timeout * futures.size)
println(results)
def fallback(timeout: Duration) = future {
Thread sleep (timeout toMillis)
"-1"
}
}
Is there a better way to handle timeouts in a sequence of futures or is this a valid solution?
There are a few things in your code here that you might want to reconsider. For starters, I'm not a huge fan of submitting tasks into the ExecutionContext that have the sole purpose of simulating a timeout and also have Thread.sleep used in them. The sleep call is blocking and you probably want to avoid having a task in the execution context that is purely blocking for the sake of waiting a fixed amount of time. I'm going to steal from my answer here and suggest that for pure timeout handling, you should use something like I outlined in that answer. The HashedWheelTimer is a highly efficient timer implementation that is mush better suited to timeout handling than a task that just sleeps.
Now, if you go that route, the next change I would suggest concerns handling the individual timeout related failures for each future. If you want an individual failure to completely fail the aggregate Future returned from the sequence call, then do nothing extra. If you don't want that to happen, and instead want a timeout to return some default value instead, then you can use recover on the Future like this:
withTimeout(someFuture).recover{
case ex:TimeoutException => someDefaultValue
}
Once you've done that, you can take advantage of the non-blocking callbacks and do something like this:
waitingList onComplete{
case Success(results) => //handle success
case Failure(ex) => //handle fail
}
Each future has a timeout and thus will not just run infinitely. There is no need IMO to block there and provide an additional layer of timeout handling via the atMost param to Await.result. But I guess this assumes you are okay with the non-blocking approach. If you really need to block there, then you should not be waiting timeout * futures.size amount of time. These futures are running in parallel; the timeout there should only need to be as long as the individual timeouts for the futures themselves (or just slightly longer to account for any delays in cpu/timing). It certainly should not be the timeout * the total number of futures.
Here's a version that shows how bad your blocking fallback is.
Notice that the executor is single threaded and you're creating many fallbacks.
#cmbaxter is right, your master timeout shouldn't be timeout * futures.size, it should be bigger!
#cmbaxter is also right that you want to think non-blocking. Once you do that, and you want to impose timeouts, then you will pick a timer component for that, see his linked answer (also linked from your linked answer).
That said, I still like my answer from your link, in so far as sitting in a loop waiting for the next thing that should timeout is really simple.
It just takes a list of futures and their timeouts and a fallback value.
Maybe there is a use case for that, such as a simple app that just blocks for some results (like your test) and must not exit before results are in.
import scala.concurrent._
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext
import java.util.concurrent.Executors
import java.lang.System.{ nanoTime => now }
object Test extends App {
//implicit val xc = ExecutionContext.global
implicit val xc = ExecutionContext fromExecutorService (Executors.newSingleThreadExecutor)
def timed[A](body: =>A): A = {
val start = now
val res = body
val end = now
Console println (Duration fromNanos end-start).toMillis + " " + res
res
}
println("Creating futureList")
val timeout = 1500 millis
val futures = List(1000, 1500, 1200, 800, 2000) map { ms =>
val f = future {
timed {
blocking(Thread sleep ms)
ms toString
}
}
Future firstCompletedOf Seq(f, fallback(timeout))
}
println("Creating waitinglist")
val waitingList = Future sequence futures
println("Created")
timed {
val results = Await result (waitingList, 2 * timeout * futures.size)
println(results)
}
xc.shutdown
def fallback(timeout: Duration) = future {
timed {
blocking(Thread sleep (timeout toMillis))
"-1"
}
}
}
What happened:
Creating futureList
Creating waitinglist
Created
1001 1000
1500 -1
1500 1500
1500 -1
1200 1200
1500 -1
800 800
1500 -1
2000 2000
1500 -1
List(1000, 1500, 1200, 800, 2000)
14007 ()
Monix Task has timeout support:
import monix.execution.Scheduler.Implicits.global
import monix.eval._
import scala.concurrent.duration._
println("Creating futureList")
val tasks = List(1000, 1500, 1200, 800, 2000).map{ ms =>
Task {
Thread.sleep(ms)
ms.toString
}.timeoutTo(2.seconds, Task.now("-1"))
}
println("Creating waitinglist")
val waitingList = Task.gather(tasks) // Task.sequence is true/literally "sequencing" operation
println("Created")
val results = Await.result(waitingList, timeout * futures.size)
println(results)

Scheduling a task at a fixed time of the day with Akka

I am a beginner with Akka. I need to schedule a task each day at a fixed time of the day, say 8AM. What I know how to do is scheduling a task periodically, for instance
import akka.util.duration._
scheduler.schedule(0 seconds, 10 minutes) {
doSomething()
}
What is the simplest way to schedule tasks at fixed times of the day in Akka?
A small parenthesis
It is easy to do what I want just using this feature. A toy implementation would look like
scheduler.schedule(0 seconds, 24 hours) {
val now = computeTimeOfDay()
val delay = desiredTime - now
scheduler.scheduleOnce(delay) {
doSomething()
}
}
It is not difficult, but I introduced a little race condition. In fact, consider what happens if I launch this just before 8AM. The external closure will start, but by the time I compute delay we may be after 8AM. This means that the internal closure - which should execute right away - will be postponed to tomorrow, thereby skipping execution for one day.
There are ways to fix this race condition: for instance I could perform the check every 12 hours, and instead of scheduling the task right away, sending it to an actor that will not accept more than one task at a time.
But probably, this already exist in Akka or some extension.
Write once, run everyday
val GatherStatisticsPeriod = 24 hours
private[this] val scheduled = new AtomicBoolean(false)
def calcBeforeMidnight: Duration = {
// TODO implement
}
def preRestart(reason: Throwable, message: Option[Any]) {
self ! GatherStatisticsScheduled(scheduled.get)
super.preRestart(reason, message)
}
def schedule(period: Duration, who: ActorRef) =
ServerRoot.actorSystem.scheduler
.scheduleOnce(period)(who ! GatherStatisticsTick)
def receive = {
case StartServer(nodeName) =>
sender ! ServerStarted(nodeName)
if (scheduled.compareAndSet(false, true))
schedule(calcBeforeMidnight, self)
case GatherStatisticsTick =>
stats.update
scheduled.set(true)
schedule(GatherStatisticsPeriod, self)
case GatherStatisticsScheduled(isScheduled) =>
if (isScheduled && scheduled.compareAndSet(false, isScheduled))
schedule(calcBeforeMidnight, self)
}
I believe that Akka's scheduler handles restarts internally, one way or another. I used non-persistent way of sending a message to self - actually no strict guarantee of delivery. Also, ticks may vary, so GatherStatisticsPeriod might be a function.
To use this kind of scheduling in Akka, you would have to roll your own or maybe use Quartz, either through Akka Camel or this prototype quartz for akka.
If you don't need anything fancy and extremely accurate, then I would just calculate the delay to the desired first time and use that as the start delay to the schedule call, and trust the interval.
Let's say you want to run your task every day at 13 pm.
import scala.concurrent.duration._
import java.time.LocalTime
val interval = 24.hours
val delay = {
val time = LocalTime.of(13, 0).toSecondOfDay
val now = LocalTime.now().toSecondOfDay
val fullDay = 60 * 60 * 24
val difference = time - now
if (difference < 0) {
fullDay + difference
} else {
time - now
}
}.seconds
system.scheduler.schedule(delay, interval)(doSomething())
Also remember that server timezone may be different from yours.
Just to add another way to achieve it, this can be done using Akka Streams by ticking a message and filtering on time.
Source
.tick(0.seconds, 2.seconds, "hello") // emits "hello" every two seconds
.filter(_ => {
val now = LocalDateTime.now.getSecond
now > 20 && now < 30 // will let through only if the timing is right.
})
.runForeach(n => println("final sink received " + n))

scala 2.10 callback at the end of a `Deadline`

In Scala 2.10, along with the new Future/Promise API, they introduced a Duration and Deadline utilities (as described here). I looked around but couldn't find anything that comes with the scala standard library, to do something like:
val deadline = 5 seconds fromNow
After(deadline){
//do stuff
}
//or
val deadlineFuture: Future[Nothing] = (5 seconds fromNow).asFuture
deadlineFuture onComplete {
//do stuff
}
Is there anything like that available that I've missed, or will I have to implement this kind of behavior myself?
Not quite built in, but they provide just enough rope.
The gist is to wait on an empty promise that must disappoint (i.e., time out).
import scala.concurrent._
import scala.concurrent.duration._
import scala.util._
import ExecutionContext.Implicits.global
object Test extends App {
val v = new SyncVar[Boolean]()
val deadline = 5 seconds fromNow
future(Await.ready(Promise().future, deadline.timeLeft)) onComplete { _ =>
println("Bye, now.")
v.put(true)
}
v.take()
// or
val w = new SyncVar[Boolean]()
val dropdeadline = 5 seconds fromNow
val p = Promise[Boolean]()
p.future onComplete {_ =>
println("Bye, now.")
w.put(true)
}
Try(Await.ready(Promise().future, dropdeadline.timeLeft))
p trySuccess true
w.take()
// rolling it
implicit class Expiry(val d: Deadline) extends AnyVal {
def expiring(f: =>Unit) {
future(Await.ready(Promise().future, d.timeLeft)) onComplete { _ =>
f
}
}
}
val x = new SyncVar[Boolean]()
5 seconds fromNow expiring {
println("That's all, folks.")
x.put(true)
}
x.take() // wait for it
}
Its just a timestamp holder. For example you need to distribute execution of N sequential tasks, in T hours. When you have finished with the first one, you check a deadline and schedule next task depending on (time left)/(tasks left) interval. At some point of time isOverdue() occurs, and you just execute tasks left, in parallel.
Or you could check isOverdue(), and if still false, use timeLeft() for setting timeout on executing the next task, for example.
It's much better than manipulating with Date and Calendar to determine time left. Also Duration was used in Akka for timing.