diff --git a/modules/clas/src/main/Env.scala b/modules/clas/src/main/Env.scala index e7d17fd36044..95b01b72f7be 100644 --- a/modules/clas/src/main/Env.scala +++ b/modules/clas/src/main/Env.scala @@ -3,6 +3,7 @@ package lila.clas import com.softwaremill.macwire.* import lila.core.config.* +import lila.core.misc.clas.ClasBus @Module final class Env( @@ -40,17 +41,16 @@ final class Env( def hasClas(using me: Me) = lila.core.perm.Granter(_.Teacher) || studentCache.isStudent(me) - lila.common.Bus.subscribeFuns( - "finishGame" -> { case lila.core.game.FinishGame(game, _) => progressApi.onFinishGame(game) }, - "clas" -> { - case lila.core.misc.clas.IsTeacherOf(teacher, student, promise) => - promise.completeWith(api.clas.isTeacherOf(teacher, student)) - case lila.core.misc.clas.AreKidsInSameClass(kid1, kid2, promise) => - promise.completeWith(api.clas.areKidsInSameClass(kid1, kid2)) - case lila.core.misc.clas.ClasMatesAndTeachers(kid, promise) => - promise.completeWith(matesCache.get(kid.id)) - } - ) + lila.common.Bus.subscribeFun("finishGame"): + case lila.core.game.FinishGame(game, _) => progressApi.onFinishGame(game) + + lila.common.Bus.sub[ClasBus]: + case ClasBus.IsTeacherOf(teacher, student, promise) => + promise.completeWith(api.clas.isTeacherOf(teacher, student)) + case ClasBus.AreKidsInSameClass(kid1, kid2, promise) => + promise.completeWith(api.clas.areKidsInSameClass(kid1, kid2)) + case ClasBus.ClasMatesAndTeachers(kid, promise) => + promise.completeWith(matesCache.get(kid.id)) private class ClasColls(db: lila.db.Db): val clas = db(CollName("clas_clas")) diff --git a/modules/common/src/main/Bus.scala b/modules/common/src/main/Bus.scala index 426c486a9df3..775cc22699d2 100644 --- a/modules/common/src/main/Bus.scala +++ b/modules/common/src/main/Bus.scala @@ -80,6 +80,19 @@ object Bus: .withTimeout(timeout, s"Bus.ask $channel $msg") .monSuccess(_.bus.ask(s"${channel}_${msg.getClass}")) + def safeAsk[A, T <: Payload](makeMsg: Promise[A] => T, timeout: FiniteDuration = 2.second)(using + wc: WithChannel[T], + e: Executor, + s: Scheduler + ): Fu[A] = + val promise = Promise[A]() + val channel = wc.channel + val msg = makeMsg(promise) + pub(msg) + promise.future + .withTimeout(timeout, s"Bus.safeAsk $channel $msg") + .monSuccess(_.bus.ask(s"${channel}_${msg.getClass}")) + private val bus = EventBus[Payload, Channel, Tellable]( initialCapacity = 4096, publish = (tellable, event) => tellable ! event diff --git a/modules/core/src/main/misc.scala b/modules/core/src/main/misc.scala index dad0fd269e29..504558285aa1 100644 --- a/modules/core/src/main/misc.scala +++ b/modules/core/src/main/misc.scala @@ -19,9 +19,12 @@ package map: case class Exists(id: String, promise: Promise[Boolean]) package clas: - case class AreKidsInSameClass(kid1: UserId, kid2: UserId, promise: Promise[Boolean]) - case class IsTeacherOf(teacher: UserId, student: UserId, promise: Promise[Boolean]) - case class ClasMatesAndTeachers(kid: UserId, promise: Promise[Set[UserId]]) + enum ClasBus: + case AreKidsInSameClass(kid1: UserId, kid2: UserId, promise: Promise[Boolean]) + case IsTeacherOf(teacher: UserId, student: UserId, promise: Promise[Boolean]) + case ClasMatesAndTeachers(kid: UserId, promise: Promise[Set[UserId]]) + object ClasBus: + given bus.WithChannel[ClasBus] = bus.WithChannel[ClasBus]("clas") package puzzle: case class StormRun(userId: UserId, score: Int) diff --git a/modules/msg/src/main/MsgSearch.scala b/modules/msg/src/main/MsgSearch.scala index e8051a6220d6..8d1b01338330 100644 --- a/modules/msg/src/main/MsgSearch.scala +++ b/modules/msg/src/main/MsgSearch.scala @@ -5,7 +5,7 @@ import reactivemongo.api.bson.* import lila.common.Bus import lila.core.LightUser import lila.db.dsl.{ *, given } -import lila.core.misc.clas.ClasMatesAndTeachers +import lila.core.misc.clas.ClasBus import lila.core.user.KidMode import lila.core.userId.UserSearch @@ -35,7 +35,7 @@ final class MsgSearch( private def forKid(q: String)(using me: Me): Fu[MsgSearch.Result] = for threads <- searchThreads(q) - allMates <- Bus.ask[Set[UserId]]("clas") { ClasMatesAndTeachers(me, _) } + allMates <- Bus.safeAsk[Set[UserId], ClasBus] { ClasBus.ClasMatesAndTeachers(me, _) } lower = q.toLowerCase mateIds = allMates.view.filter(_.value.startsWith(lower)).toList.take(15) mates <- lightUserApi.asyncMany(mateIds) diff --git a/modules/msg/src/main/MsgSecurity.scala b/modules/msg/src/main/MsgSecurity.scala index e28ee1a2ff6b..2bd88be35612 100644 --- a/modules/msg/src/main/MsgSecurity.scala +++ b/modules/msg/src/main/MsgSecurity.scala @@ -2,7 +2,7 @@ package lila.msg import lila.common.Bus import lila.db.dsl.{ *, given } -import lila.core.misc.clas.{ AreKidsInSameClass, IsTeacherOf } +import lila.core.misc.clas.ClasBus import lila.core.team.IsLeaderOf import lila.memo.RateLimit import lila.core.perm.Granter @@ -175,7 +175,8 @@ final private class MsgSecurity( if !isNew || !hasKid then fuTrue else (orig.isKid, dest.isKid) match - case (true, true) => Bus.ask[Boolean]("clas") { AreKidsInSameClass(orig.id, dest.id, _) } + case (true, true) => + Bus.safeAsk[Boolean, ClasBus] { ClasBus.AreKidsInSameClass(orig.id, dest.id, _) } case (false, true) => isTeacherOf(orig.id, dest.id) case (true, false) => isTeacherOf(dest.id, orig.id) case _ => fuFalse @@ -184,7 +185,7 @@ final private class MsgSecurity( isTeacherOf(contacts.orig.id, contacts.dest.id) private def isTeacherOf(teacher: UserId, student: UserId): Fu[Boolean] = - Bus.ask[Boolean]("clas") { IsTeacherOf(teacher, student, _) } + Bus.safeAsk[Boolean, ClasBus] { ClasBus.IsTeacherOf(teacher, student, _) } private def isLeaderOf(contacts: Contacts) = Bus.ask[Boolean]("teamIsLeaderOf") { IsLeaderOf(contacts.orig.id, contacts.dest.id, _) }