2013-12-20 3 views
1

Я пытаюсь разработать структуру управления, которая повторяет некоторые объявленные исключения, но бросает других. Структура управления работает хорошо, но у меня есть проблема с проверкой, если обнаруженное исключение относится к типам объявленных исключений. В более общих словах, как проверить, является ли параметр одним из объявленных списков параметров типа?Проверить несколько исключений в структуре управления повторной попыткой Scala

Определить структуру управления Retry:

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 
    } 
} 

}

определяет функцию isOneOf для проверки заявленного и исключения автономной работы Типа

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)) 
} 

определить функцию, которая выбрасывает несколько исключений

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) 
} 

и я могу вызвать функцию с повторной попытки, как:

retry(3, 1000)(classOf[IllegalArgumentException], classOf[java.io.IOException])("abc"){ 
    x=> d(x) 
} 

Я хочу повторить на IllegalArgumentException и IOException, но бросит UnsupportedOperationException.

Моя цель состоит в том, чтобы вызвать функцию следующим образом:

retry(3, 1000)[IllegalArgumentException, java.io.IOException]("abc"){ 
    x=> d(x) 
} 

Для структуры повторных попыток, перечень заявленных исключений передается в динамически во время выполнения. Таким образом, множество случаев исключения исключений для меня не работает. Когда исключение поймано, я сопоставляю его с общим исключением, проверяю тип исключения с помощью функции isOneOf. В идеале функция будет принимать последовательность типов, а не последовательность классов. Как передать последовательность типов исключений, а не последовательность классов и проверить исключение пойманного в отношении последовательности типов?

+1

На самом деле существует довольно много реализаций повторной попытки с задержкой. Один из них - https://gist.github.com/Mortimerp9/5430595 –

+1

Вы не можете использовать переменное число идентификаторов типа в методе 'retry'. Это просто не то, как они должны были использоваться. Вероятно, вы застряли в списке поддерживаемых повторных исключений. – cmbaxter

ответ

2

Что вы думаете о замене список исключений с помощью функции, которая знает, какие исключения могут быть возмещены (и которые вы можете построить динамически):

def retry[T, R](times: Int = 3, delay: Int = 1000)(t: T)(block: T => R)(recoverable: Throwable => Boolean): R = { 

    Try(block(t)) match { 
    case Success(value) => value 
    case Failure(throwable) => if (recoverable(throwable)) retry(times - 1, delay)(t)(block)(recoverable) else throw throwable 
    } 

} 

recoverable функция может выглядеть следующим образом:

def recoverable(throwable: Throwable): Boolean = throwable match { 
    case exc @ (_: IllegalArgumentException | _: IOException) => true 
    case _ => false 
} 
+0

'if (восстанавливаемый (throwable) && times> = 0) ...' в выражении if. – aepurniet

+0

Поэтому для использования структуры повтора необходимо определить восстанавливаемую функцию и привязку к шаблону. случай отл @ (_: IllegalArgumentException | _: IOException) => верно эквивалентно случае возб: IllegalArgumentException => верно случае возб: IOException => верно и два исключения должны быть статически закодированный в восстанавливаемой функции , Это не упрощает код. С определением класса varargs я могу создать список исключений для повторения во время выполнения: val extractable: Seq [Класс [_ <: Исключение]] = вычислить и повторить вызов с retry() (восстанавливается) ("abc") {x => d (x)} – sabz

+0

Вы правы, вам нужно их жестко закодировать, но разве вы не будете делать то же самое с «списком»?Я имею в виду, что вы создадите вне функции «повторить» список с предопределенными исключениями, и таким же образом вы будете динамически строить функцию с этими исключениями. Поэтому идея состоит в том, чтобы сделать этот список настраиваемым вне «повтора», что вы можете сделать с обоими. Как вы думаете? – iuriisusuk

Смежные вопросы