How to create a timer method with start and stop - scala

I want to execute a method every 5 seconds. I also need a start and stop
I am quite new to Scala so I don't have enough experience with timer object. I have played a bit with it but I do not have enough understanding of it
val timer = new Timer()
val run = timer.schedule(method(messageSender, "hello"), 5.Seconds)
def method (messageSender: MessageSender, message: String): Unit ={
messageSender.sendMessage(message)
}
run.start()
run.stop()
I know the code is not correct. I just wrote how I think it would look like raughly.
run.start would start executing the method every 5 seconds. and run.stop would stop the execution. Anyone have a rough idea of how I can achieve this.

By using akka actor I am doing it as follows
import system.dispatcher
val system = ActorSystem("mySystem", config)
//1 second as initial delay
system.scheduler.schedule(1 seconds, 5 seconds) {
taskToCall()
}
You can refer to this https://doc.akka.io/docs/akka/current/scheduler.html?language=scala

Related

Monix - Why does this future complete?

Below is a simple program that awaits a cancellable future. The future should evaluate to wait 20 seconds. I'm trying to demonstrate the 5.second max time bound kicking in. However, the program seems to ignore the 5.second max time bound, and waits for 20 seconds. Does anyone know why this is? Thanks
import com.github.nscala_time.time.Imports.{DateTime, richReadableInstant, richReadableInterval}
import monix.eval.Task
import monix.execution.Scheduler
import monix.execution.Scheduler.Implicits.global
import scala.concurrent.duration._
import scala.concurrent.Await
object TaskRunToFuture extends App {
def waitTwenty = {
val start = DateTime.now()
while ((start to DateTime.now()).millis < 20000) { /** do nothing */ }
}
val result = Await.result(Task.eval(waitTwenty).runToFuture, 5.seconds)
}
From Monix's Design Summary:
doesn’t necessarily execute on another logical thread
In your case, you've defined a Task that doesn't inherently have any "async boundaries" that would force Monix to shift to another thread, so when you call runToFuture it ends up executing waitTwenty on the current thread. Thus, the task has already completed by the time the Future is actually returned, so Await.result isn't actually called until the 20 seconds are up.
See Task#executeAsync which inserts an async boundary before the task, e.g. Task.eval(waitTwenty).executeAsync.runToFuture
Normally this kind of thing isn't an issue since you generally don't want to call any of the run* methods except in your application's main; instead you'll compose everything in terms of Task so your whole app is ultimately one big Task that can be run, e.g. as a TaskApp.
def waitTwenty = {
println("starting wait...")
Thread.sleep(20000)
println("done waiting!")
}
Await.result(Task.eval(waitTwenty).executeAsync.runToFuture, 5.seconds)
Outputs
waiting...
java.util.concurrent.TimeoutException: Future timed out after [5 seconds]
at scala.concurrent.impl.Promise$DefaultPromise.tryAwait0(Promise.scala:248)
at scala.concurrent.impl.Promise$DefaultPromise.result(Promise.scala:261)
at monix.execution.CancelableFuture$Async.result(CancelableFuture.scala:371)
at scala.concurrent.Await$.$anonfun$result$1(package.scala:201)
at scala.concurrent.BlockContext$DefaultBlockContext$.blockOn(BlockContext.scala:62)
at scala.concurrent.Await$.result(package.scala:124)
... 59 elided

Problems with afterAll() in ScalaTest in case of Future usage

