I'm trying to develop a control structure that retries on some declared exceptions but throw others. The control structure works nicely but I have problem checking if the exception caught belongs to the types of declared exceptions. In more generic words, how do I check if a parameter is one of the declared list of type parameters?
Define a retry control structure:
def retry[T, R](times:Int=3, delay:Int=1000)(ex:Class[_<:Exception]*)(t:T)(block:T=>R):R = {
try {
block(t)
}
catch {
case e:Exception if (isOneOf(e, ex:_*) && times>0) => {
println(s"Exception $e happened, sleep $delay milliseconds")
Thread.sleep(delay)
println(s"$times times remain for retry before give up")
retry(times-1, delay)(ex:_*)(t)(block)
}
case e:Throwable => {
println(s"Exception $e is not handled")
throw e
}
}
}
define isOneOf function to check the declared and runtime exception type
def isOneOf[T:scala.reflect.ClassTag](obj:T, cs:Class[_]*) = {
val dc = obj.getClass
val rc = scala.reflect.classTag[T].runtimeClass
cs.exists(c=>c.isAssignableFrom(dc) || c.isAssignableFrom(rc))
}
define a function that throws multiple exceptions
def d(str:String) = {
val r = Math.random()
println(r)
if (r>0.6) throw new IllegalArgumentException
else if (r>0.4) throw new java.io.IOException
else if (r>0.2) throw new UnsupportedOperationException
else println(str)
}
and I can call the function with retry as:
retry(3, 1000)(classOf[IllegalArgumentException], classOf[java.io.IOException])("abc"){
x=> d(x)
}
I want to retry on IllegalArgumentException and IOException, but will throw UnsupportedOperationException.
My goal is to call the function like this:
retry(3, 1000)[IllegalArgumentException, java.io.IOException]("abc"){
x=> d(x)
}
For the retry structure, the list of declared exceptions is passed in dynamically at runtime. So multiple exception case statement does not work for me. When an exception is caught, I match it with generic exception, check the exception type with the isOneOf function. Ideally the function will take a sequence of types, instead of a sequence of classes. How do I pass in a sequence of exception types, rather than a sequence of classes and check the caught exception against the sequence of types?
What do you think about replacing the list of exceptions with the function that knows which of exceptions are recoverable (and which you can build dynamically):
recoverablefunction could look like this: