diff --git a/modules/db/src/main/package.scala b/modules/db/src/main/package.scala index da2efbfade..81874024c5 100644 --- a/modules/db/src/main/package.scala +++ b/modules/db/src/main/package.scala @@ -8,4 +8,12 @@ package object db extends PackageObject with WithPlay { type JsTubeInColl[A] = JsTube[A] with InColl[A] type BsTubeInColl[A] = BsTube[A] with InColl[A] + + private val duplicateKeyMessage = "duplicate key error" + + import reactivemongo.api.commands.WriteResult + + def recoverDuplicateKey[A](f: WriteResult => A): PartialFunction[Throwable, A] = { + case e: WriteResult if e.getMessage.contains(duplicateKeyMessage) => f(e) + } } diff --git a/modules/donation/src/main/DonationApi.scala b/modules/donation/src/main/DonationApi.scala index 5d19503031..88fa5468ce 100644 --- a/modules/donation/src/main/DonationApi.scala +++ b/modules/donation/src/main/DonationApi.scala @@ -24,10 +24,8 @@ final class DonationApi(coll: Coll, monthlyGoal: Int) { )).cursor[Donation]() .collect[List](nb) - def create(donation: Donation) = coll insert donation recover { - case e: reactivemongo.core.commands.LastError if e.getMessage.contains("duplicate key error") => - println(e.getMessage) - } void + def create(donation: Donation) = coll insert donation recover + lila.db.recoverDuplicateKey(e => println(e.getMessage)) void // in $ cents def donatedByUser(userId: String): Fu[Int] = diff --git a/modules/game/src/main/CrosstableApi.scala b/modules/game/src/main/CrosstableApi.scala index 46fce2d72a..8568fcd9c4 100644 --- a/modules/game/src/main/CrosstableApi.scala +++ b/modules/game/src/main/CrosstableApi.scala @@ -21,17 +21,16 @@ final class CrosstableApi(coll: Coll) { } def apply(u1: String, u2: String): Fu[Option[Crosstable]] = - coll.find(select(u1, u2)).one[Crosstable] orElse create(u1, u2) recover { - case e: reactivemongo.core.commands.LastError if e.getMessage.contains("duplicate key error") => none - } + coll.find(select(u1, u2)).one[Crosstable] orElse create(u1, u2) recoverWith + lila.db.recoverDuplicateKey(_ => coll.find(select(u1, u2)).one[Crosstable]) def nbGames(u1: String, u2: String): Fu[Int] = coll.find( select(u1, u2), BSONDocument("n" -> true) ).one[BSONDocument] map { - ~_.flatMap(_.getAs[Int]("n")) - } + ~_.flatMap(_.getAs[Int]("n")) + } def add(game: Game): Funit = game.userIds.distinct.sorted match { case List(u1, u2) => diff --git a/modules/memo/src/main/MongoCache.scala b/modules/memo/src/main/MongoCache.scala index df7d4516ec..fac348308e 100644 --- a/modules/memo/src/main/MongoCache.scala +++ b/modules/memo/src/main/MongoCache.scala @@ -20,9 +20,8 @@ final class MongoCache[K, V: MongoCache.Handler] private ( def apply(k: K): Fu[V] = cache(k) { coll.find(select(k)).one[Entry] flatMap { case None => f(k) flatMap { v => - coll.insert(makeEntry(k, v)) recover { - case e: reactivemongo.core.commands.LastError if e.getMessage.contains("duplicate key error") => () - } inject v + coll.insert(makeEntry(k, v)) recover + lila.db.recoverDuplicateKey(_ => ()) inject v } case Some(entry) => fuccess(entry.v) } diff --git a/modules/opening/src/main/Finisher.scala b/modules/opening/src/main/Finisher.scala index dc2233ba6c..6595488ad2 100644 --- a/modules/opening/src/main/Finisher.scala +++ b/modules/opening/src/main/Finisher.scala @@ -41,9 +41,7 @@ private[opening] final class Finisher( )) ++ BSONDocument("$set" -> BSONDocument( Opening.BSONFields.perf -> Perf.perfBSONHandler.write(openingPerf) ))) zip UserRepo.setPerf(user.id, "opening", userPerf) - }) recover { - case e: reactivemongo.core.commands.LastError if e.getMessage.contains("duplicate key error") => () - } inject (a -> none) + }) recover lila.db.recoverDuplicateKey(_ => ()) inject (a -> none) } } diff --git a/modules/puzzle/src/main/Finisher.scala b/modules/puzzle/src/main/Finisher.scala index 875af37b63..dc88bb23d7 100644 --- a/modules/puzzle/src/main/Finisher.scala +++ b/modules/puzzle/src/main/Finisher.scala @@ -45,9 +45,7 @@ private[puzzle] final class Finisher( )) ++ BSONDocument("$set" -> BSONDocument( Puzzle.BSONFields.perf -> Perf.perfBSONHandler.write(puzzlePerf) ))) zip UserRepo.setPerf(user.id, "puzzle", userPerf) - }) recover { - case e: reactivemongo.core.commands.LastError if e.getMessage.contains("duplicate key error") => () - } inject (a -> none) + }) recover lila.db.recoverDuplicateKey(_ => ()) inject (a -> none) } private val VOLATILITY = Glicko.default.volatility diff --git a/modules/team/src/main/TeamApi.scala b/modules/team/src/main/TeamApi.scala index 55bac307d8..35dba26c27 100644 --- a/modules/team/src/main/TeamApi.scala +++ b/modules/team/src/main/TeamApi.scala @@ -120,9 +120,7 @@ final class TeamApi( ).toFollowersOf(userId).toUsers(previousMembers)) } } - } recover { - case e: reactivemongo.core.commands.LastError if e.getMessage.contains("duplicate key error") => - } + } recover lila.db.recoverDuplicateKey(e => ()) def quit(teamId: String)(implicit ctx: UserContext): Fu[Option[Team]] = for { teamOption ← $find.byId[Team](teamId) diff --git a/modules/video/src/main/VideoApi.scala b/modules/video/src/main/VideoApi.scala index cb44a6d91b..bed23b9ff4 100644 --- a/modules/video/src/main/VideoApi.scala +++ b/modules/video/src/main/VideoApi.scala @@ -152,9 +152,8 @@ private[video] final class VideoApi( View.BSONFields.id -> View.makeId(videoId, userId) )).one[View] - def add(a: View) = (viewColl insert a).void recover { - case e: reactivemongo.core.commands.LastError if e.getMessage.contains("duplicate key error") => () - } + def add(a: View) = (viewColl insert a).void recover + lila.db.recoverDuplicateKey(_ => ()) def hasSeen(user: User, video: Video): Fu[Boolean] = viewColl.count(BSONDocument(