limit study chapter nodes to 3000
I've seen some with 35,000 nodes on prod. It works but it's slow. And pointless.pull/4019/head
parent
2f89731d4e
commit
a457bc3e7c
|
@ -79,10 +79,16 @@ case class Chapter(
|
|||
def withoutChildren = copy(root = root.withoutChildren)
|
||||
|
||||
def relayAndTags = relay map { Chapter.RelayAndTags(id, _, tags) }
|
||||
|
||||
def isOverweight = root.children.countRecursive >= Chapter.maxNodes
|
||||
}
|
||||
|
||||
object Chapter {
|
||||
|
||||
// I've seen chapters with 35,000 nodes on prod.
|
||||
// It works but could be used for DoS.
|
||||
val maxNodes = 3000
|
||||
|
||||
case class Id(value: String) extends AnyVal with StringValue
|
||||
implicit val idIso = lila.common.Iso.string[Id](Id.apply, _.value)
|
||||
|
||||
|
|
|
@ -21,7 +21,10 @@ private final class ExplorerGame(
|
|||
}
|
||||
|
||||
def insert(userId: User.ID, study: Study, position: Position, gameId: Game.ID): Fu[Option[(Chapter, Path)]] =
|
||||
importer(gameId) map {
|
||||
if (position.chapter.isOverweight) {
|
||||
logger.info(s"Overweight chapter ${study.id}/${position.chapter.id}")
|
||||
fuccess(none)
|
||||
} else importer(gameId) map {
|
||||
_ ?? { game =>
|
||||
position.node ?? { fromNode =>
|
||||
GameToRoot(game, none, false).|> { root =>
|
||||
|
|
|
@ -198,6 +198,10 @@ object Node {
|
|||
case (node, index) => node.children.pathToIndexes(tail).map(rest => index :: rest)
|
||||
}
|
||||
}
|
||||
|
||||
def countRecursive: Int = nodes.foldLeft(nodes.size) {
|
||||
case (count, n) => count + n.children.countRecursive
|
||||
}
|
||||
}
|
||||
val emptyChildren = Children(Vector.empty)
|
||||
|
||||
|
|
|
@ -192,12 +192,16 @@ final class StudyApi(
|
|||
}
|
||||
}
|
||||
|
||||
private[study] def doAddNode(userId: User.ID, study: Study, position: Position, rawNode: Node, uid: Uid, opts: MoveOpts, relay: Option[Chapter.Relay]): Funit = {
|
||||
private def doAddNode(userId: User.ID, study: Study, position: Position, rawNode: Node, uid: Uid, opts: MoveOpts, relay: Option[Chapter.Relay]): Funit = {
|
||||
val node = rawNode.withoutChildren
|
||||
position.chapter.addNode(node, position.path, relay) match {
|
||||
def failReload = reloadUidBecauseOf(study, uid, position.chapter.id)
|
||||
if (position.chapter.isOverweight) {
|
||||
logger.info(s"Overweight chapter ${study.id}/${position.chapter.id}")
|
||||
fuccess(failReload)
|
||||
} else position.chapter.addNode(node, position.path, relay) match {
|
||||
case None =>
|
||||
fufail(s"Invalid addNode ${study.id} ${position.ref} $node") >>-
|
||||
reloadUidBecauseOf(study, uid, position.chapter.id) inject none
|
||||
failReload
|
||||
fufail(s"Invalid addNode ${study.id} ${position.ref} $node")
|
||||
case Some(chapter) =>
|
||||
chapter.root.nodeAt(position.path) ?? { parent =>
|
||||
val newPosition = position.ref + node
|
||||
|
|
Loading…
Reference in New Issue