Skip to content

Commit

Permalink
GH-458 Part of the statistics implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
dzikoysk committed Jun 9, 2021
1 parent b95b07b commit 93dab9c
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 55 deletions.
2 changes: 0 additions & 2 deletions reposilite-backend/reposilite-backend.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,6 @@ dependencies {
testImplementation("com.google.http-client:google-http-client-jackson2:1.39.2")
testImplementation("org.mockito:mockito-inline:3.9.0")
testImplementation("org.mockito:mockito-core:3.9.0")

testImplementation("org.codehaus.groovy:groovy-all:3.0.7")
testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.1")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,5 @@ fun <TABLE : Table> TABLE.insertOrUpdate(identifiableEntity: IdentifiableEntity,
}
}

inline fun <T, R> Iterable<T>.firstAndMap(transform: (T) -> R): R? =
this.firstOrNull()?.let(transform)

fun <T, R> Iterable<T>.firstAndMap(transform: (T) -> R): R? =
this.firstOrNull()?.let(transform)
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,19 @@

package org.panda_lang.reposilite.stats.api

import org.panda_lang.reposilite.shared.sql.UNINITIALIZED_ENTITY_ID

enum class RecordType {
REQUEST
}

data class Record(
val id: Int = -1,
val id: Int = UNINITIALIZED_ENTITY_ID,
val type: RecordType,
val identifier: String,
val count: Long
)

enum class RecordType {
REQUEST
}

data class RecordIdentifier(
val type: RecordType,
val identifier: String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

package org.panda_lang.reposilite.stats.infrastructure

import org.jetbrains.exposed.sql.Op
import org.jetbrains.exposed.sql.Op.Companion.build
import org.jetbrains.exposed.sql.ResultRow
import org.jetbrains.exposed.sql.SchemaUtils
import org.jetbrains.exposed.sql.SqlExpressionBuilder
Expand All @@ -27,6 +27,8 @@ import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.sum
import org.jetbrains.exposed.sql.transactions.transaction
import org.jetbrains.exposed.sql.update
import org.panda_lang.reposilite.shared.sql.firstAndMap
import org.panda_lang.reposilite.shared.sql.transactionUnit
import org.panda_lang.reposilite.stats.StatisticsRepository
import org.panda_lang.reposilite.stats.api.Record
import org.panda_lang.reposilite.stats.api.RecordIdentifier
Expand All @@ -40,28 +42,26 @@ internal class SqlStatisticsRepository : StatisticsRepository {
}
}

override fun createRecord(identifier: RecordIdentifier, initCount: Long) {
transaction {
override fun createRecord(identifier: RecordIdentifier, initCount: Long) =
transactionUnit {
StatisticsTable.insert {
it[StatisticsTable.type] = identifier.type
it[StatisticsTable.identifier] = identifier.identifier
it[StatisticsTable.count] = initCount
it[this.type] = identifier.type.name
it[this.identifier] = identifier.identifier
it[this.count] = initCount
}
}
}

override fun incrementRecord(identifier: RecordIdentifier, count: Long) {
transaction {
val id: Int? = StatisticsTable
.select { Op.build { StatisticsTable.type eq identifier.type }.and { StatisticsTable.identifier eq identifier.identifier } }
.map { it[StatisticsTable.id].value }
.firstOrNull()
override fun incrementRecord(identifier: RecordIdentifier, count: Long) =
transactionUnit {
val id = StatisticsTable
.select { build { StatisticsTable.type eq identifier.type.name }.and { StatisticsTable.identifier eq identifier.identifier } }
.firstAndMap { it[StatisticsTable.id].value }

if (id == null) {
StatisticsTable.insert {
it[StatisticsTable.type] = identifier.type
it[StatisticsTable.identifier] = identifier.identifier
it[StatisticsTable.count] = count
it[this.type] = identifier.type.name
it[this.identifier] = identifier.identifier
it[this.count] = count
}
}
else {
Expand All @@ -73,42 +73,40 @@ internal class SqlStatisticsRepository : StatisticsRepository {
}

}
}

override fun findRecordByTypeAndIdentifier(identifier: RecordIdentifier): Record? = transaction {
StatisticsTable
.select { Op.build { StatisticsTable.type eq identifier.type }.and { StatisticsTable.identifier eq identifier.identifier } }
.map { toRecord(it) }
.firstOrNull()
}

override fun findRecordsByPhrase(type: RecordType, phrase: String): List<Record> = transaction {
StatisticsTable
.select { Op.build { StatisticsTable.type eq type }.and { StatisticsTable.identifier like "%${phrase}%" }}
.map { toRecord(it) }
}

private fun toRecord(row: ResultRow) =
Record(
row[StatisticsTable.id].value,
row[StatisticsTable.type],
RecordType.valueOf(row[StatisticsTable.type].toUpperCase()),
row[StatisticsTable.identifier],
row[StatisticsTable.count]
)

override fun countUniqueRecords(): Long = transaction {
StatisticsTable.selectAll().count()
}
override fun findRecordByTypeAndIdentifier(identifier: RecordIdentifier): Record? =
transaction {
StatisticsTable.select { build { StatisticsTable.type eq identifier.type.name }.and { StatisticsTable.identifier eq identifier.identifier } }
.firstAndMap { toRecord(it) }
}

override fun countRecords(): Long = transaction {
val countSum = StatisticsTable.count.sum()
override fun findRecordsByPhrase(type: RecordType, phrase: String): List<Record> =
transaction {
StatisticsTable.select { build { StatisticsTable.type eq type.name }.and { StatisticsTable.identifier like "%${phrase}%" }}
.map { toRecord(it) }
}

StatisticsTable
.slice(countSum)
.selectAll()
.first()
.let { it[countSum] }
?: 0
}
override fun countRecords(): Long =
transaction {
StatisticsTable.count.sum().let { countSum ->
StatisticsTable.slice(countSum).selectAll()
.first()
.let { it[countSum] }
?: 0
}
}

override fun countUniqueRecords(): Long =
transaction {
StatisticsTable.selectAll().count()
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,16 @@ package org.panda_lang.reposilite.stats.infrastructure

import org.jetbrains.exposed.dao.id.IntIdTable
import org.jetbrains.exposed.sql.Column
import org.panda_lang.reposilite.stats.api.RecordType

internal object StatisticsTable : IntIdTable("statistics") {

val type: Column<RecordType> = enumeration("type", RecordType::class)
val type: Column<String> = varchar("type", 32)
val identifier: Column<String> = varchar("identifier", 2048)
val count: Column<Long> = long("count")

init {
index(columns = arrayOf(type))
uniqueIndex(type, identifier)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ internal abstract class FileSystemStorageProvider private constructor(
}

val fileChannel = FileChannel.open(file, WRITE, CREATE)
// TOFIX: FS locks are not truly respected, it should be enhanced with .lock file to be sure if it's respected.
// ~ https://github.com/dzikoysk/reposilite/issues/264
fileChannel.lock()

val bytesWritten = writer.apply(input, fileChannel).toLong()
Expand Down

0 comments on commit 93dab9c

Please sign in to comment.