Skip to content

Commit

Permalink
fix: refactor block indexing
Browse files Browse the repository at this point in the history
  • Loading branch information
d1snin committed Nov 9, 2023
1 parent 2693b40 commit 901b2a4
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ public suspend fun SpaceContext.block(configure: suspend BlockContext.() -> Unit

val createdBlock = client.postBlock {
row = 0
index = null
size = BlockSize.SMALL
spaceId = space

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public sealed interface AbstractBlock {
public data class Block(
val id: BlockId,
override val row: RowIndex,
override val index: BlockIndex?,
override val index: BlockIndex,
override val size: BlockSize,
override val entities: ContentEntities,
override val metadata: Metadata,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package dev.d1s.beam.daemon.converter

import dev.d1s.beam.commons.Block
import dev.d1s.beam.daemon.entity.BlockEntity
import dev.d1s.beam.daemon.entity.requiredIndex
import dev.d1s.exkt.dto.DtoConverter
import org.koin.core.component.KoinComponent

Expand All @@ -28,7 +29,7 @@ class BlockDtoConverter : DtoConverter<BlockEntity, Block>, KoinComponent {
Block(
id.toString(),
row,
index,
requiredIndex,
size,
entities,
metadata,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,18 @@

package dev.d1s.beam.daemon.database

import dev.d1s.beam.commons.RowIndex
import dev.d1s.beam.daemon.entity.BlockEntities
import dev.d1s.beam.daemon.entity.BlockEntity
import dev.d1s.beam.daemon.entity.SpaceEntity
import dev.d1s.beam.daemon.entity.requiredIndex
import dev.d1s.beam.daemon.util.withIoCatching
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
import org.ktorm.database.Database
import org.ktorm.dsl.and
import org.ktorm.dsl.eq
import org.ktorm.dsl.greaterEq
import org.ktorm.entity.*
import java.util.*

Expand All @@ -37,6 +41,14 @@ interface BlockRepository {

suspend fun findBlocksInSpace(space: SpaceEntity): Result<BlockEntities>

suspend fun findLatestBlockIndexInSpaceByRow(space: SpaceEntity, row: RowIndex): Result<Int>

suspend fun findBlocksInSpaceByRowWhichIndexIsGreaterOrEqualTo(
space: SpaceEntity,
row: RowIndex,
index: Int
): Result<BlockEntities>

suspend fun updateBlock(block: BlockEntity): Result<BlockEntity>

suspend fun updateBlocks(blocks: BlockEntities): Result<BlockEntities>
Expand Down Expand Up @@ -73,6 +85,26 @@ class DefaultBlockRepository : BlockRepository, KoinComponent {
findBlocksInSpaceAsSequence(space).toList()
}

override suspend fun findLatestBlockIndexInSpaceByRow(space: SpaceEntity, row: RowIndex): Result<Int> =
withIoCatching {
findBlocksInSpaceAsSequence(space, row).sortedByDescending {
it.index
}.first().requiredIndex
}

override suspend fun findBlocksInSpaceByRowWhichIndexIsGreaterOrEqualTo(
space: SpaceEntity,
row: RowIndex,
index: Int
): Result<BlockEntities> =
withIoCatching {
findBlocksInSpaceAsSequence(space, row).sortedByDescending {
it.index
}.filter {
it.index greaterEq index
}.toList()
}

override suspend fun updateBlock(block: BlockEntity): Result<BlockEntity> =
withIoCatching {
block.apply {
Expand All @@ -96,8 +128,14 @@ class DefaultBlockRepository : BlockRepository, KoinComponent {
Unit
}

private fun findBlocksInSpaceAsSequence(space: SpaceEntity) =
database.blocks.filter {
it.spaceId eq space.id
private fun findBlocksInSpaceAsSequence(space: SpaceEntity, row: RowIndex? = null) =
database.blocks.filter { block ->
(block.spaceId eq space.id).let {
if (row != null) {
it and (block.row eq row)
} else {
it
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,9 @@ interface BlockEntity : UuidIdentified<BlockEntity> {
}

val BlockEntity.asString
get() = "BlockEntity{row = $row, index = $index, size = $size, entities = $entities, metadata = $metadata}"
get() = "BlockEntity{row = $row, index = $index, size = $size, entities = $entities, metadata = $metadata}"

val BlockEntity.requiredIndex get() =
requireNotNull(index) {
"Block (entity) index is not set"
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import dev.d1s.beam.daemon.configuration.DtoConverters
import dev.d1s.beam.daemon.database.BlockRepository
import dev.d1s.beam.daemon.entity.BlockEntity
import dev.d1s.beam.daemon.entity.asString
import dev.d1s.beam.daemon.entity.requiredIndex
import dev.d1s.beam.daemon.exception.UnprocessableEntityException
import dev.d1s.exkt.dto.*
import dev.d1s.ktor.events.server.WebSocketEventChannel
Expand Down Expand Up @@ -95,6 +96,7 @@ class DefaultBlockService : BlockService, KoinComponent {
translationService.verifyLocationsExist(block).getOrThrow()

processBlockRow(block)
processBlockIndex(block)

val addedBlock = blockRepository.addBlock(block).getOrThrow()
val translatedBlock = translateOptionally(addedBlock, languageCode)
Expand Down Expand Up @@ -146,7 +148,7 @@ class DefaultBlockService : BlockService, KoinComponent {

val sortedBlocks = blocks
.sortedBy {
it.index ?: MAX_INDEX
it.index
}
.sortedBy {
it.row
Expand Down Expand Up @@ -175,6 +177,7 @@ class DefaultBlockService : BlockService, KoinComponent {
translationService.verifyLocationsExist(modification).getOrThrow()

processBlockRow(modification)
processBlockIndex(modification)

originalBlock.apply {
this.row = modification.row
Expand Down Expand Up @@ -224,6 +227,50 @@ class DefaultBlockService : BlockService, KoinComponent {
rowService.getOrCreateRow(block.row, block.space.id.toString()).getOrThrow()
}

private suspend fun processBlockIndex(block: BlockEntity) {
val space = block.space
val row = block.row

var latestIndex = blockRepository.findLatestBlockIndexInSpaceByRow(space, row).getOrNull()

if (block.index == null) {
block.index = latestIndex?.inc() ?: START_INDEX
}

val requiredIndex = block.requiredIndex

if (latestIndex == null) {
if (requiredIndex != START_INDEX) {
throw BadRequestException("First block index must be $START_INDEX")
}

latestIndex = START_INDEX
}

logger.d {
"Processing block index. index: $requiredIndex; latestIndex: $latestIndex"
}

when {
requiredIndex == latestIndex + 1 -> {}
requiredIndex <= latestIndex -> {
val blocksToUpdate =
blockRepository.findBlocksInSpaceByRowWhichIndexIsGreaterOrEqualTo(space, row, requiredIndex)
.getOrThrow()

blocksToUpdate.forEach {
it.index = it.requiredIndex + 1
}

blockRepository.updateBlocks(blocksToUpdate)
}

else -> {
throw BadRequestException("Block index is out of bounds")
}
}
}

// Я боюсь наступления вечера...

private suspend fun translateOptionally(block: BlockEntity, languageCode: LanguageCode?) =
Expand Down Expand Up @@ -264,6 +311,6 @@ class DefaultBlockService : BlockService, KoinComponent {

private companion object {

private const val MAX_INDEX = Int.MAX_VALUE
private const val START_INDEX = 0
}
}
6 changes: 5 additions & 1 deletion config/db/changelog.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@
{
"column": {
"name": "index",
"type": "integer"
"type": "integer",
"constraints": {
"nullable": false,
"notNullConstraintName": "nn_block_index"
}
}
},
{
Expand Down
6 changes: 3 additions & 3 deletions http/daemon.http
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Content-Type: application/json
"remark": null
}
}

a
### POST Root Space
POST http://localhost:8573/spaces/root
Content-Type: application/json
Expand Down Expand Up @@ -90,8 +90,8 @@ Authorization: Bearer {{token}}
Content-Type: application/json

{
"row": 0,
"index": null,
"row": 1,
"index": 0,
"size": "MEDIUM",
"entities": [
{
Expand Down

0 comments on commit 901b2a4

Please sign in to comment.