less mongodb queries to show recent forum posts

This commit is contained in:
Thibault Duplessis 2012-12-17 22:13:44 +01:00
parent b0c62ca1d7
commit 5ab8145387
10 changed files with 40 additions and 27 deletions

View file

@ -30,6 +30,7 @@ final class ForumEnv(
lazy val postApi = new PostApi(this, modLog, ForumPostMaxPerPage)
lazy val recent = new Recent(
categRepo = categRepo,
postRepo = postRepo,
postApi = postApi,
timeout = ForumRecentTimeout)

View file

@ -69,6 +69,15 @@ final class PostApi(
def view(post: Post): IO[Option[PostView]] = views(List(post)) map (_.headOption)
def liteViews(posts: List[Post]): IO[List[PostLiteView]] = for {
topics env.topicRepo byIds posts.map(_.topicId).distinct
} yield (for {
post posts
} yield for {
topic topics find (_.id == post.topicId)
} yield PostLiteView(post, topic, lastPageOf(topic))
).flatten
def lastNumberOf(topic: Topic): IO[Int] =
env.postRepo lastByTopics List(topic) map (_.number)

View file

@ -7,7 +7,11 @@ import security.{ Permission, Granter }
import scalaz.effects._
final class Recent(postRepo: PostRepo, postApi: PostApi, timeout: Int) {
final class Recent(
categRepo: CategRepo,
postRepo: PostRepo,
postApi: PostApi,
timeout: Int) {
private val nb = 20
@ -15,34 +19,31 @@ final class Recent(postRepo: PostRepo, postApi: PostApi, timeout: Int) {
private val Staff = "$staff"
private def teamSlug(id: String) = "team-" + id
private lazy val publicCategIds = List(
"game-analysis",
"general-chess-discussion",
"lichess-feedback",
"off-topic-discussion")
private lazy val publicCategIds =
categRepo.withTeams(Nil).unsafePerformIO.map(_.slug) filterNot ("staff" ==)
private lazy val staffCategIds = "staff" :: publicCategIds
private val cache = Builder.cache[String, List[PostView]](timeout, key
private val cache = Builder.cache[String, List[PostLiteView]](timeout, key
fetch(key).unsafePerformIO
)
def apply(user: Option[User]): IO[List[PostView]] = io {
def apply(user: Option[User]): IO[List[PostLiteView]] = io {
cache get Granter.option(Permission.StaffForum)(user).fold(Staff, Public)
}
def team(teamId: String): IO[List[PostView]] = io {
def team(teamId: String): IO[List[PostLiteView]] = io {
cache get teamId
}
val invalidate: IO[Unit] = io(cache.invalidateAll)
private def fetch(key: String): IO[List[PostView]] = for {
private def fetch(key: String): IO[List[PostLiteView]] = for {
posts postRepo.recentInCategs(nb)(key match {
case Public publicCategIds
case Staff staffCategIds
case teamId List(teamSlug(teamId))
})
views postApi views posts
views postApi liteViews posts
} yield views
}

View file

@ -27,7 +27,9 @@ case class TopicView(
}
case class PostView(
post: Post,
topic: Topic,
categ: Categ,
topicLastPage: Int)
post: Post,
topic: Topic,
categ: Categ,
topicLastPage: Int)
case class PostLiteView(post: Post, topic: Topic, topicLastPage: Int)

View file

@ -3,7 +3,7 @@ package lobby
import timeline.Entry
import game.{ DbGame, Featured }
import forum.PostView
import forum.PostLiteView
import controllers.routes
import socket.History
import tournament.Created
@ -26,7 +26,7 @@ final class Preload(
private implicit val executor = Akka.system.dispatcher
private implicit val timeout = Timeout(1 second)
private type RightResponse = (Map[String, Any], List[PostView], List[Created], Option[DbGame])
private type RightResponse = (Map[String, Any], List[PostLiteView], List[Created], Option[DbGame])
private type Response = Either[Call, RightResponse]
def apply(
@ -34,7 +34,7 @@ final class Preload(
chat: Boolean,
myHook: Option[Hook],
timeline: IO[List[Entry]],
posts: IO[List[PostView]],
posts: IO[List[PostLiteView]],
tours: IO[List[Created]]): Future[Response] =
myHook.flatMap(_.gameId).fold(
gameId futureGame(gameId) map { gameOption

View file

@ -5,7 +5,7 @@ import core.Settings
import site.Captcha
import user.UserRepo
import message.LichessThread
import forum.{ Categ, PostView }
import forum.{ Categ, PostLiteView }
import com.mongodb.casbah.MongoCollection
import scalaz.effects._
@ -17,7 +17,7 @@ final class TeamEnv(
sendMessage: LichessThread IO[Unit],
makeForum: (String, String) IO[Unit],
getForumNbPosts: String IO[Int],
getForumPosts: String IO[List[PostView]],
getForumPosts: String IO[List[PostLiteView]],
mongodb: String MongoCollection) {
import settings._

View file

@ -3,7 +3,7 @@ package team
import user.{ User, UserRepo }
import game.{ GameRepo, DbGame }
import forum.PostView
import forum.PostLiteView
import http.Context
import scalaz.effects._
@ -16,7 +16,7 @@ case class TeamInfo(
bestPlayers: List[User],
averageElo: Int,
forumNbPosts: Int,
forumPosts: List[PostView]) {
forumPosts: List[PostLiteView]) {
def hasRequests = requests.nonEmpty
}
@ -29,7 +29,7 @@ object TeamInfo {
requestRepo: RequestRepo,
userRepo: UserRepo,
getForumNbPosts: String IO[Int],
getForumPosts: String IO[List[PostView]])(team: Team, me: Option[User]): IO[TeamInfo] = for {
getForumPosts: String IO[List[PostLiteView]])(team: Team, me: Option[User]): IO[TeamInfo] = for {
requests api.requestsWithUsers(team) doIf {
team.enabled && ~me.map(m team.isCreator(m.id))
}

View file

@ -1,6 +1,6 @@
@(posts: List[lila.forum.PostView])(implicit ctx: Context)
@(posts: List[lila.forum.PostLiteView])(implicit ctx: Context)
@posts.reverse.map { v =>
@defining(routes.ForumTopic.show(v.categ.slug, v.topic.slug, v.topicLastPage) + "#" + v.post.number) { postUrl =>
@defining(routes.ForumTopic.show(v.topic.categId, v.topic.slug, v.topicLastPage) + "#" + v.post.number) { postUrl =>
<li>
<a class="post_link" href="@postUrl">@v.topic.name</a>
<span>@authorLink(v.post, withOnline = false)</span>

View file

@ -1,4 +1,4 @@
@(preload: String, myHook: Option[lila.lobby.Hook], forumRecent: List[lila.forum.PostView], tours: List[lila.tournament.Created], featured: Option[DbGame])(implicit ctx: Context)
@(preload: String, myHook: Option[lila.lobby.Hook], forumRecent: List[lila.forum.PostLiteView], tours: List[lila.tournament.Created], featured: Option[DbGame])(implicit ctx: Context)
@chat = {
@for(m <- ctx.me; if m.canChat) {

View file

@ -45,7 +45,7 @@
<h2><a href="@teamForumUrl(t.id)">@trans.forum() (@info.forumNbPosts)</a></h2>
<ol class="posts">
@info.forumPosts.take(5).map { v =>
@defining(routes.ForumTopic.show(v.categ.slug, v.topic.slug, v.topicLastPage) + "#" + v.post.number) { postUrl =>
@defining(routes.ForumTopic.show(v.topic.categId, v.topic.slug, v.topicLastPage) + "#" + v.post.number) { postUrl =>
<li>
<p class="meta clearfix">
<a href="@postUrl">@v.topic.name</a>