At the end of my ScalaTest suite I need to do some DB clean up.
The cleanup itself is a Future. The suite does not call the super.afterAll() which leaves some resources used by the suite (like a web browser and db connections) pending.
Here is relevant pieces of code:
override def afterAll():Unit={
var cleanUpsInProgress = true
DB.cleanUpDeletedSegments(db).onComplete{case _ =>
cleanUpsInProgress = false
}
while(cleanUpsInProgress){}
db.close()
aggregatesDB.close()
super.afterAll()
}
and
def cleanUpDeletedSegments(implicit db:ADMPDB):Future[Int]={
db.run{
segments.filter(_.deleted === 1).delete
}
}
I've debugged and scratched my head for a while and got to conclusion it is not even processing the code in the future's onComplete callback. Even when I substitute Slick's db action with stub Future.successfull(1) I still have everything pending and super.afterAll() gets NOT invoked.
Probably I'm doing something stupidly wrong? Could you help?
Note: Also I do think I need to use this ugly var and while loop here because otherwise the main thread gets completed and the framework which initiates the suite running just closes JVM. Maybe I am wrong here so would be great to hear some comments.
--------------------------UPDATE----------------------
The solution by Tyler works. But when I flatMap one more asynch cleanup (which I actually need to do) then the problem is the same again. The code below freezes and does not call super.afterAll:
override def afterAll():Unit={
val cleanUp = DB.cleanUpDeletedSegments(db).flatMap(_ => DB.cleanUpDeletedSegmentGroups(db))
Await.result(cleanUp, 6 seconds)
db.close()
aggregatesDB.close()
super.afterAll()
}
Await.result also does not throw TimeoutException and from what I see neither completed normally. Any ideas?
It works only if I use Await.result sequentially for each future like below:
override def afterAll():Unit={
val cleanUpSegments = DB.cleanUpDeletedSegments(db)
Await.result(cleanUpSegments, 3 seconds)
val cleanUpSegmentGroups = DB.cleanUpDeletedSegmentGroups(db)
Await.result(cleanUpSegmentGroups, 3 seconds)
db.close()
aggregatesDB.close()
super.afterAll()
}
Its probably just easier to await for your Future cleanup to finish:
import scala.concurrent.Await
import scala.concurrent.duration._
override def afterAll() ={
val future = DB.cleanUpDeletedSegments(db)
Await.result(future, 2 minutes)
aggregatesDB.close()
super.afterAll()
}
You can set the timeout to whatever is reasonable
Use solution by #Tyler. Your solution didn't work because you used non-volatile variable cleanupInProgress from multiple threads.

Scala looping for certain duration

I'm looking for a possibility to loop for certain duration.
For example, I'd like to println("Hi there!") for 5 minutes.
I'm using Scala and Akka.
I was thinking about using future, which will be finished in 5 minutes, meanwhile I would use while cycle on it with check that it's not completed. Such approach doesn't work for me, as my class isn't an actor, and I cant finish the future from outside the loop.
Any ideas or maybe there are ready solutions for such things?
Current ugly solution:
def now = Calendar.getInstance.getTime.getTime
val ms = durationInMins * 60 * 1000
val finish = now + ms
while (now <= finish) {
println("hi")
}
Thanks in advance!
The solution of #Radian is potentially dangerous, as it will eventually block all the threads in the ExecutorService, when your app runs this code several times concurrently. You can better use a Deadline for that:
import scala.concurrent.duration._
val deadline = 5.seconds.fromNow
while(deadline.hasTimeLeft) {
// ...
}
val timeout = future{Thread.sleep(5000)}
while(!timeout.isCompleted){println("Hello")}
This works, but I don't like it because:
Long loops without sleeps are bad.
Long loops in the main Thread is blocking your application
Another solution, would be to move your logic (the print function) into a separate Actor, and introduce a scheduler to handle the timing for you, and another scheduler-once to send a PoisonPill after a duration
More about Scheduler
You can also do it in the actor manner:
case object Init
case object Loop
case object Stop
class Looper extends Actor {
var needToRun = true
def receive = {
case Init =>
needToRun = true
self ! Loop
case Stop =>
needToRun = false
case Loop =>
if(needToRun) {
//do whatever you need to do
self ! Loop
}
}
}
And use scheduler to send a message:
looperRef ! Init
system.scheduler.scheduleOnce(5 MINUTES, looperRef, Stop)

Time delay between futures in Play framework 2.1

I have a number of consuming works that are fully asynchronous and started roughly at the same time. I mean something like this:
for (i <- 1 to n) {
Future { startWork("work" + i) }
}
But I need to add some time lag to start these works successively at the different time. For example, if (time lag = 1 second) => i-work starts after i seconds. How can simply do this?
Thanks!
Play integrates Akka for scheduling. In Play's documentation, you can find an example for running a block of code once with a set delay:
import play.api.libs.concurrent.Execution.Implicits._
Akka.system.scheduler.scheduleOnce(10.seconds) {
file.delete()
}
Akka's documentation has some more info on its scheduler.
The argument (10.seconds) in the example is a FiniteDuration, so in your case, you'd probably want to set it to i seconds.
Yo Dawg! I heard you like Futures, so I'm going to show you how to execute a Future in the future so you can compose other Futures from your Future in the future.
import play.api.concurrent.Akka
import scala.concurrent._
import scala.concurrent.duration._
val promise = Promise[Unit]
Akka.system.scheduler.scheduleOnce(1.seconds) { promise.success() }
promise.future.map { _ => /* The body of the Future to be run in the future */ }
This should be a non-blocking solution do delay the execution of a Future until some time in the future.

