Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // @deprecated.
- // Please note that this way is recommended: https://pastebin.com/H9S4rGJT
- // 1. Simple Action
- class TestController @Inject() (cc: ControllerComponents) extends AbstractController(cc) {
- // add to routes file: GET /testFuture controllers.TestController.testFuture
- def testFuture = Action {
- Logger.debug(LocalDateTime.now() + ": Start!")
- Thread.sleep(3000)
- Logger.debug(LocalDateTime.now() + ": Finish!")
- Ok("OK")
- }
- }
- // Output:
- // [debug] application - 2018-01-15T22:17:56.484: Start!
- // [debug] application - 2018-01-15T22:17:59.484: Finish!
- // 2. Now make it async:
- import scala.concurrent.{ExecutionContext, Future}
- class TestController @Inject()(cc: ControllerComponents)(implicit ec: ExecutionContext) extends AbstractController(cc) {
- // add to routes file: GET /testFuture controllers.TestController.testFuture
- def testFuture: Action[AnyContent] = Action.async {
- Future {
- Logger.debug(LocalDateTime.now() + ": Start!")
- Thread.sleep(3000)
- Logger.debug(LocalDateTime.now() + ": Finish!")
- Ok("OK")
- }
- }
- }
- // Output:
- // [debug] application - 2018-01-15T22:21:23.310: Start!
- // [debug] application - 2018-01-15T22:21:26.310: Finish!
- // 3. Let's make work harder!
- Thread.sleep(20000)
- // Output:
- // [debug] application - 2018-01-15T22:39:31.162: Start!
- // [debug] application - 2018-01-15T22:39:51.163: Finish!
- // 4. And finally we create a guard function "withTimeout":
- // utils/package.scala
- import scala.concurrent.duration.FiniteDuration
- import scala.concurrent.{ExecutionContext, Future, TimeoutException}
- import akka.actor.Scheduler
- import akka.pattern.after
- package object utils {
- /**
- * Creates a new [[scala.concurrent.Future Future]] based on a given Future with given timeout
- * @param duration duration for timeout, e.g: {{{5 seconds}}}
- * @param f base Future
- * @param ec external [[scala.concurrent.ExecutionContext ExecutionContext]]
- * @param scheduler external [[akka.actor.Scheduler Scheduler]], e.g:
- * {{{implicit val scheduler = actorSystem.scheduler}}}
- * @return new wrapped Future enhanced with timeout
- */
- def withTimeout[T](duration: FiniteDuration)(f: => Future[T])
- (implicit ec: ExecutionContext, scheduler: Scheduler): Future[T] = {
- val timeoutFut = after(duration, scheduler)(Future.failed(new TimeoutException(s"Future timed out after $duration")))
- Future.firstCompletedOf(Seq(f, timeoutFut))
- }
- }
- // TestController.scala
- import java.time.LocalDateTime
- import javax.inject.Inject
- import scala.concurrent.{ExecutionContext, Future}
- import scala.concurrent.duration._
- import akka.actor.ActorSystem
- import play.api.Logger
- import play.api.mvc.{AbstractController, Action, AnyContent, ControllerComponents}
- import utils.withTimeout
- class TestController @Inject()(cc: ControllerComponents, actorSystem: ActorSystem)(implicit ec: ExecutionContext)
- extends AbstractController(cc) {
- implicit val scheduler = actorSystem.scheduler
- // add to routes file: GET /testFuture controllers.TestController.testFuture
- def testFuture: Action[AnyContent] = Action.async {
- withTimeout(5 seconds) {
- Future {
- Logger.debug(LocalDateTime.now() + ": Start!")
- Thread.sleep(20000)
- Logger.debug(LocalDateTime.now() + ": Finish!")
- Ok("OK")
- }
- }
- }
- }
- // Output:
- // [debug] application - 2018-01-15T22:45:45.316: Start!
- // [error] application -
- //
- // ! @76jgce8bj - Internal server error, for (GET) [/testFuture] ->
- //
- // play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[TimeoutException: Future timed out after 5 seconds]]
- // at play.api.http.HttpErrorHandlerExceptions$.throwableToUsefulException(HttpErrorHandler.scala:255)
- // ...
- // Caused by: java.util.concurrent.TimeoutException: Future timed out after 5 seconds
- // at utils.package$.$anonfun$withTimeout$1(package.scala:18)
- // ...
- // [debug] application - 2018-01-15T22:46:05.316: Finish!
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement