Compare commits

...

16 Commits

8 changed files with 122 additions and 28 deletions

View File

@@ -1,5 +1,30 @@
# Changelog
## 0.9.23
* `Repos`:
* `Exposed`:
* New property `ExposedRepo#selectAll` to retrieve all the rows in the table
## 0.9.22
* `Ktor`:
* `Server`:
* Now `createKtorServer` fun is fully customizable
## 0.9.21
* `Repos`:
* `Exposed`:
* fixes in `AbstractExposedWriteCRUDRepo`
## 0.9.20
* `Repos`:
* `Common`:
* Fixes in `OneToManyAndroidRepo`
* New `CursorIterator`
## 0.9.19
* `Versions`:

View File

@@ -14,5 +14,5 @@ crypto_js_version=4.1.1
# Project data
group=dev.inmo
version=0.9.19
android_code_version=109
version=0.9.23
android_code_version=113

View File

@@ -3,6 +3,7 @@ package dev.inmo.micro_utils.ktor.server
import dev.inmo.micro_utils.ktor.server.configurators.KtorApplicationConfigurator
import io.ktor.application.Application
import io.ktor.server.cio.CIO
import io.ktor.server.cio.CIOApplicationEngine
import io.ktor.server.engine.*
import kotlin.random.Random
@@ -10,17 +11,21 @@ fun <TEngine : ApplicationEngine, TConfiguration : ApplicationEngine.Configurati
engine: ApplicationEngineFactory<TEngine, TConfiguration>,
host: String = "localhost",
port: Int = Random.nextInt(1024, 65535),
additionalEngineEnvironmentConfigurator: ApplicationEngineEnvironmentBuilder.() -> Unit = {},
additionalConfigurationConfigurator: TConfiguration.() -> Unit = {},
block: Application.() -> Unit
): TEngine {
val env = applicationEngineEnvironment {
): TEngine = embeddedServer(
engine,
applicationEngineEnvironment {
module(block)
connector {
this@connector.host = host
this@connector.port = port
this.host = host
this.port = port
}
}
return embeddedServer(engine, env)
}
additionalEngineEnvironmentConfigurator()
},
additionalConfigurationConfigurator
)
/**
* Create server with [CIO] server engine without starting of it
@@ -30,18 +35,31 @@ fun <TEngine : ApplicationEngine, TConfiguration : ApplicationEngine.Configurati
fun createKtorServer(
host: String = "localhost",
port: Int = Random.nextInt(1024, 65535),
additionalEngineEnvironmentConfigurator: ApplicationEngineEnvironmentBuilder.() -> Unit = {},
additionalConfigurationConfigurator: CIOApplicationEngine.Configuration.() -> Unit = {},
block: Application.() -> Unit
): ApplicationEngine = createKtorServer(CIO, host, port, block)
): CIOApplicationEngine = createKtorServer(
CIO,
host,
port,
additionalEngineEnvironmentConfigurator,
additionalConfigurationConfigurator,
block
)
fun <TEngine : ApplicationEngine, TConfiguration : ApplicationEngine.Configuration> createKtorServer(
engine: ApplicationEngineFactory<TEngine, TConfiguration>,
host: String = "localhost",
port: Int = Random.nextInt(1024, 65535),
additionalEngineEnvironmentConfigurator: ApplicationEngineEnvironmentBuilder.() -> Unit = {},
additionalConfigurationConfigurator: TConfiguration.() -> Unit = {},
configurators: List<KtorApplicationConfigurator>
): TEngine = createKtorServer(
engine,
host,
port
port,
additionalEngineEnvironmentConfigurator,
additionalConfigurationConfigurator
) {
configurators.forEach { it.apply { configure() } }
}
@@ -54,5 +72,7 @@ fun <TEngine : ApplicationEngine, TConfiguration : ApplicationEngine.Configurati
fun createKtorServer(
host: String = "localhost",
port: Int = Random.nextInt(1024, 65535),
configurators: List<KtorApplicationConfigurator>
): ApplicationEngine = createKtorServer(CIO, host, port, configurators)
configurators: List<KtorApplicationConfigurator>,
additionalEngineEnvironmentConfigurator: ApplicationEngineEnvironmentBuilder.() -> Unit = {},
additionalConfigurationConfigurator: CIOApplicationEngine.Configuration.() -> Unit = {},
): ApplicationEngine = createKtorServer(CIO, host, port, additionalEngineEnvironmentConfigurator, additionalConfigurationConfigurator, configurators)

View File

@@ -6,7 +6,7 @@ import dev.inmo.micro_utils.pagination.*
* Example:
*
* * `|__f__l_______________________|` will be transformed to `|_______________________f__l__|`
* * `|__f__l_|` will be transformed to `|__f__l_|`
* * `|__f__l_|` will be transformed to `|_f__l__|`
*
* @return Reversed version of this [Pagination]
*/

View File

