cache user teams

This commit is contained in:
Thibault Duplessis 2012-12-13 17:56:22 +01:00
parent 271c2bfa20
commit 81f7faaa3a
5 changed files with 58 additions and 30 deletions

View file

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

View file

@ -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]]()
}
}

View file

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

View file

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

View file

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