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 scala.concurrent.{ExecutionContext, Future}
23 
24 final case class ValueNotFoundException(message: String) extends Exception(message)
25 
26 object Futures {
27 
28   implicit class RichFutures[T](val self: Future[T]) extends AnyVal {
29     def withoutFailure(implicit executionContext: ExecutionContext): Future[Either[Throwable, T]] = {
30       self.map(Right(_)).recoverWith { case e => Future.successful(Left(e)) }
31     }
32   }
33 
34   implicit class Fallback[T](val f: () => Future[Option[Option[T]]]) extends AnyVal {
35     def or(fallback: () => Future[Option[T]])(implicit executionContext: ExecutionContext): () => Future[Option[T]] =
36       () =>
37         f().flatMap {
38           case Some(t @ Some(_)) => Future.successful(t)
39           case _                 => fallback()
40         }
41   }
42 
43   implicit class FutureOfOption[T](val future: Future[Option[T]]) extends AnyVal {
44 
45     def flattenOrFail(errMsg: String)(implicit ec: ExecutionContext): Future[T] =
46       future.flatMap(_.fold(Future.failed[T](ValueNotFoundException(errMsg)))(Future.successful))
47   }
48 }
Line Stmt Id Pos Tree Symbol Tests Code
30 110 1110 - 1181 ApplyToImplicitArgs scala.concurrent.Future.recoverWith RichFutures.this.self.map[scala.util.Right[Nothing,T]](((x$1: T) => scala.`package`.Right.apply[Nothing, T](x$1)))(executionContext).recoverWith[Either[Throwable,T]](({ @SerialVersionUID(value = 0) final <synthetic> class $anonfun extends scala.runtime.AbstractPartialFunction[Throwable,scala.concurrent.Future[Either[Throwable,T]]] with java.io.Serializable { def <init>(): <$anon: Throwable => scala.concurrent.Future[Either[Throwable,T]]> = { $anonfun.super.<init>(); () }; final override def applyOrElse[A1 <: Throwable, B1 >: scala.concurrent.Future[Either[Throwable,T]]](x1: A1, default: A1 => B1): B1 = ((x1.asInstanceOf[Throwable]: Throwable): Throwable @unchecked) match { case (e @ _) => scala.concurrent.Future.successful[scala.util.Left[Throwable,Nothing]](scala.`package`.Left.apply[Throwable, Nothing](e)) case (defaultCase$ @ _) => default.apply(x1) }; final def isDefinedAt(x1: Throwable): Boolean = ((x1.asInstanceOf[Throwable]: Throwable): Throwable @unchecked) match { case (e @ _) => true case (defaultCase$ @ _) => false } }; new $anonfun() }: PartialFunction[Throwable,scala.concurrent.Future[Either[Throwable,T]]]))(executionContext)
37 49 1417 - 1544 ApplyToImplicitArgs scala.concurrent.Future.flatMap org.make.api.crmtemplates.crmtemplatesservicetest Fallback.this.f.apply().flatMap[Option[T]](((x0$1: Option[Option[T]]) => x0$1 match { case (value: Option[T]): Some[Option[T]]((t @ (value: T): Some[T](_))) => scala.concurrent.Future.successful[Some[T]](t) case _ => fallback.apply() }))(executionContext)
46 257 1722 - 1813 ApplyToImplicitArgs scala.concurrent.Future.flatMap org.make.api.technical.crm.sendmailpublisherservicetest FutureOfOption.this.future.flatMap[T](((x$2: Option[T]) => x$2.fold[scala.concurrent.Future[T]](scala.concurrent.Future.failed[T](ValueNotFoundException.apply(errMsg)))(((result: T) => scala.concurrent.Future.successful[T](result)))))(ec)