Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ package net.opatry.tasks.app.di

import android.content.Context
import androidx.room.Room
import androidx.room.withTransaction
import net.opatry.tasks.CredentialsStorage
import net.opatry.tasks.FileCredentialsStorage
import net.opatry.tasks.data.TasksAppDatabase
import net.opatry.tasks.data.TransactionRunner
import org.koin.core.module.Module
import org.koin.dsl.module
import java.io.File
Expand All @@ -52,4 +54,15 @@ actual fun platformModule(target: String): Module = module {
val credentialsFile = File(context.cacheDir, "google_auth_token_cache.json")
FileCredentialsStorage(credentialsFile.absolutePath)
}

single<TransactionRunner> {
object : TransactionRunner {
override suspend fun <R> runInTransaction(logic: suspend () -> R): R {
val db = get<TasksAppDatabase>()
return db.withTransaction {
logic()
}
}
}
}
Comment on lines +58 to +67

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The TasksAppDatabase instance is resolved using get() inside runInTransaction, meaning it's resolved on every call. Resolving the dependency once when the TransactionRunner is created would be more efficient.

    single<TransactionRunner> {
        val db = get<TasksAppDatabase>()
        object : TransactionRunner {
            override suspend fun <R> runInTransaction(logic: suspend () -> R): R {
                return db.withTransaction(logic)
            }
        }
    }

}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import net.opatry.tasks.app.presentation.UserViewModel
import net.opatry.tasks.data.TaskDao
import net.opatry.tasks.data.TaskListDao
import net.opatry.tasks.data.TaskRepository
import net.opatry.tasks.data.TransactionRunner
import net.opatry.tasks.data.UserDao
import org.koin.core.annotation.KoinExperimentalAPI
import org.koin.dsl.module
Expand Down Expand Up @@ -103,7 +104,14 @@ class AndroidDITest {
fun `verify app module`() {
tasksAppModule.verify(
injections = injectedParameters(
definition<TaskRepository>(TaskListDao::class, TaskDao::class, TaskListsApi::class, TasksApi::class, NowProvider::class),
definition<TaskRepository>(
TransactionRunner::class,
TaskListDao::class,
TaskDao::class,
TaskListsApi::class,
TasksApi::class,
NowProvider::class
),
definition<TaskListsViewModel>(Duration::class, Logger::class),
definition<UserViewModel>(Logger::class, UserDao::class, CredentialsStorage::class, UserInfoApi::class, NowProvider::class),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import net.opatry.google.tasks.TasksApi
import net.opatry.tasks.InMemoryTasksApi
import net.opatry.tasks.NowProvider
import net.opatry.tasks.data.TaskRepository
import net.opatry.tasks.data.TransactionRunner

internal suspend fun TaskRepository.printTaskTree() {
getTaskLists().firstOrNull()?.let { taskLists ->
Expand All @@ -49,6 +50,10 @@ internal suspend fun TaskRepository.printTaskTree() {
} ?: println("Task lists not ready.")
}

private val TestTransactionRunner = object : TransactionRunner {
override suspend fun <R> runInTransaction(logic: suspend () -> R): R = logic()
}

internal fun runTaskRepositoryTest(
taskListsApi: TaskListsApi = InMemoryTaskListsApi(),
tasksApi: TasksApi = InMemoryTasksApi(),
Expand All @@ -59,7 +64,14 @@ internal fun runTaskRepositoryTest(
.setQueryCoroutineContext(backgroundScope.coroutineContext)
.build()

val repository = TaskRepository(db.getTaskListDao(), db.getTaskDao(), taskListsApi, tasksApi, NowProvider(Clock.System::now))
val repository = TaskRepository(
transactionRunner = TestTransactionRunner,
taskListDao = db.getTaskListDao(),
taskDao = db.getTaskDao(),
taskListsApi = taskListsApi,
tasksApi = tasksApi,
nowProvider = NowProvider(Clock.System::now)
)
try {
test(repository)
} catch (e: AssertionError) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,12 @@
package net.opatry.tasks.app.di

import androidx.room.Room
import androidx.room.Transactor
import androidx.room.useWriterConnection
import net.opatry.tasks.CredentialsStorage
import net.opatry.tasks.FileCredentialsStorage
import net.opatry.tasks.data.TasksAppDatabase
import net.opatry.tasks.data.TransactionRunner
import org.koin.core.module.Module
import org.koin.core.qualifier.named
import org.koin.dsl.module
Expand All @@ -52,4 +55,17 @@ actual fun platformModule(target: String): Module = module {
val credentialsFile = File(get<File>(named("app_root_dir")), "google_auth_token_cache.json")
FileCredentialsStorage(credentialsFile.absolutePath)
}
}

single<TransactionRunner> {
object : TransactionRunner {
override suspend fun <R> runInTransaction(logic: suspend () -> R): R {
val db = get<TasksAppDatabase>()
return db.useWriterConnection { transactor ->
transactor.withTransaction(Transactor.SQLiteTransactionType.IMMEDIATE) {
logic()
}
}
}
}
}
Comment on lines +59 to +70

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The TasksAppDatabase for JVM resolves on every transaction. Optimizing by resolving it once when the TransactionRunner is created would be more efficient.

    single<TransactionRunner> {
        val db = get<TasksAppDatabase>()
        object : TransactionRunner {
            override suspend fun <R> runInTransaction(logic: suspend () -> R): R {
                return db.useWriterConnection { transactor ->
                    transactor.withTransaction(Transactor.SQLiteTransactionType.IMMEDIATE, logic)
                }
            }
        }
    }

}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import net.opatry.tasks.app.presentation.UserViewModel
import net.opatry.tasks.data.TaskDao
import net.opatry.tasks.data.TaskListDao
import net.opatry.tasks.data.TaskRepository
import net.opatry.tasks.data.TransactionRunner
import net.opatry.tasks.data.UserDao
import org.koin.core.annotation.KoinExperimentalAPI
import org.koin.dsl.module
Expand Down Expand Up @@ -109,7 +110,14 @@ class DesktopDITest {
fun `verify app module`() {
tasksAppModule.verify(
injections = injectedParameters(
definition<TaskRepository>(TaskListDao::class, TaskDao::class, TaskListsApi::class, TasksApi::class, NowProvider::class),
definition<TaskRepository>(
TransactionRunner::class,
TaskListDao::class,
TaskDao::class,
TaskListsApi::class,
TasksApi::class,
NowProvider::class
),
definition<TaskListsViewModel>(Duration::class, Logger::class),
definition<UserViewModel>(Logger::class, UserDao::class, CredentialsStorage::class, UserInfoApi::class, NowProvider::class),
)
Expand Down
Loading