perf: activity_log autoGenerate id (#704)

This commit is contained in:
lisonge 2024-08-16 11:01:34 +08:00
parent b78660d60c
commit 6f366f04ae
3 changed files with 372 additions and 13 deletions

View File

@ -0,0 +1,347 @@
{
"formatVersion": 1,
"database": {
"version": 8,
"identityHash": "409bb51310bcdb55ea721a8e88b6cef6",
"entities": [
{
"tableName": "subs_item",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `ctime` INTEGER NOT NULL, `mtime` INTEGER NOT NULL, `enable` INTEGER NOT NULL, `enable_update` INTEGER NOT NULL, `order` INTEGER NOT NULL, `update_url` TEXT, PRIMARY KEY(`id`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "ctime",
"columnName": "ctime",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "mtime",
"columnName": "mtime",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "enable",
"columnName": "enable",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "enableUpdate",
"columnName": "enable_update",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "order",
"columnName": "order",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "updateUrl",
"columnName": "update_url",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"id"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "snapshot",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `app_id` TEXT, `activity_id` TEXT, `app_name` TEXT, `app_version_code` INTEGER, `app_version_name` TEXT, `screen_height` INTEGER NOT NULL, `screen_width` INTEGER NOT NULL, `is_landscape` INTEGER NOT NULL, `github_asset_id` INTEGER, PRIMARY KEY(`id`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "appId",
"columnName": "app_id",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "activityId",
"columnName": "activity_id",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "appName",
"columnName": "app_name",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "appVersionCode",
"columnName": "app_version_code",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "appVersionName",
"columnName": "app_version_name",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "screenHeight",
"columnName": "screen_height",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "screenWidth",
"columnName": "screen_width",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "isLandscape",
"columnName": "is_landscape",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "githubAssetId",
"columnName": "github_asset_id",
"affinity": "INTEGER",
"notNull": false
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"id"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "subs_config",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `type` INTEGER NOT NULL, `enable` INTEGER, `subs_item_id` INTEGER NOT NULL, `app_id` TEXT NOT NULL, `group_key` INTEGER NOT NULL, `exclude` TEXT NOT NULL DEFAULT '', PRIMARY KEY(`id`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "type",
"columnName": "type",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "enable",
"columnName": "enable",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "subsItemId",
"columnName": "subs_item_id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "appId",
"columnName": "app_id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "groupKey",
"columnName": "group_key",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "exclude",
"columnName": "exclude",
"affinity": "TEXT",
"notNull": true,
"defaultValue": "''"
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"id"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "click_log",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `app_id` TEXT, `activity_id` TEXT, `subs_id` INTEGER NOT NULL, `subs_version` INTEGER NOT NULL DEFAULT 0, `group_key` INTEGER NOT NULL, `group_type` INTEGER NOT NULL DEFAULT 2, `rule_index` INTEGER NOT NULL, `rule_key` INTEGER, PRIMARY KEY(`id`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "appId",
"columnName": "app_id",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "activityId",
"columnName": "activity_id",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "subsId",
"columnName": "subs_id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "subsVersion",
"columnName": "subs_version",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "0"
},
{
"fieldPath": "groupKey",
"columnName": "group_key",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "groupType",
"columnName": "group_type",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "2"
},
{
"fieldPath": "ruleIndex",
"columnName": "rule_index",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "ruleKey",
"columnName": "rule_key",
"affinity": "INTEGER",
"notNull": false
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"id"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "category_config",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `enable` INTEGER, `subs_item_id` INTEGER NOT NULL, `category_key` INTEGER NOT NULL, PRIMARY KEY(`id`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "enable",
"columnName": "enable",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "subsItemId",
"columnName": "subs_item_id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "categoryKey",
"columnName": "category_key",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"id"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "activity_log_v2",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `ctime` INTEGER NOT NULL, `app_id` TEXT NOT NULL, `activity_id` TEXT)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "ctime",
"columnName": "ctime",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "appId",
"columnName": "app_id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "activityId",
"columnName": "activity_id",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
},
"indices": [],
"foreignKeys": []
}
],
"views": [],
"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, '409bb51310bcdb55ea721a8e88b6cef6')"
]
}
}

View File

@ -3,18 +3,23 @@ package li.songe.gkd.data
import androidx.paging.PagingSource import androidx.paging.PagingSource
import androidx.room.ColumnInfo import androidx.room.ColumnInfo
import androidx.room.Dao import androidx.room.Dao
import androidx.room.DeleteTable
import androidx.room.Entity import androidx.room.Entity
import androidx.room.Insert import androidx.room.Insert
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
import androidx.room.Query import androidx.room.Query
import androidx.room.migration.AutoMigrationSpec
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import li.songe.gkd.util.format import li.songe.gkd.util.format
@Entity( @Entity(
tableName = "activity_log", tableName = "activity_log_v2",
) )
data class ActivityLog( data class ActivityLog(
@PrimaryKey @ColumnInfo(name = "id") val id: Long = System.currentTimeMillis(), // 不使用时间戳作为主键的原因
// https://github.com/gkd-kit/gkd/issues/704
@PrimaryKey(autoGenerate = true) @ColumnInfo(name = "id") val id: Int = 0,
@ColumnInfo(name = "ctime") val ctime: Long = System.currentTimeMillis(),
@ColumnInfo(name = "app_id") val appId: String, @ColumnInfo(name = "app_id") val appId: String,
@ColumnInfo(name = "activity_id") val activityId: String? = null, @ColumnInfo(name = "activity_id") val activityId: String? = null,
) { ) {
@ -32,37 +37,43 @@ data class ActivityLog(
null null
} }
} }
val date by lazy { id.format("MM-dd HH:mm:ss SSS") } val date by lazy { ctime.format("MM-dd HH:mm:ss SSS") }
@Dao @Dao
interface ActivityLogDao { interface ActivityLogDao {
@Insert @Insert
suspend fun insert(vararg objects: ActivityLog): List<Long> suspend fun insert(vararg objects: ActivityLog): List<Long>
@Query("DELETE FROM activity_log") @Query("DELETE FROM activity_log_v2")
suspend fun deleteAll() suspend fun deleteAll()
@Query("SELECT * FROM activity_log ORDER BY id DESC ") @Query("SELECT * FROM activity_log_v2 ORDER BY ctime DESC ")
fun pagingSource(): PagingSource<Int, ActivityLog> fun pagingSource(): PagingSource<Int, ActivityLog>
@Query("SELECT COUNT(*) FROM activity_log") @Query("SELECT COUNT(*) FROM activity_log_v2")
fun count(): Flow<Int> fun count(): Flow<Int>
@Query( @Query(
""" """
DELETE FROM activity_log DELETE FROM activity_log_v2
WHERE ( WHERE (
SELECT COUNT(*) SELECT COUNT(*)
FROM activity_log FROM activity_log_v2
) > 1000 ) > 1000
AND id <= ( AND ctime <= (
SELECT id SELECT ctime
FROM activity_log FROM activity_log_v2
ORDER BY id DESC ORDER BY ctime DESC
LIMIT 1 OFFSET 1000 LIMIT 1 OFFSET 1000
) )
""" """
) )
suspend fun deleteKeepLatest(): Int suspend fun deleteKeepLatest(): Int
} }
@DeleteTable.Entries(
DeleteTable(tableName = "activity_log")
)
class ActivityLogV2Spec : AutoMigrationSpec
} }

View File

@ -11,7 +11,7 @@ import li.songe.gkd.data.SubsConfig
import li.songe.gkd.data.SubsItem import li.songe.gkd.data.SubsItem
@Database( @Database(
version = 7, version = 8,
entities = [ entities = [
SubsItem::class, SubsItem::class,
Snapshot::class, Snapshot::class,
@ -27,6 +27,7 @@ import li.songe.gkd.data.SubsItem
AutoMigration(from = 4, to = 5), AutoMigration(from = 4, to = 5),
AutoMigration(from = 5, to = 6), AutoMigration(from = 5, to = 6),
AutoMigration(from = 6, to = 7), AutoMigration(from = 6, to = 7),
AutoMigration(from = 7, to = 8, spec = ActivityLog.ActivityLogV2Spec::class),
] ]
) )
abstract class AppDb : RoomDatabase() { abstract class AppDb : RoomDatabase() {