diff --git a/IO/gtfs/src/commonMain/kotlin/xyz.ksharma.krail.io.gtfs/nswstops/ProtoParser.kt b/IO/gtfs/src/commonMain/kotlin/xyz.ksharma.krail.io.gtfs/nswstops/ProtoParser.kt index ea9e219c..d13bed81 100644 --- a/IO/gtfs/src/commonMain/kotlin/xyz.ksharma.krail.io.gtfs/nswstops/ProtoParser.kt +++ b/IO/gtfs/src/commonMain/kotlin/xyz.ksharma.krail.io.gtfs/nswstops/ProtoParser.kt @@ -4,7 +4,8 @@ import app.krail.kgtfs.proto.NswStopList interface ProtoParser { /** - * Reads the stops from the proto file packaged in the resources + * Reads and decodes the NSW stops from a protobuf file, then inserts the stops into the database. + * @return The decoded `NswStopList` containing the NSW stops. */ - suspend fun readStops(): NswStopList? + suspend fun parseAndInsertStops(): NswStopList? } diff --git a/IO/gtfs/src/commonMain/kotlin/xyz.ksharma.krail.io.gtfs/nswstops/StopsProtoParser.kt b/IO/gtfs/src/commonMain/kotlin/xyz.ksharma.krail.io.gtfs/nswstops/StopsProtoParser.kt index c9a30062..739430d3 100644 --- a/IO/gtfs/src/commonMain/kotlin/xyz.ksharma.krail.io.gtfs/nswstops/StopsProtoParser.kt +++ b/IO/gtfs/src/commonMain/kotlin/xyz.ksharma.krail.io.gtfs/nswstops/StopsProtoParser.kt @@ -17,33 +17,38 @@ class StopsProtoParser( private val sandook: Sandook, ) : ProtoParser { + /** + * Reads and decodes the NSW stops from a protobuf file, then inserts the stops into the database. + * + * @return The decoded `NswStopList` containing the NSW stops. + */ @OptIn(ExperimentalResourceApi::class) - override suspend fun readStops(): NswStopList = - withContext(ioDispatcher) { - var start = Clock.System.now() + override suspend fun parseAndInsertStops(): NswStopList = withContext(ioDispatcher) { + var start = Clock.System.now() - val byteArray = Res.readBytes("files/NSW_STOPS.pb") - val decoded = NswStopList.ADAPTER.decode(byteArray) + val byteArray = Res.readBytes("files/NSW_STOPS.pb") + val decodedStops = NswStopList.ADAPTER.decode(byteArray) - var duration = start.until( - Clock.System.now(), DateTimeUnit.MILLISECOND, TimeZone.currentSystemDefault() - ) - log("Decoded #Stops: ${decoded.nswStops.size} - duration: $duration ms") + var duration = start.until( + Clock.System.now(), DateTimeUnit.MILLISECOND, + TimeZone.currentSystemDefault(), + ) + log("Decoded #Stops: ${decodedStops.nswStops.size} - duration: $duration ms") - log("Start inserting stops. Currently ${sandook.stopsCount()} stops in the database") - start = Clock.System.now() - insertStopsInTransaction(decoded) + log("Start inserting stops. Currently ${sandook.stopsCount()} stops in the database") + start = Clock.System.now() + insertStopsInTransaction(decodedStops) + duration = start.until( + Clock.System.now(), DateTimeUnit.MILLISECOND, TimeZone.currentSystemDefault() + ) + log("Inserted #Stops: ${decodedStops.nswStops.size} in duration: $duration ms") - duration = start.until( - Clock.System.now(), DateTimeUnit.MILLISECOND, TimeZone.currentSystemDefault() - ) - log("Inserted #Stops: ${decoded.nswStops.size} in duration: $duration ms") - - decoded - } + decodedStops + } private suspend fun insertStopsInTransaction(decoded: NswStopList) = withContext(ioDispatcher) { - sandook.nswStopsQueries.transaction { + val start = Clock.System.now() + sandook.insertTransaction { decoded.nswStops.forEach { nswStop -> sandook.insertNswStop( stopId = nswStop.stopId, @@ -59,7 +64,13 @@ class StopsProtoParser( } } } + + val duration = start.until( + Clock.System.now(), DateTimeUnit.MILLISECOND, TimeZone.currentSystemDefault(), + ) // Log less frequently, for example once after the transaction completes - println("Inserted ${decoded.nswStops.size} stops in a single transaction.") + println("Inserted ${decoded.nswStops.size} stops in a single transaction in $duration ms") + // TODO - analytics track how much time it took to insert stops. + // Also track based on Firebase for performance. } } diff --git a/composeApp/src/commonMain/kotlin/xyz/ksharma/krail/splash/SplashViewModel.kt b/composeApp/src/commonMain/kotlin/xyz/ksharma/krail/splash/SplashViewModel.kt index e52c0bc9..ed09cd02 100644 --- a/composeApp/src/commonMain/kotlin/xyz/ksharma/krail/splash/SplashViewModel.kt +++ b/composeApp/src/commonMain/kotlin/xyz/ksharma/krail/splash/SplashViewModel.kt @@ -45,7 +45,7 @@ class SplashViewModel( kotlin.runCatching { log("Reading NSW_STOPS proto file - StopsParser:") - protoParser.readStops() + protoParser.parseAndInsertStops() }.getOrElse { log("Error reading proto file: $it") } diff --git a/core/test/src/commonTest/kotlin/xyz/ksharma/core/test/fakes/FakeSandook.kt b/core/test/src/commonTest/kotlin/xyz/ksharma/core/test/fakes/FakeSandook.kt index 36cd4bb6..4ee491b4 100644 --- a/core/test/src/commonTest/kotlin/xyz/ksharma/core/test/fakes/FakeSandook.kt +++ b/core/test/src/commonTest/kotlin/xyz/ksharma/core/test/fakes/FakeSandook.kt @@ -80,6 +80,10 @@ class FakeSandook : Sandook { stops.add(NswStops(stopId, stopName, stopLat, stopLon)) } + override fun stopsCount(): Int { + return stops.size + } + override fun insertNswStopProductClass(stopId: String, productClass: Int) { val productClasses = stopProductClasses.getOrPut(stopId) { mutableListOf() } productClasses.add(productClass) @@ -119,4 +123,8 @@ class FakeSandook : Sandook { stopProductClasses[stop.stopId]?.none { it in excludeProductClassList } == true } } + + override fun insertTransaction(block: () -> Unit) { + block() + } } diff --git a/sandook/src/commonMain/kotlin/xyz/ksharma/krail/sandook/RealSandook.kt b/sandook/src/commonMain/kotlin/xyz/ksharma/krail/sandook/RealSandook.kt index fe439473..0ed94165 100644 --- a/sandook/src/commonMain/kotlin/xyz/ksharma/krail/sandook/RealSandook.kt +++ b/sandook/src/commonMain/kotlin/xyz/ksharma/krail/sandook/RealSandook.kt @@ -7,7 +7,7 @@ internal class RealSandook(factory: SandookDriverFactory) : Sandook { private val sandook = KrailSandook(factory.createDriver()) private val query = sandook.krailSandookQueries - override val nswStopsQueries = sandook.nswStopsQueries + private val nswStopsQueries = sandook.nswStopsQueries // region Theme override fun insertOrReplaceTheme(productClass: Long) { @@ -146,5 +146,9 @@ internal class RealSandook(factory: SandookDriverFactory) : Sandook { ).executeAsList() } + override fun insertTransaction(block: () -> Unit) { + nswStopsQueries.transaction { block() } + } + // endregion NswStops } diff --git a/sandook/src/commonMain/kotlin/xyz/ksharma/krail/sandook/Sandook.kt b/sandook/src/commonMain/kotlin/xyz/ksharma/krail/sandook/Sandook.kt index 8fc9b87f..4a426481 100644 --- a/sandook/src/commonMain/kotlin/xyz/ksharma/krail/sandook/Sandook.kt +++ b/sandook/src/commonMain/kotlin/xyz/ksharma/krail/sandook/Sandook.kt @@ -2,8 +2,6 @@ package xyz.ksharma.krail.sandook interface Sandook { - val nswStopsQueries: NswStopsQueries - // region Theme fun insertOrReplaceTheme(productClass: Long) fun getProductClass(): Long? @@ -76,5 +74,10 @@ interface Sandook { excludeProductClassList: List = emptyList(), ): List + /** + * Inserts a list of stops in a single transaction. + */ + fun insertTransaction(block: () -> Unit) + // endregion }