Sleeping actors?

What's the best way to have an actor sleep? I have actors set up as agents which want to maintain different parts of a database (including getting data from external sources). For a number of reasons (including not overloading the database or communications and general load issues), I want the actors to sleep between each operation. I'm looking at something like 10 actor objects.
The actors will run pretty much infinitely, as there will always be new data coming in, or sitting in a table waiting to be propagated to other parts of the database etc. The idea is for the database to be as complete as possible at any point in time.
I could do this with an infinite loop, and a sleep at the end of each loop, but according to http://www.scala-lang.org/node/242 actors use a thread pool which is expanded whenever all threads are blocked. So I imagine a Thread.sleep in each actor would be a bad idea as would waste threads unnecessarily.
I could perhaps have a central actor with its own loop that sends messages to subscribers on a clock (like async event clock observers)?
Has anyone done anything similar or have any suggestions? Sorry for extra (perhaps superfluous) information.
Cheers
Joe
There was a good point to Erlang in the first answer, but it seems disappeared. You can do the same Erlang-like trick with Scala actors easily. E.g. let's create a scheduler that does not use threads:
import actors.{Actor,TIMEOUT}
def scheduler(time: Long)(f: => Unit) = {
def fixedRateLoop {
Actor.reactWithin(time) {
case TIMEOUT => f; fixedRateLoop
case 'stop =>
}
}
Actor.actor(fixedRateLoop)
}
And let's test it (I did it right in Scala REPL) using a test client actor:
case class Ping(t: Long)
import Actor._
val test = actor { loop {
receiveWithin(3000) {
case Ping(t) => println(t/1000)
case TIMEOUT => println("TIMEOUT")
case 'stop => exit
}
} }
Run the scheduler:
import compat.Platform.currentTime
val sched = scheduler(2000) { test ! Ping(currentTime) }
and you will see something like this
scala> 1249383399
1249383401
1249383403
1249383405
1249383407
which means our scheduler sends a message every 2 seconds as expected. Let's stop the scheduler:
sched ! 'stop
the test client will begin to report timeouts:
scala> TIMEOUT
TIMEOUT
TIMEOUT
stop it as well:
test ! 'stop
There's no need to explicitly cause an actor to sleep: using loop and react for each actor means that the underlying thread pool will have waiting threads whilst there are no messages for the actors to process.
In the case that you want to schedule events for your actors to process, this is pretty easy using a single-threaded scheduler from the java.util.concurrent utilities:
object Scheduler {
import java.util.concurrent.Executors
import scala.compat.Platform
import java.util.concurrent.TimeUnit
private lazy val sched = Executors.newSingleThreadScheduledExecutor();
def schedule(f: => Unit, time: Long) {
sched.schedule(new Runnable {
def run = f
}, time , TimeUnit.MILLISECONDS);
}
}
You could extend this to take periodic tasks and it might be used thus:
val execTime = //...
Scheduler.schedule( { Actor.actor { target ! message }; () }, execTime)
Your target actor will then simply need to implement an appropriate react loop to process the given message. There is no need for you to have any actor sleep.
ActorPing (Apache License) from lift-util has schedule and scheduleAtFixedRate Source: ActorPing.scala
From scaladoc:
The ActorPing object schedules an actor to be ping-ed with a given message at specific intervals. The schedule methods return a ScheduledFuture object which can be cancelled if necessary
There unfortunately are two errors in the answer of oxbow_lakes.
One is a simple declaration mistake (long time vs time: Long), but the second is some more subtle.
oxbow_lakes declares run as
def run = actors.Scheduler.execute(f)
This however leads to messages disappearing from time to time. That is: they are scheduled but get never send. Declaring run as
def run = f
fixed it for me. It's done the exact way in the ActorPing of lift-util.
The whole scheduler code becomes:
object Scheduler {
private lazy val sched = Executors.newSingleThreadedScheduledExecutor();
def schedule(f: => Unit, time: Long) {
sched.schedule(new Runnable {
def run = f
}, time - Platform.currentTime, TimeUnit.MILLISECONDS);
}
}
I tried to edit oxbow_lakes post, but could not save it (broken?), not do I have rights to comment, yet. Therefore a new post.