Mark
Mark

Reputation: 10964

Calling a function periodically in Scala while another expensive function is computing

I have a function that takes a long time to compute

def longFunc = {Thread.sleep(30000); true}

while this function is computing, I'd need to ping a server so it keeps waiting for the value of my function. But for the sake of the argument let's say I need to run the following function every 5 seconds while my longFunc is running

def shortFunc = println("pinging server! I am alive!")

To do this I have the following snippet and it works but I wonder if there is a better pattern for this scenario

import scala.concurrent.{Await, Future}
import scala.concurrent.duration._
import java.util.{Timer, TimerTask}
import scala.concurrent.ExecutionContext.Implicits.global

def shortFunc = println("pinging server! I am alive!")
def longFunc = {Thread.sleep(30000); true}

val funcFuture = Future{longFunc}

val timer = new Timer()
def pinger = new TimerTask {
        def run(): Unit = shortFunc
}

timer.schedule(pinger, 0L, 5000L) // ping the server every two minutes to say you are still working
val done = Await.result(funcFuture, 1 minutes)
pinger.cancel 

Upvotes: 0

Views: 512

Answers (1)

Bogdan Vakulenko
Bogdan Vakulenko

Reputation: 3390

I'm not actually sure if this is more elegant pattern or just for fun:

import scala.concurrent.{Await, Future}
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global

def waiter[T](futureToWait:Future[_], waitFunc: => T, timer: Duration) = Future {
  while (!futureToWait.isCompleted) {
    Try(Await.ready(futureToWait, timer))
    waitFunc
  }
}

def longFunc = {Thread.sleep(30000); true}
def shortFunc = println("pinging server! I am alive!")

val funcFuture = Future{longFunc}
waiter(funcFuture,shortFunc,5 second)

val done = Await.result(funcFuture, 1 minutes)

The same but shorter:

import scala.concurrent.{Await, Future}
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global

def longFunc = {Thread.sleep(30000); true}
def shortFunc = println("pinging server! I am alive!")

val funcFuture = Future{longFunc}

def ff:Future[_] = Future{
  shortFunc
  Try(Await.ready(funcFuture, 5 second)).getOrElse(ff)
}
ff

val done = Await.result(funcFuture, 1 minutes)

Upvotes: 1

Related Questions