chore: Flow version of firstOrNull

This commit is contained in:
Ahmad Ansori Palembani 2024-12-04 12:05:19 +07:00
parent 19ea7cbebd
commit 106737371f
Signed by: null2264
GPG key ID: BA64F8B60AF3EFB6
6 changed files with 47 additions and 0 deletions

View file

@ -12,6 +12,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.withContext
import yokai.data.util.executeAsFirstOrNull
import yokai.data.util.mapToFirstOrNull
class AndroidDatabaseHandler(
val db: Database,
@ -80,6 +81,10 @@ class AndroidDatabaseHandler(
return block(db).asFlow().mapToOneOrNull(queryDispatcher)
}
override fun <T : Any> subscribeToFirstOrNull(block: Database.() -> Query<T>): Flow<T?> {
return block(db).asFlow().mapToFirstOrNull(queryDispatcher)
}
/*
override fun <T : Any> subscribeToPagingSource(
countQuery: Database.() -> Query<Long>,

View file

@ -43,6 +43,8 @@ interface DatabaseHandler {
fun <T : Any> subscribeToOneOrNull(block: Database.() -> Query<T>): Flow<T?>
fun <T : Any> subscribeToFirstOrNull(block: Database.() -> Query<T>): Flow<T?>
/*
fun <T : Any> subscribeToPagingSource(
countQuery: Database.() -> Query<Long>,

View file

@ -1,7 +1,12 @@
package yokai.data.util
import app.cash.sqldelight.ExecutableQuery
import app.cash.sqldelight.Query
import app.cash.sqldelight.db.QueryResult
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.withContext
fun <T : Any> ExecutableQuery<T>.executeAsFirst(): T {
return executeAsFirstOrNull() ?: throw NullPointerException("ResultSet returned null for $this")
@ -11,3 +16,33 @@ fun <T : Any> ExecutableQuery<T>.executeAsFirstOrNull(): T? = execute { cursor -
if (!cursor.next().value) return@execute QueryResult.Value(null)
QueryResult.Value(mapper(cursor))
}.value
suspend fun <T : Any> ExecutableQuery<T>.awaitAsFirst(): T {
return awaitAsFirstOrNull()
?: throw NullPointerException("ResultSet returned null for $this")
}
suspend fun <T : Any> ExecutableQuery<T>.awaitAsFirstOrNull(): T? = execute { cursor ->
// If the cursor isn't async, we want to preserve the blocking semantics and execute it synchronously
when (val next = cursor.next()) {
is QueryResult.AsyncValue -> {
QueryResult.AsyncValue {
if (!next.await()) return@AsyncValue null
mapper(cursor)
}
}
is QueryResult.Value -> {
if (!next.value) return@execute QueryResult.Value(null)
QueryResult.Value(mapper(cursor))
}
}
}.await()
fun <T : Any> Flow<Query<T>>.mapToFirstOrNull(
context: CoroutineContext,
): Flow<T?> = map {
withContext(context) {
it.awaitAsFirstOrNull()
}
}