feat(server): store and expose last updated date of gtfs data
This commit is contained in:
parent
25e5282ea8
commit
5535034fd7
8 changed files with 430 additions and 2 deletions
|
|
@ -19,6 +19,7 @@ import moe.lava.banksia.Constants
|
||||||
import moe.lava.banksia.di.CommonModules
|
import moe.lava.banksia.di.CommonModules
|
||||||
import moe.lava.banksia.room.dao.RouteDao
|
import moe.lava.banksia.room.dao.RouteDao
|
||||||
import moe.lava.banksia.room.dao.StopDao
|
import moe.lava.banksia.room.dao.StopDao
|
||||||
|
import moe.lava.banksia.room.dao.VersionMetadataDao
|
||||||
import moe.lava.banksia.server.di.ServerModules
|
import moe.lava.banksia.server.di.ServerModules
|
||||||
import moe.lava.banksia.server.gtfs.GtfsHandler
|
import moe.lava.banksia.server.gtfs.GtfsHandler
|
||||||
import moe.lava.banksia.server.gtfsr.GtfsrService
|
import moe.lava.banksia.server.gtfsr.GtfsrService
|
||||||
|
|
@ -61,6 +62,22 @@ fun Application.module() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get("/metadata/{type?}") {
|
||||||
|
val dao by inject<VersionMetadataDao>()
|
||||||
|
val type = call.parameters["type"]
|
||||||
|
if (type == null) {
|
||||||
|
call.respond(dao.getAll().map { it.asModel() })
|
||||||
|
return@get
|
||||||
|
}
|
||||||
|
|
||||||
|
val data = dao.get(type)?.asModel()
|
||||||
|
if (data == null) {
|
||||||
|
call.respond(HttpStatusCode.NotFound)
|
||||||
|
} else {
|
||||||
|
call.respond(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
get("/routes") {
|
get("/routes") {
|
||||||
val routes = withContext(context = Dispatchers.IO) {
|
val routes = withContext(context = Dispatchers.IO) {
|
||||||
inject<RouteDao>().value.getAll()
|
inject<RouteDao>().value.getAll()
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,8 @@ import moe.lava.banksia.server.gtfs.structures.GtfsTrip
|
||||||
import moe.lava.banksia.util.Point
|
import moe.lava.banksia.util.Point
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.zip.ZipFile
|
import java.util.zip.ZipFile
|
||||||
|
import kotlin.time.Clock
|
||||||
|
import kotlin.time.ExperimentalTime
|
||||||
|
|
||||||
class GtfsHandler(
|
class GtfsHandler(
|
||||||
private val log: Logger,
|
private val log: Logger,
|
||||||
|
|
@ -38,7 +40,8 @@ class GtfsHandler(
|
||||||
private val csv = CsvFormat(StringDeferringConfig(EmptySerializersModule()))
|
private val csv = CsvFormat(StringDeferringConfig(EmptySerializersModule()))
|
||||||
private val datasetPath = File("/tmp/banksia", "dataset.zip")
|
private val datasetPath = File("/tmp/banksia", "dataset.zip")
|
||||||
|
|
||||||
suspend fun update(datasetUrl: String) {
|
@OptIn(ExperimentalTime::class)
|
||||||
|
suspend fun update(datasetUrl: String, date: Long? = null) {
|
||||||
val parentDir = datasetPath.parentFile
|
val parentDir = datasetPath.parentFile
|
||||||
@Suppress("SimplifyBooleanWithConstants", "KotlinConstantConditions")
|
@Suppress("SimplifyBooleanWithConstants", "KotlinConstantConditions")
|
||||||
if (parentDir.exists() && !Constants.devMode)
|
if (parentDir.exists() && !Constants.devMode)
|
||||||
|
|
@ -72,6 +75,8 @@ class GtfsHandler(
|
||||||
addTrips(files)
|
addTrips(files)
|
||||||
addStopTimes(files)
|
addStopTimes(files)
|
||||||
|
|
||||||
|
updateMetadata(date ?: Clock.System.now().epochSeconds)
|
||||||
|
|
||||||
@Suppress("KotlinConstantConditions")
|
@Suppress("KotlinConstantConditions")
|
||||||
if (!Constants.devMode) {
|
if (!Constants.devMode) {
|
||||||
parentDir.deleteRecursively()
|
parentDir.deleteRecursively()
|
||||||
|
|
@ -80,6 +85,12 @@ class GtfsHandler(
|
||||||
log.info("done!")
|
log.info("done!")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun updateMetadata(date: Long) {
|
||||||
|
val dao = db.versionMetadataDao
|
||||||
|
log.info("updating metadata...")
|
||||||
|
dao.update(date, listOf("routes", "stops", "shapes", "trips", "stop_times"))
|
||||||
|
}
|
||||||
|
|
||||||
private suspend fun addRoutes(files: List<File>) {
|
private suspend fun addRoutes(files: List<File>) {
|
||||||
val dao = db.routeDao
|
val dao = db.routeDao
|
||||||
log.info("parsing routes...")
|
log.info("parsing routes...")
|
||||||
|
|
|
||||||
339
shared/schemas/moe.lava.banksia.room.Database/3.json
Normal file
339
shared/schemas/moe.lava.banksia.room.Database/3.json
Normal file
|
|
@ -0,0 +1,339 @@
|
||||||
|
{
|
||||||
|
"formatVersion": 1,
|
||||||
|
"database": {
|
||||||
|
"version": 3,
|
||||||
|
"identityHash": "5a7252ab3bcae4d0d0950024b19ba002",
|
||||||
|
"entities": [
|
||||||
|
{
|
||||||
|
"tableName": "Route",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `type` INTEGER NOT NULL, `number` TEXT, `name` TEXT NOT NULL, PRIMARY KEY(`id`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "type",
|
||||||
|
"columnName": "type",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "number",
|
||||||
|
"columnName": "number",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "name",
|
||||||
|
"columnName": "name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "Shape",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `path` BLOB NOT NULL, PRIMARY KEY(`id`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "path",
|
||||||
|
"columnName": "path",
|
||||||
|
"affinity": "BLOB",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "Stop",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL, `lat` REAL NOT NULL, `lng` REAL NOT NULL, `parent` TEXT NOT NULL, `hasWheelChairBoarding` INTEGER NOT NULL, `level` TEXT NOT NULL, `platformCode` TEXT NOT NULL, PRIMARY KEY(`id`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "name",
|
||||||
|
"columnName": "name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lat",
|
||||||
|
"columnName": "lat",
|
||||||
|
"affinity": "REAL",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lng",
|
||||||
|
"columnName": "lng",
|
||||||
|
"affinity": "REAL",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "parent",
|
||||||
|
"columnName": "parent",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "hasWheelChairBoarding",
|
||||||
|
"columnName": "hasWheelChairBoarding",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "level",
|
||||||
|
"columnName": "level",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "platformCode",
|
||||||
|
"columnName": "platformCode",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_Stop_parent",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"parent"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_Stop_parent` ON `${TABLE_NAME}` (`parent`)"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "StopTime",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`tripId` TEXT NOT NULL, `stopId` TEXT NOT NULL, `arrivalTime` INTEGER NOT NULL, `departureTime` INTEGER NOT NULL, `headsign` TEXT, `pickupType` INTEGER NOT NULL, `dropOffType` INTEGER NOT NULL, PRIMARY KEY(`tripId`, `stopId`), FOREIGN KEY(`tripId`) REFERENCES `Trip`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`stopId`) REFERENCES `Stop`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "tripId",
|
||||||
|
"columnName": "tripId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "stopId",
|
||||||
|
"columnName": "stopId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "arrivalTime",
|
||||||
|
"columnName": "arrivalTime",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "departureTime",
|
||||||
|
"columnName": "departureTime",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "headsign",
|
||||||
|
"columnName": "headsign",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "pickupType",
|
||||||
|
"columnName": "pickupType",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "dropOffType",
|
||||||
|
"columnName": "dropOffType",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"tripId",
|
||||||
|
"stopId"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"foreignKeys": [
|
||||||
|
{
|
||||||
|
"table": "Trip",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "NO ACTION",
|
||||||
|
"columns": [
|
||||||
|
"tripId"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"table": "Stop",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "NO ACTION",
|
||||||
|
"columns": [
|
||||||
|
"stopId"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "Trip",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `routeId` TEXT NOT NULL, `serviceId` TEXT NOT NULL, `shapeId` TEXT, `tripHeadsign` TEXT NOT NULL, `directionId` TEXT NOT NULL, `blockId` TEXT NOT NULL, `wheelchairAccessible` TEXT NOT NULL, PRIMARY KEY(`id`), FOREIGN KEY(`routeId`) REFERENCES `Route`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`shapeId`) REFERENCES `Shape`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "routeId",
|
||||||
|
"columnName": "routeId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "serviceId",
|
||||||
|
"columnName": "serviceId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "shapeId",
|
||||||
|
"columnName": "shapeId",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "tripHeadsign",
|
||||||
|
"columnName": "tripHeadsign",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "directionId",
|
||||||
|
"columnName": "directionId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "blockId",
|
||||||
|
"columnName": "blockId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "wheelchairAccessible",
|
||||||
|
"columnName": "wheelchairAccessible",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_Trip_routeId",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"routeId"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_Trip_routeId` ON `${TABLE_NAME}` (`routeId`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": [
|
||||||
|
{
|
||||||
|
"table": "Route",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "NO ACTION",
|
||||||
|
"columns": [
|
||||||
|
"routeId"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"table": "Shape",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "NO ACTION",
|
||||||
|
"columns": [
|
||||||
|
"shapeId"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "VersionMetadata",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`type` TEXT NOT NULL, `lastUpdated` INTEGER NOT NULL, PRIMARY KEY(`type`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "type",
|
||||||
|
"columnName": "type",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lastUpdated",
|
||||||
|
"columnName": "lastUpdated",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"type"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"setupQueries": [
|
||||||
|
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||||
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '5a7252ab3bcae4d0d0950024b19ba002')"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,7 @@ val CommonModules = module {
|
||||||
includes(PlatformModule)
|
includes(PlatformModule)
|
||||||
|
|
||||||
single { Database.build(get<PlatformDatabaseBuilder>().getBuilder()) }
|
single { Database.build(get<PlatformDatabaseBuilder>().getBuilder()) }
|
||||||
|
single { get<Database>().versionMetadataDao }
|
||||||
single { get<Database>().routeDao }
|
single { get<Database>().routeDao }
|
||||||
single { get<Database>().shapeDao }
|
single { get<Database>().shapeDao }
|
||||||
single { get<Database>().stopDao }
|
single { get<Database>().stopDao }
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
package moe.lava.banksia.model
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class VersionMetadata(
|
||||||
|
val type: String,
|
||||||
|
val lastUpdated: Long,
|
||||||
|
)
|
||||||
|
|
@ -7,6 +7,7 @@ import androidx.sqlite.driver.bundled.BundledSQLiteDriver
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.IO
|
import kotlinx.coroutines.IO
|
||||||
import moe.lava.banksia.room.converter.RouteTypeConverter
|
import moe.lava.banksia.room.converter.RouteTypeConverter
|
||||||
|
import moe.lava.banksia.room.dao.VersionMetadataDao
|
||||||
import moe.lava.banksia.room.dao.RouteDao
|
import moe.lava.banksia.room.dao.RouteDao
|
||||||
import moe.lava.banksia.room.dao.ShapeDao
|
import moe.lava.banksia.room.dao.ShapeDao
|
||||||
import moe.lava.banksia.room.dao.StopDao
|
import moe.lava.banksia.room.dao.StopDao
|
||||||
|
|
@ -17,23 +18,27 @@ import moe.lava.banksia.room.entity.ShapeEntity
|
||||||
import moe.lava.banksia.room.entity.StopEntity
|
import moe.lava.banksia.room.entity.StopEntity
|
||||||
import moe.lava.banksia.room.entity.StopTimeEntity
|
import moe.lava.banksia.room.entity.StopTimeEntity
|
||||||
import moe.lava.banksia.room.entity.TripEntity
|
import moe.lava.banksia.room.entity.TripEntity
|
||||||
|
import moe.lava.banksia.room.entity.VersionMetadataEntity
|
||||||
import androidx.room.Database as DatabaseAnnotation
|
import androidx.room.Database as DatabaseAnnotation
|
||||||
|
|
||||||
@DatabaseAnnotation(
|
@DatabaseAnnotation(
|
||||||
version = 2,
|
version = 3,
|
||||||
entities = [
|
entities = [
|
||||||
RouteEntity::class,
|
RouteEntity::class,
|
||||||
ShapeEntity::class,
|
ShapeEntity::class,
|
||||||
StopEntity::class,
|
StopEntity::class,
|
||||||
StopTimeEntity::class,
|
StopTimeEntity::class,
|
||||||
TripEntity::class,
|
TripEntity::class,
|
||||||
|
VersionMetadataEntity::class,
|
||||||
],
|
],
|
||||||
autoMigrations = [
|
autoMigrations = [
|
||||||
AutoMigration(from = 1, to = 2),
|
AutoMigration(from = 1, to = 2),
|
||||||
|
AutoMigration(from = 2, to = 3),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@TypeConverters(RouteTypeConverter::class)
|
@TypeConverters(RouteTypeConverter::class)
|
||||||
abstract class Database : RoomDatabase() {
|
abstract class Database : RoomDatabase() {
|
||||||
|
abstract val versionMetadataDao: VersionMetadataDao
|
||||||
abstract val routeDao: RouteDao
|
abstract val routeDao: RouteDao
|
||||||
abstract val shapeDao: ShapeDao
|
abstract val shapeDao: ShapeDao
|
||||||
abstract val stopDao: StopDao
|
abstract val stopDao: StopDao
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
package moe.lava.banksia.room.dao
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.OnConflictStrategy.Companion.REPLACE
|
||||||
|
import androidx.room.Query
|
||||||
|
import moe.lava.banksia.room.entity.VersionMetadataEntity
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface VersionMetadataDao {
|
||||||
|
@Query("SELECT * FROM VersionMetadata WHERE type == :type")
|
||||||
|
suspend fun get(type: String): VersionMetadataEntity?
|
||||||
|
|
||||||
|
@Query("SELECT * FROM VersionMetadata")
|
||||||
|
suspend fun getAll(): List<VersionMetadataEntity>
|
||||||
|
|
||||||
|
@Insert(onConflict = REPLACE)
|
||||||
|
suspend fun update(vararg data: VersionMetadataEntity)
|
||||||
|
|
||||||
|
suspend fun update(vararg data: Pair<String, Long>) {
|
||||||
|
update(*data.map { (type, lastUpdated) -> VersionMetadataEntity(type, lastUpdated) }.toTypedArray())
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun update(lastUpdated: Long, types: Collection<String>) {
|
||||||
|
update(*types.map { VersionMetadataEntity(it, lastUpdated) }.toTypedArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
package moe.lava.banksia.room.entity
|
||||||
|
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
import moe.lava.banksia.model.VersionMetadata
|
||||||
|
|
||||||
|
@Entity(
|
||||||
|
"VersionMetadata",
|
||||||
|
)
|
||||||
|
data class VersionMetadataEntity(
|
||||||
|
/** Entity type this metadata applies to */
|
||||||
|
@PrimaryKey val type: String,
|
||||||
|
/** Last updated */
|
||||||
|
val lastUpdated: Long,
|
||||||
|
) {
|
||||||
|
fun asModel() = VersionMetadata(type, lastUpdated)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun VersionMetadata.asEntity() = VersionMetadataEntity(type, lastUpdated)
|
||||||
Loading…
Add table
Add a link
Reference in a new issue