2016-10-18 15 views
2

でみてくださいでラップ:が、私は将来を返すレポメソッドを持っているのScala

def insert(newUser: User): Future[User] 

この方法では、様々な理由で失敗することができ、しかし、私はこれらの理由の1をキャッチできるようにしたいです他の人を転覆させる。 私は単に結果として試してみてください

Try(userRepository.insert(usr)) match { 
     case Success(newUserFuture) => newUserFuture 

     case Failure(e) if e.getCause.getMessage.contains("duplicate key") => { 
     logger.warn(e.getMessage) 
     throw DuplicateEntityException("duplicate user record") 
     } 

     case Failure(e) => { 
     logger.error(e.getMessage) 
     throw e 
     } 
    } 

とのコールをラップしていた場合、私はTry[Future[User]]を取得していますが、この状況では、どちらの障害の未来が正常に作成されて以来、発生します。 この時点で、私はそれに対処する方法がわかりません。理想的には、Future[Either[String, User]](またはそれに類するもの)を手に入れたいです。

この状況にどう対処すればよいですか、まったく間違った方向に向いていますか?

EDIT以下の推奨 このような解決策 私が試した何か:私はあなたのコードをクリーンアップあなたのアプローチを逆にし、ケースにはガードを使用することができると思う

userRepository.insert(usr).map(newUser => Right(newUser)) recoverWith { 
     case e: PSQLException if e.getMessage.contains("duplicate key") => 
     Future.successful(Left("duplicate user record")) 
    } 

答えて

4

Futureが例外を処理します。将来のコードをTryで囲む必要はありません。

FutureTryのジョブも同様です。

このコード行は必要ありません

Try(userRepository.insert(usr)) 

私はあなたの挿入方法は、上記の方法では、この

def insert(newUser: User): Future[User] = Future { doSomeDBCall() } 

のようなものであると思います。 doSomeDBCall()が失敗した場合。この例外は将来安全にキャッチされ、Failure(exception)という発信者に配信されます。したがって、FutureTry

で捕捉する必要はありません。特定の例外をキャッチし、他の例外をスローする(他のものを伝播する)必要はありません。あなたはrecoverWithを使用して例外を処理し、あなたに興味を持っていない例外を伝播させることができます。

以下のコードSQLException

が処理され、他の例外は、呼び出し側に伝播されます。

userRepository.insert(usr).recoverWith { 
case ex: SQLException => Future.successful(defaultValue) 
case ex => Future.failed(ex) 
} 
+0

私はあなたが何を意味するか分かりません –

+0

@ShurikAgulyanskyは説明を追加しました – pamu

+0

私は例外を1種類だけ捕まえることができるように未来をアンラップする方法はありますか? –

1

少し。まず、userRepository.insert(usr)にはFuture[Try[User]]が返されます。

userRepository.insert(user).map { 
    case Success(insertedUser) => Right(insertedUser) 
    case Failure(ex) if ex.getCause.getMessage.contains("duplicate key") => throw DuplicateEntityException("duplicate user record") 
    case Failure(ex) => throw ex 
} 

この結果は、ユーザーまたは契約で他に何かをするか(http://docs.scala-lang.org/overviews/core/futures.htmlを参照)へのコールバックを添付することができますFuture[User]次のようになります。そして、このように使用することができます

def insert(user: User): Future[Try[User]] 

例外はある。

+0

をチェックするため

def futureToFutureTry[T](f: Future[T]): Future[Try[T]] = f.map(Success(_)).recover { case e: Throwable => { Failure(e) } } ... userRepository.insert(usr) map futureToFutureTry 

を、 'insert'方法は、私のコントロールの外にあります。そうでなければ、私はそれを正確に行うでしょう。 –

0

はそのような何かしてみてください:残念ながら

def checkOperations[A](operations: List[Try[A]]): Future[List[A]] = { 
    Future { 
     if (!operations.filter(_.isFailure).isEmpty) { 
     // there were some error 

     } else { 
     // all operations are ok 
    } 
} 
+0

私がポストで提供した解決策は、私が期待した通りに正確に機能しました。 –

関連する問題