@@ -0,0 +1,27 @@
package dev.inmo.micro_utils.repos
import android.database.Cursor
class CursorIterator(
private val c: Cursor
) : Iterator<Cursor> {
private var i = 0
init {
c.moveToFirst()
}
override fun hasNext(): Boolean {
return i < c.count
}
override fun next(): Cursor {
i++
return if (c.moveToNext()) {
c
} else {
throw NoSuchElementException()
}
}
}
operator fun Cursor.iterator(): CursorIterator = CursorIterator(this)

View File

@@ -143,7 +143,12 @@ class OneToManyAndroidRepo<Key, Value>(
}.toLong()
override suspend fun count(k: Key): Long = helper.blockingReadableTransaction {
selectDistinct(tableName, columns = valueColumnArray, selection = "$idColumnName=?", selectionArgs = arrayOf(k.keyAsString()), limit = FirstPagePagination(1).limitClause()).use {
selectDistinct(
tableName,
columns = valueColumnArray,
selection = "$idColumnName=?",
selectionArgs = arrayOf(k.keyAsString())
).use {
it.count
}
}.toLong()

View File

@@ -17,13 +17,19 @@ abstract class AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>(
ExposedCRUDRepo<ObjectType, IdType>,
WriteStandardCRUDRepo<ObjectType, IdType, InputValueType>
{
protected val newObjectsChannel = MutableSharedFlow<ObjectType>(replyCacheInFlows, flowsChannelsSize)
protected val updateObjectsChannel = MutableSharedFlow<ObjectType>(replyCacheInFlows, flowsChannelsSize)
protected val deleteObjectsIdsChannel = MutableSharedFlow<IdType>(replyCacheInFlows, flowsChannelsSize)
protected val _newObjectsFlow = MutableSharedFlow<ObjectType>(replyCacheInFlows, flowsChannelsSize)
protected val _updatedObjectsFlow = MutableSharedFlow<ObjectType>(replyCacheInFlows, flowsChannelsSize)
protected val _deletedObjectsIdsFlow = MutableSharedFlow<IdType>(replyCacheInFlows, flowsChannelsSize)
@Deprecated("Renamed", ReplaceWith("_newObjectsFlow"))
protected val newObjectsChannel = _newObjectsFlow
@Deprecated("Renamed", ReplaceWith("_updatedObjectsFlow"))
protected val updateObjectsChannel = _updatedObjectsFlow
@Deprecated("Renamed", ReplaceWith("_deletedObjectsIdsFlow"))
protected val deleteObjectsIdsChannel = _deletedObjectsIdsFlow
override val newObjectsFlow: Flow<ObjectType> = newObjectsChannel.asSharedFlow()
override val updatedObjectsFlow: Flow<ObjectType> = updateObjectsChannel.asSharedFlow()
override val deletedObjectsIdsFlow: Flow<IdType> = deleteObjectsIdsChannel.asSharedFlow()
override val newObjectsFlow: Flow<ObjectType> = _newObjectsFlow.asSharedFlow()
override val updatedObjectsFlow: Flow<ObjectType> = _updatedObjectsFlow.asSharedFlow()
override val deletedObjectsIdsFlow: Flow<IdType> = _deletedObjectsIdsFlow.asSharedFlow()
protected abstract fun InsertStatement<Number>.asObject(value: InputValueType): ObjectType
abstract val selectByIds: SqlExpressionBuilder.(List<IdType>) -> Op<Boolean>
@@ -43,7 +49,7 @@ abstract class AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>(
return transaction(db = database) {
values.map { value -> createWithoutNotification(value) }
}.onEach {
newObjectsChannel.emit(it)
_newObjectsFlow.emit(it)
}
}
@@ -74,7 +80,7 @@ abstract class AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>(
onBeforeUpdate(listOf(id to value))
return updateWithoutNotification(id, value).also {
if (it != null) {
updateObjectsChannel.emit(it)
_updatedObjectsFlow.emit(it)
}
}
}
@@ -85,16 +91,25 @@ abstract class AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>(
values.map { (id, value) -> updateWithoutNotification(id, value) }
}.filterNotNull()
).onEach {
updateObjectsChannel.emit(it)
_updatedObjectsFlow.emit(it)
}
}
protected open suspend fun onBeforeDelete(ids: List<IdType>) {}
override suspend fun deleteById(ids: List<IdType>) {
onBeforeDelete(ids)
transaction(db = database) {
deleteWhere(null, null) {
val deleted = deleteWhere(null, null) {
selectByIds(ids)
}
if (deleted == ids.size) {
ids
} else {
ids.filter {
select { selectById(it) }.limit(1).none()
}
}
}.forEach {
_deletedObjectsIdsFlow.emit(it)
}
}
}

View File

@@ -1,8 +1,10 @@
package dev.inmo.micro_utils.repos.exposed
import dev.inmo.micro_utils.repos.Repo
import org.jetbrains.exposed.sql.Database
import org.jetbrains.exposed.sql.*
interface ExposedRepo : Repo {
interface ExposedRepo : Repo, FieldSet {
val database: Database
}
val selectAll: Transaction.() -> Query
get() = { (this@ExposedRepo as FieldSet).selectAll() }
}