in imageCopier/src/main/scala/com/gu/imageCopier/attempt/Attempt.scala [216:265]
def Right[A](a: A): Attempt[A] =
Attempt(Future.successful(scala.Right(a)))
/** Syntax sugar to create an Attempt failure if there's only a single error.
*/
def Left[A](err: Failure): Attempt[A] =
Attempt(Future.successful(scala.Left(err)))
/** Asynchronous versions of the Attempt Right/Left helpers for when you have
* a Future that returns a good/bad value directly.
*/
object async {
/** Run f asynchronously and catch any non-fatal exceptions from the
* execution. This is typically used to wrap IO SDK calls.
* @param f
* function to run asynchronously
* @param recovery
* partial function to convert thrown exceptions to Failure types
*/
def catchNonFatal[A](f: => A)(
recovery: PartialFunction[Throwable, Failure]
)(implicit ec: ExecutionContext): Attempt[A] =
Attempt(Future(scala.Right(f)).recover { case NonFatal(t) =>
scala.Left(recovery.lift(t).getOrElse(UnknownFailure(t)))
})
/** Run f asynchronously and convert all non fatal exceptions to
* UnknownFailures. Best practice is to use catchNonFatal instead but this
* can be used when you don't know what kind of exceptions will be thrown
* or you have a blasé attitude to exceptions.
*/
def catchNonFatalBlasé[A](f: => A)(implicit
ec: ExecutionContext
): Attempt[A] = catchNonFatal(f)(Map.empty)
/** Create an Attempt from a Future of a good value.
*/
def Right[A](fa: Future[A])(implicit ec: ExecutionContext): Attempt[A] =
Attempt(fa.map(scala.Right(_)))
/** Create an Attempt from a known failure in the future. For example, if a
* piece of logic fails but you need to make a Database/API call to get the
* failure information.
*/
def Left[A](ferr: Future[Failure])(implicit
ec: ExecutionContext
): Attempt[A] =
Attempt(ferr.map(scala.Left(_)))
}