This commit is contained in:
InsanusMokrassar 2020-11-22 23:19:16 +06:00
parent 615f7f99c3
commit 07a65e0bb5
3 changed files with 40 additions and 8 deletions

View File

@ -1,6 +1,6 @@
package dev.inmo.micro_utils.repos package dev.inmo.micro_utils.repos
import kotlinx.coroutines.newSingleThreadContext import kotlinx.coroutines.Dispatchers
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
val DatabaseCoroutineContext: CoroutineContext = newSingleThreadContext("db-context") val DatabaseCoroutineContext: CoroutineContext = Dispatchers.IO

View File

@ -3,10 +3,42 @@ package dev.inmo.micro_utils.repos
import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteDatabase
import dev.inmo.micro_utils.coroutines.safely import dev.inmo.micro_utils.coroutines.safely
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import java.util.concurrent.Executors import java.util.concurrent.Executors
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.coroutineContext import kotlin.coroutines.coroutineContext
private object ContextsPool {
private val contexts = mutableListOf<CoroutineContext>()
private val mutex = Mutex(locked = false)
private val freeContexts = mutableListOf<CoroutineContext>()
suspend fun acquireContext(): CoroutineContext {
return mutex.withLock {
freeContexts.removeFirstOrNull() ?: Executors.newSingleThreadExecutor().asCoroutineDispatcher().also {
contexts.add(it)
}
}
}
suspend fun freeContext(context: CoroutineContext) {
return mutex.withLock {
if (context in contexts && context !in freeContexts) {
freeContexts.add(context)
}
}
}
suspend fun <T> use(block: suspend (CoroutineContext) -> T): T = acquireContext().let {
try {
block(it)
} finally {
freeContext(it)
}
}
}
class TransactionContext( class TransactionContext(
val databaseContext: CoroutineContext val databaseContext: CoroutineContext
): CoroutineContext.Element { ): CoroutineContext.Element {
@ -20,7 +52,7 @@ suspend fun <T> SQLiteDatabase.transaction(block: suspend SQLiteDatabase.() -> T
withContext(it.databaseContext) { withContext(it.databaseContext) {
block() block()
} }
} ?: Executors.newSingleThreadExecutor().asCoroutineDispatcher().let { context -> } ?: ContextsPool.use { context ->
withContext(TransactionContext(context) + context) { withContext(TransactionContext(context) + context) {
beginTransaction() beginTransaction()
safely( safely(

View File

@ -32,11 +32,11 @@ class AndroidSQLStandardVersionsRepoProxy(
} }
} }
override suspend fun getTableVersion(tableName: String): Int? = database.writableTransaction { override suspend fun getTableVersion(table: String): Int? = database.writableTransaction {
select( select(
tableName, tableName,
selection = "$tableNameColumnName=?", selection = "$tableNameColumnName=?",
selectionArgs = arrayOf(tableName), selectionArgs = arrayOf(table),
limit = limitClause(1) limit = limitClause(1)
).use { ).use {
if (it.moveToFirst()) { if (it.moveToFirst()) {
@ -47,16 +47,16 @@ class AndroidSQLStandardVersionsRepoProxy(
} }
} }
override suspend fun updateTableVersion(tableName: String, version: Int) { override suspend fun updateTableVersion(table: String, version: Int) {
database.writableTransaction { database.writableTransaction {
val updated = update( val updated = update(
tableName, tableName,
contentValuesOf(tableVersionColumnName to version), contentValuesOf(tableVersionColumnName to version),
"$tableNameColumnName=?", "$tableNameColumnName=?",
arrayOf(version.toString()) arrayOf(table)
) > 0 ) > 0
if (!updated) { if (!updated) {
insert(tableName, null, contentValuesOf(tableNameColumnName to tableName, tableVersionColumnName to version)) insert(tableName, null, contentValuesOf(tableNameColumnName to table, tableVersionColumnName to version))
} }
} }
} }