Advertisement
Guest User

Untitled

a guest
Jul 20th, 2017
58
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 3.14 KB | None | 0 0
  1.  
  2. import Retry.{LazyLogging, Recovery}
  3. import Retry.Recovery.RecoverySettings
  4. import rx.lang.scala.Observable
  5.  
  6. import scala.annotation.tailrec
  7. import scala.concurrent.{ExecutionContext, Future}
  8. import scala.util.Try
  9.  
  10. object Retry {
  11.  
  12.   trait Recovery {
  13.     this: LazyLogging =>
  14.  
  15.     trait RecoverableLike[T[_]] {
  16.       import RecoverableLike._
  17.       def recoverWith[R](t: => T[R], f: RecoveryFun[T, R]): T[R]
  18.     }
  19.  
  20.     object RecoverableLike {
  21.       type RecoveryFun[T[_], R] = PartialFunction[Throwable, T[R]]
  22.  
  23.       def apply[T[_]: RecoverableLike, R]: RecoverableLike[T] = implicitly[RecoverableLike[T]]
  24.  
  25.       implicit def recoverableObservable: RecoverableLike[Observable] = new RecoverableLike[Observable] {
  26.         override def recoverWith[T](t: => Observable[T], f: RecoveryFun[Observable, T]): Observable[T] =
  27.           t.onErrorResumeNext(f)
  28.       }
  29.  
  30.       implicit def recoverableFuture(implicit ec: ExecutionContext): RecoverableLike[Future] = new RecoverableLike[Future] {
  31.         override def recoverWith[T](t: => Future[T], f: RecoveryFun[Future, T]): Future[T] =
  32.           t.recoverWith(f)
  33.       }
  34.  
  35.       implicit def recoverableTry: RecoverableLike[Try] = new RecoverableLike[Try] {
  36.         override def recoverWith[T](t: => Try[T], f: RecoveryFun[Try, T]): Try[T] =
  37.           t.recoverWith(f)
  38.       }
  39.  
  40.       type Supplier[T] = T
  41.       implicit def recoverableSupplier[T]: RecoverableLike[Supplier] = new RecoverableLike[Supplier] {
  42.         override def recoverWith[T](t: => Supplier[T], f: RecoveryFun[Supplier, T]): Supplier[T] = {
  43.           recoverSupplier(t, f)
  44.         }
  45.       }
  46.  
  47.       private def recoverSupplier[T](supplier: => Supplier[T], recovery: RecoveryFun[Supplier, T]): Supplier[T] = {
  48.         (Try {
  49.           supplier
  50.         } recover {
  51.           recovery
  52.         }).get
  53.       }
  54.     }
  55.     def retry[T[_] : RecoverableLike, R](msg: String)(f: => T[R])(implicit recoverySettings: RecoverySettings): T[R] = {
  56.       retryRecursively(msg, 1, f)
  57.     }
  58.  
  59.     @tailrec
  60.     private def retryRecursively[T[_] : RecoverableLike, R](msg: String, retry: Int, f: => T[R])
  61.                                                            (implicit recoverySettings: RecoverySettings): T[R] = {
  62.       if (retry > recoverySettings.retries) f
  63.       else retryRecursively(msg, retry + 1,
  64.         RecoverableLike[T, R].recoverWith(f, {
  65.           case t: Throwable =>
  66.             logger.error(s"$msg (retry $retry of ${recoverySettings.retries})", t)
  67.             f
  68.         }))
  69.     }
  70.   }
  71.  
  72.   object Recovery {
  73.  
  74.     case class RecoverySettings(delay: Int, retries: Int)
  75.  
  76.   }
  77.  
  78.   trait LazyLogging {
  79.  
  80.     object logger {
  81.       def error(s: String, t: Throwable) = {
  82.         println(s)
  83.         t.printStackTrace()
  84.       }
  85.     }
  86.  
  87.   }
  88.  
  89. }
  90.  
  91. object Test extends App with Recovery with LazyLogging {
  92.   implicit val recoverySettings: RecoverySettings = RecoverySettings(100, 4)
  93.   import  scala.concurrent.ExecutionContext.Implicits._
  94.   var i = 0
  95.   def f(): Int = {
  96.     i += 1
  97.     if(i < 3) throw new RuntimeException
  98.     else 4
  99.   }
  100.  
  101.  
  102.   retry("Failed to get int") (Try(f())).foreach(println)
  103.  
  104.   Thread.sleep(1000)
  105.  
  106. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement