1 /*
2  *  Make.org Core API
3  *  Copyright (C) 2021 Make.org
4  *
5  * This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU Affero General Public License as
7  *  published by the Free Software Foundation, either version 3 of the
8  *  License, or (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU Affero General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Affero General Public License
16  *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
17  *
18  */
19 
20 package org.make.api.technical
21 
22 import akka.actor.typed.{ActorRef, ActorSystem}
23 import akka.actor.typed.scaladsl.AskPattern._
24 import akka.util.Timeout
25 
26 import java.util.concurrent.TimeoutException
27 import scala.concurrent.{ExecutionContext, Future, Promise}
28 
29 object BetterLoggingActors {
30 
31   implicit class BetterLoggingTypedActorRef[Req](val ref: ActorRef[Req]) extends AnyVal {
32     def ??[Res](
33       replyTo: ActorRef[Res] => Req
34     )(implicit ec: ExecutionContext, system: ActorSystem[_], timeout: Timeout): Future[Res] = {
35       val message = Promise[Req]()
36       ref.ask { sender: ActorRef[Res] =>
37         val value = replyTo(sender)
38         message.success(value)
39         value
40       }.recoverWith {
41         case e: TimeoutException => message.future.flatMap(m => Future.failed(ActorTimeoutException(m, e)))
42         case other               => Future.failed(other)
43       }
44     }
45   }
46 
47 }
Line Stmt Id Pos Tree Symbol Tests Code
35 329 1292 - 1306 Apply scala.concurrent.Promise.apply scala.concurrent.Promise.apply[Req]()
40 385 1313 - 1623 ApplyToImplicitArgs scala.concurrent.Future.recoverWith akka.actor.typed.scaladsl.AskPattern.Askable[Req](BetterLoggingTypedActorRef.this.ref).ask[Res](((sender: akka.actor.typed.ActorRef[Res]) => { val value: Req = replyTo.apply(sender); message.success(value); value }))(timeout, akka.actor.typed.scaladsl.AskPattern.schedulerFromActorSystem(system)).recoverWith[Res](({ @SerialVersionUID(value = 0) final <synthetic> class $anonfun extends scala.runtime.AbstractPartialFunction[Throwable,scala.concurrent.Future[Res]] with java.io.Serializable { def <init>(): <$anon: Throwable => scala.concurrent.Future[Res]> = { $anonfun.super.<init>(); () }; final override def applyOrElse[A1 <: Throwable, B1 >: scala.concurrent.Future[Res]](x1: A1, default: A1 => B1): B1 = ((x1.asInstanceOf[Throwable]: Throwable): Throwable @unchecked) match { case (e @ (_: java.util.concurrent.TimeoutException)) => message.future.flatMap[Nothing](((m: Req) => scala.concurrent.Future.failed[Nothing](ActorTimeoutException.apply(m, e))))(ec) case (other @ _) => scala.concurrent.Future.failed[Nothing](other) case (defaultCase$ @ _) => default.apply(x1) }; final def isDefinedAt(x1: Throwable): Boolean = ((x1.asInstanceOf[Throwable]: Throwable): Throwable @unchecked) match { case (e @ (_: java.util.concurrent.TimeoutException)) => true case (other @ _) => true case (defaultCase$ @ _) => false } }; new $anonfun() }: PartialFunction[Throwable,scala.concurrent.Future[Res]]))(ec)