cache user teams
This commit is contained in:
parent
271c2bfa20
commit
81f7faaa3a
|
@ -11,7 +11,7 @@ trait ForumGranter {
|
|||
private val StaffSlug = "staff"
|
||||
|
||||
// teamId userId
|
||||
protected def userBelongsToTeam: (String, String) ⇒ IO[Boolean]
|
||||
protected def userBelongsToTeam: (String, String) ⇒ Boolean
|
||||
|
||||
def isGrantedRead(categSlug: String)(implicit ctx: Context): Boolean =
|
||||
(categSlug == StaffSlug).fold(
|
||||
|
@ -21,7 +21,7 @@ trait ForumGranter {
|
|||
|
||||
def isGrantedWrite(categSlug: String)(implicit ctx: Context): Boolean = categSlug match {
|
||||
case StaffSlug ⇒ ctx.me exists { u ⇒ Granter(Permission.StaffForum)(u) }
|
||||
case TeamSlugPattern(teamId) ⇒ ctx.me.fold(me ⇒ userBelongsToTeam(teamId, me.id).unsafePerformIO, false)
|
||||
case TeamSlugPattern(teamId) ⇒ ctx.me.fold(me ⇒ userBelongsToTeam(teamId, me.id), false)
|
||||
case _ ⇒ true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,14 +3,35 @@ package team
|
|||
|
||||
import scala.collection.mutable
|
||||
|
||||
final class Cached(teamRepo: TeamRepo) {
|
||||
final class Cached(
|
||||
teamRepo: TeamRepo,
|
||||
memberRepo: MemberRepo) {
|
||||
|
||||
def name(id: String): Option[String] =
|
||||
nameCache.getOrElseUpdate(
|
||||
id.toLowerCase,
|
||||
(teamRepo name id).unsafePerformIO
|
||||
def name(id: String): Option[String] = NameCache(id)
|
||||
|
||||
def teamIds(userId: String): List[String] = TeamIdsCache(userId.pp).pp
|
||||
|
||||
def invalidateTeamIds(userId: String) { TeamIdsCache invalidate userId }
|
||||
|
||||
private object NameCache {
|
||||
|
||||
def apply(id: String): Option[String] = cache.getOrElseUpdate(id,
|
||||
(teamRepo name id).unsafePerformIO
|
||||
)
|
||||
|
||||
// id => name
|
||||
private val nameCache = mutable.Map[String, Option[String]]()
|
||||
// id => name
|
||||
private val cache = mutable.Map[String, Option[String]]()
|
||||
}
|
||||
|
||||
private object TeamIdsCache {
|
||||
|
||||
def apply(userId: String): List[String] = cache.getOrElseUpdate(userId,
|
||||
(memberRepo teamIdsByUserId userId).unsafePerformIO
|
||||
)
|
||||
|
||||
def invalidate(userId: String) { cache -= userId }
|
||||
|
||||
// id => name
|
||||
private val cache = mutable.Map[String, List[String]]()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ final class TeamApi(
|
|||
teamRepo: TeamRepo,
|
||||
memberRepo: MemberRepo,
|
||||
requestRepo: RequestRepo,
|
||||
cached: Cached,
|
||||
userRepo: UserRepo,
|
||||
messenger: TeamMessenger,
|
||||
makeForum: (String, String) ⇒ IO[Unit],
|
||||
|
@ -59,7 +60,7 @@ final class TeamApi(
|
|||
|
||||
def join(teamId: String)(implicit ctx: Context): IO[Option[Requesting]] = for {
|
||||
teamOption ← teamRepo byId teamId
|
||||
result ← ~(teamOption |@| ctx.me).tupled.map({
|
||||
result ← ~(teamOption |@| ctx.me)({
|
||||
case (team, user) if team.open ⇒
|
||||
(doJoin(team, user) inject Joined(team).some): IO[Option[Requesting]]
|
||||
case (team, user) ⇒
|
||||
|
@ -72,10 +73,10 @@ final class TeamApi(
|
|||
able ← ~teamOption.map(requestable(_, user))
|
||||
} yield teamOption filter (_ ⇒ able)
|
||||
|
||||
def requestable(team: Team, user: User): IO[Boolean] = for {
|
||||
exists ← requestRepo.exists(team.id, user.id)
|
||||
mine ← belongsTo(team.id, user.id)
|
||||
} yield !exists && !mine
|
||||
def requestable(team: Team, user: User): IO[Boolean] =
|
||||
requestRepo.exists(team.id, user.id) map { exists ⇒
|
||||
!exists && !belongsTo(team.id, user.id)
|
||||
}
|
||||
|
||||
def createRequest(team: Team, setup: RequestSetup, user: User): IO[Unit] = for {
|
||||
able ← requestable(team, user)
|
||||
|
@ -93,24 +94,26 @@ final class TeamApi(
|
|||
))
|
||||
} yield ()
|
||||
|
||||
def doJoin(team: Team, user: User): IO[Unit] = for {
|
||||
exists ← belongsTo(team.id, user.id)
|
||||
_ ← (memberRepo.add(team.id, user.id) >> teamRepo.incMembers(team.id, +1)) doUnless exists
|
||||
} yield ()
|
||||
def doJoin(team: Team, user: User): IO[Unit] = {
|
||||
memberRepo.add(team.id, user.id) >>
|
||||
teamRepo.incMembers(team.id, +1) >>
|
||||
io(cached invalidateTeamIds user.id)
|
||||
} doUnless belongsTo(team.id, user.id)
|
||||
|
||||
def quit(teamId: String)(implicit ctx: Context): IO[Option[Team]] = for {
|
||||
teamOption ← teamRepo byId teamId
|
||||
result ← ~(teamOption |@| ctx.me).tupled.map({
|
||||
case (team, user) ⇒ for {
|
||||
exists ← belongsTo(team.id, user.id)
|
||||
_ ← (for {
|
||||
_ ← memberRepo.remove(team.id, user.id)
|
||||
_ ← teamRepo.incMembers(team.id, -1)
|
||||
} yield ()) doIf exists
|
||||
} yield team.some
|
||||
result ← ~(teamOption |@| ctx.me)({
|
||||
case (team, user) ⇒ doQuit(team, user) inject team.some
|
||||
})
|
||||
} yield result
|
||||
|
||||
def belongsTo(teamId: String, userId: String): IO[Boolean] =
|
||||
memberRepo.exists(teamId = teamId, userId = userId)
|
||||
def doQuit(team: Team, user: User): IO[Unit] = {
|
||||
memberRepo.remove(team.id, user.id) >>
|
||||
teamRepo.incMembers(team.id, -1) >>
|
||||
io(cached invalidateTeamIds user.id)
|
||||
} doIf belongsTo(team.id, user.id)
|
||||
|
||||
def teamIds = cached.teamIds _
|
||||
|
||||
def belongsTo(teamId: String, userId: String): Boolean = teamIds(userId) contains teamId
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ final class TeamEnv(
|
|||
teamRepo = teamRepo,
|
||||
memberRepo = memberRepo,
|
||||
requestRepo = requestRepo,
|
||||
cached = cached,
|
||||
userRepo = userRepo,
|
||||
messenger = messenger,
|
||||
makeForum = makeForum,
|
||||
|
@ -57,5 +58,5 @@ final class TeamEnv(
|
|||
|
||||
lazy val forms = new DataForm(teamRepo, captcha)
|
||||
|
||||
lazy val cached = new Cached(teamRepo)
|
||||
lazy val cached = new Cached(teamRepo, memberRepo)
|
||||
}
|
||||
|
|
|
@ -30,7 +30,10 @@ object TeamInfo {
|
|||
userRepo: UserRepo,
|
||||
getForumNbPosts: String ⇒ IO[Int],
|
||||
getForumPosts: String ⇒ IO[List[PostView]])(team: Team, me: Option[User]): IO[TeamInfo] = for {
|
||||
mine ← ~me.map(m ⇒ api.belongsTo(team.id, m.id))
|
||||
requests ← api.requestsWithUsers(team) doIf {
|
||||
team.enabled && ~me.map(m ⇒ team.isCreator(m.id))
|
||||
}
|
||||
mine = ~me.map(m ⇒ api.belongsTo(team.id, m.id))
|
||||
requestedByMe ← ~me.map(m ⇒ requestRepo.exists(team.id, m.id)) doUnless mine
|
||||
requests ← api.requestsWithUsers(team) doIf {
|
||||
team.enabled && ~me.map(m ⇒ team.isCreator(m.id))
|
||||
|
|
Loading…
Reference in a new issue