rewrite forum DB code
This commit is contained in:
parent
d11f0acaff
commit
1b0628c168
|
@ -19,17 +19,7 @@ abstract class BSON[T]
|
|||
def write(obj: T): BSONDocument = writes(writer, obj)
|
||||
}
|
||||
|
||||
object BSON {
|
||||
|
||||
implicit object BSONJodaDateTimeHandler extends BSONHandler[BSONDateTime, DateTime] {
|
||||
def read(x: BSONDateTime) = new DateTime(x.value)
|
||||
def write(x: DateTime) = BSONDateTime(x.getMillis)
|
||||
}
|
||||
|
||||
def stringAnyValHandler[A](from: A => String, to: String => A) = new BSONHandler[BSONString, A] {
|
||||
def read(x: BSONString) = to(x.value)
|
||||
def write(x: A) = BSONString(from(x))
|
||||
}
|
||||
object BSON extends Handlers {
|
||||
|
||||
object MapDocument {
|
||||
|
||||
|
@ -88,24 +78,6 @@ object BSON {
|
|||
}
|
||||
}
|
||||
|
||||
private def readStream[T](array: BSONArray, reader: BSONReader[BSONValue, T]): Stream[T] = {
|
||||
array.stream.filter(_.isSuccess).map { v =>
|
||||
reader.read(v.get)
|
||||
}
|
||||
}
|
||||
|
||||
implicit def bsonArrayToListHandler[T](implicit reader: BSONReader[_ <: BSONValue, T], writer: BSONWriter[T, _ <: BSONValue]): BSONHandler[BSONArray, List[T]] = new BSONHandler[BSONArray, List[T]] {
|
||||
def read(array: BSONArray) = readStream(array, reader.asInstanceOf[BSONReader[BSONValue, T]]).toList
|
||||
def write(repr: List[T]) =
|
||||
new BSONArray(repr.map(s => scala.util.Try(writer.write(s))).to[Stream])
|
||||
}
|
||||
|
||||
implicit def bsonArrayToVectorHandler[T](implicit reader: BSONReader[_ <: BSONValue, T], writer: BSONWriter[T, _ <: BSONValue]): BSONHandler[BSONArray, Vector[T]] = new BSONHandler[BSONArray, Vector[T]] {
|
||||
def read(array: BSONArray) = readStream(array, reader.asInstanceOf[BSONReader[BSONValue, T]]).toVector
|
||||
def write(repr: Vector[T]) =
|
||||
new BSONArray(repr.map(s => scala.util.Try(writer.write(s))).to[Stream])
|
||||
}
|
||||
|
||||
final class Reader(val doc: BSONDocument) {
|
||||
|
||||
val map = {
|
||||
|
|
37
modules/db/src/main/Handlers.scala
Normal file
37
modules/db/src/main/Handlers.scala
Normal file
|
@ -0,0 +1,37 @@
|
|||
package lila.db
|
||||
|
||||
import dsl._
|
||||
|
||||
import org.joda.time.DateTime
|
||||
import reactivemongo.bson._
|
||||
|
||||
trait Handlers {
|
||||
|
||||
implicit object BSONJodaDateTimeHandler extends BSONHandler[BSONDateTime, DateTime] {
|
||||
def read(x: BSONDateTime) = new DateTime(x.value)
|
||||
def write(x: DateTime) = BSONDateTime(x.getMillis)
|
||||
}
|
||||
|
||||
def stringAnyValHandler[A](from: A => String, to: String => A) = new BSONHandler[BSONString, A] {
|
||||
def read(x: BSONString) = to(x.value)
|
||||
def write(x: A) = BSONString(from(x))
|
||||
}
|
||||
|
||||
implicit def bsonArrayToListHandler[T](implicit reader: BSONReader[_ <: BSONValue, T], writer: BSONWriter[T, _ <: BSONValue]): BSONHandler[BSONArray, List[T]] = new BSONHandler[BSONArray, List[T]] {
|
||||
def read(array: BSONArray) = readStream(array, reader.asInstanceOf[BSONReader[BSONValue, T]]).toList
|
||||
def write(repr: List[T]) =
|
||||
new BSONArray(repr.map(s => scala.util.Try(writer.write(s))).to[Stream])
|
||||
}
|
||||
|
||||
implicit def bsonArrayToVectorHandler[T](implicit reader: BSONReader[_ <: BSONValue, T], writer: BSONWriter[T, _ <: BSONValue]): BSONHandler[BSONArray, Vector[T]] = new BSONHandler[BSONArray, Vector[T]] {
|
||||
def read(array: BSONArray) = readStream(array, reader.asInstanceOf[BSONReader[BSONValue, T]]).toVector
|
||||
def write(repr: Vector[T]) =
|
||||
new BSONArray(repr.map(s => scala.util.Try(writer.write(s))).to[Stream])
|
||||
}
|
||||
|
||||
private def readStream[T](array: BSONArray, reader: BSONReader[BSONValue, T]): Stream[T] = {
|
||||
array.stream.filter(_.isSuccess).map { v =>
|
||||
reader.read(v.get)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -375,4 +375,4 @@ trait dsl {
|
|||
|
||||
}
|
||||
|
||||
object dsl extends dsl with CollExt with QueryBuilderExt
|
||||
object dsl extends dsl with CollExt with QueryBuilderExt with Handlers
|
||||
|
|
|
@ -84,8 +84,4 @@ private[forum] final class CategApi(env: Env) {
|
|||
lastPostIdTroll = lastPostTroll ?? (_.id)
|
||||
)).void
|
||||
} yield ()
|
||||
|
||||
def denormalize: Funit = env.categColl.list[Categ]($empty) flatMap { categs =>
|
||||
categs.map(denormalize).sequenceFu
|
||||
} void
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ object CategRepo {
|
|||
coll.find($or(
|
||||
"team" $exists false,
|
||||
"team" $in teams
|
||||
)).sort($sort asc "pos").cursor[Categ].collect[List]()
|
||||
)).sort($sort asc "pos").cursor[Categ]().collect[List]()
|
||||
|
||||
def nextPosition: Fu[Int] =
|
||||
coll.primitiveOne[Int]($empty, $sort desc "pos", "pos") map (~_ + 1)
|
||||
|
|
|
@ -54,13 +54,6 @@ final class Env(
|
|||
lazy val forms = new DataForm(hub.actor.captcher)
|
||||
lazy val recent = new Recent(postApi, RecentTtl, RecentNb, PublicCategIds)
|
||||
|
||||
def cli = new lila.common.Cli {
|
||||
def process = {
|
||||
case "forum" :: "denormalize" :: Nil =>
|
||||
topicApi.denormalize >> categApi.denormalize inject "Forum denormalized"
|
||||
}
|
||||
}
|
||||
|
||||
system.actorOf(Props(new Actor {
|
||||
def receive = {
|
||||
case MakeTeam(id, name) => categApi.makeTeam(id, name)
|
||||
|
|
|
@ -60,7 +60,7 @@ sealed abstract class PostRepo(troll: Boolean) {
|
|||
else $doc("lang" $in langs)
|
||||
|
||||
def findDuplicate(post: Post): Fu[Option[Post]] = coll.one($doc(
|
||||
"createdAt" -> $gt(DateTime.now.minusHours(1)),
|
||||
"createdAt" $gt DateTime.now.minusHours(1),
|
||||
"userId" -> ~post.userId,
|
||||
"text" -> post.text
|
||||
))
|
||||
|
|
|
@ -56,7 +56,7 @@ object Topic {
|
|||
name: String,
|
||||
troll: Boolean,
|
||||
featured: Boolean): Topic = Topic(
|
||||
id = Random nextString idSize,
|
||||
_id = Random nextString idSize,
|
||||
categId = categId,
|
||||
slug = slug,
|
||||
name = name,
|
||||
|
|
|
@ -57,9 +57,9 @@ private[forum] final class TopicApi(
|
|||
lang = lang map (_.language),
|
||||
number = 1,
|
||||
categId = categ.id)
|
||||
$insert(post) >>
|
||||
$insert(topic withPost post) >>
|
||||
$update(categ withTopic post) >>-
|
||||
env.postColl.insert(post) >>
|
||||
env.topicColl.insert(topic withPost post) >>
|
||||
env.categColl.update($id(categ.id), categ withTopic post) >>-
|
||||
(indexer ! InsertPost(post)) >>
|
||||
env.recent.invalidate >>-
|
||||
ctx.userId.?? { userId =>
|
||||
|
@ -79,10 +79,12 @@ private[forum] final class TopicApi(
|
|||
|
||||
def paginator(categ: Categ, page: Int, troll: Boolean): Fu[Paginator[TopicView]] = Paginator(
|
||||
adapter = new Adapter[Topic](
|
||||
collection = env.topicColl,
|
||||
selector = TopicRepo(troll) byCategQuery categ,
|
||||
sort = Seq($sort.updatedDesc)
|
||||
projection = $empty,
|
||||
sort = $sort.updatedDesc
|
||||
) mapFuture { topic =>
|
||||
$find.byId[Post](topic lastPostId troll) map { post =>
|
||||
env.postColl.byId[Post](topic lastPostId troll) map { post =>
|
||||
TopicView(categ, topic, post, env.postApi lastPageOf topic, troll)
|
||||
}
|
||||
},
|
||||
|
@ -91,7 +93,7 @@ private[forum] final class TopicApi(
|
|||
|
||||
def delete(categ: Categ, topic: Topic): Funit =
|
||||
PostRepo.idsByTopicId(topic.id) flatMap { postIds =>
|
||||
(PostRepo removeByTopic topic.id zip $remove(topic)) >>
|
||||
(PostRepo removeByTopic topic.id zip env.topicColl.remove($id(topic.id))) >>
|
||||
(env.categApi denormalize categ) >>-
|
||||
(indexer ! RemovePosts(postIds)) >>
|
||||
env.recent.invalidate
|
||||
|
@ -100,33 +102,29 @@ private[forum] final class TopicApi(
|
|||
def toggleClose(categ: Categ, topic: Topic, mod: User): Funit =
|
||||
TopicRepo.close(topic.id, topic.open) >> {
|
||||
MasterGranter(_.ModerateForum)(mod) ??
|
||||
modLog.toggleCloseTopic(mod, categ.name, topic.name, topic.open)
|
||||
modLog.toggleCloseTopic(mod.id, categ.name, topic.name, topic.open)
|
||||
}
|
||||
|
||||
def toggleHide(categ: Categ, topic: Topic, mod: User): Funit =
|
||||
TopicRepo.hide(topic.id, topic.visibleOnHome) >> {
|
||||
MasterGranter(_.ModerateForum)(mod) ?? {
|
||||
PostRepo.hideByTopic(topic.id, topic.visibleOnHome) zip
|
||||
modLog.toggleHideTopic(mod, categ.name, topic.name, topic.visibleOnHome)
|
||||
modLog.toggleHideTopic(mod.id, categ.name, topic.name, topic.visibleOnHome)
|
||||
} >> env.recent.invalidate
|
||||
}
|
||||
|
||||
def denormalize(topic: Topic): Funit = for {
|
||||
nbPosts ← PostRepo countByTopics List(topic)
|
||||
lastPost ← PostRepo lastByTopics List(topic)
|
||||
nbPostsTroll ← PostRepoTroll countByTopics List(topic)
|
||||
lastPostTroll ← PostRepoTroll lastByTopics List(topic)
|
||||
_ ← $update(topic.copy(
|
||||
nbPosts ← PostRepo countByTopics List(topic.id)
|
||||
lastPost ← PostRepo lastByTopics List(topic.id)
|
||||
nbPostsTroll ← PostRepoTroll countByTopics List(topic.id)
|
||||
lastPostTroll ← PostRepoTroll lastByTopics List(topic.id)
|
||||
_ ← env.topicColl.update($id(topic.id), topic.copy(
|
||||
nbPosts = nbPosts,
|
||||
lastPostId = lastPost ?? (_.id),
|
||||
updatedAt = lastPost.fold(topic.updatedAt)(_.createdAt),
|
||||
nbPostsTroll = nbPostsTroll,
|
||||
lastPostIdTroll = lastPostTroll ?? (_.id),
|
||||
updatedAtTroll = lastPostTroll.fold(topic.updatedAtTroll)(_.createdAt)
|
||||
))
|
||||
)).void
|
||||
} yield ()
|
||||
|
||||
def denormalize: Funit = $find.all[Topic] flatMap { topics =>
|
||||
topics.map(denormalize).sequenceFu
|
||||
} void
|
||||
}
|
||||
|
|
|
@ -13,22 +13,22 @@ sealed abstract class TopicRepo(troll: Boolean) {
|
|||
|
||||
import BSONHandlers.TopicBSONHandler
|
||||
|
||||
private lazy val trollFilter = troll.fold(
|
||||
Json.obj(),
|
||||
Json.obj("troll" -> false)
|
||||
)
|
||||
// dirty
|
||||
private val coll = Env.current.topicColl
|
||||
|
||||
private val trollFilter = troll.fold($empty, $doc("troll" -> false))
|
||||
|
||||
def close(id: String, value: Boolean): Funit =
|
||||
$update.field(id, "closed", value)
|
||||
coll.updateField($id(id), "closed", value).void
|
||||
|
||||
def hide(id: String, value: Boolean): Funit =
|
||||
$update.field(id, "hidden", value)
|
||||
coll.updateField($id(id), "hidden", value).void
|
||||
|
||||
def byCateg(categ: Categ): Fu[List[Topic]] =
|
||||
$find(byCategQuery(categ))
|
||||
coll.list[Topic](byCategQuery(categ))
|
||||
|
||||
def byTree(categSlug: String, slug: String): Fu[Option[Topic]] =
|
||||
$find.one(Json.obj("categId" -> categSlug, "slug" -> slug) ++ trollFilter)
|
||||
coll.one[Topic]($doc("categId" -> categSlug, "slug" -> slug) ++ trollFilter)
|
||||
|
||||
def nextSlug(categ: Categ, name: String, it: Int = 1): Fu[String] = {
|
||||
val slug = Topic.nameToId(name) + ~(it != 1).option("-" + it)
|
||||
|
@ -42,7 +42,7 @@ sealed abstract class TopicRepo(troll: Boolean) {
|
|||
}
|
||||
|
||||
def incViews(topic: Topic): Funit =
|
||||
$update($select(topic.id), $inc("views" -> 1))
|
||||
coll.update($id(topic.id), $inc("views" -> 1)).void
|
||||
|
||||
def byCategQuery(categ: Categ) = Json.obj("categId" -> categ.slug) ++ trollFilter
|
||||
def byCategQuery(categ: Categ) = $doc("categId" -> categ.slug) ++ trollFilter
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import play.api.libs.json._
|
|||
import reactivemongo.bson._
|
||||
|
||||
import lila.common.LightUser
|
||||
import lila.db.BSON._
|
||||
import lila.db.BSON
|
||||
import lila.db.dsl._
|
||||
import lila.memo.{ ExpireSetMemo, MongoCache }
|
||||
import lila.rating.{ Perf, PerfType }
|
||||
|
|
|
@ -7,7 +7,6 @@ import reactivemongo.bson._
|
|||
import scala.concurrent.duration._
|
||||
|
||||
import lila.db.dsl._
|
||||
import lila.db.BSON._
|
||||
import lila.db.BSON.MapValue.MapHandler
|
||||
import lila.memo.{ AsyncCache, MongoCache }
|
||||
import lila.rating.{ Perf, PerfType }
|
||||
|
|
Loading…
Reference in a new issue