perf: add composite index to fix chat session loading latency (fixes #276) (#316)

* perf: add composite index on session_id and timestamp to chat_messages

Fixes a high-severity performance issue (PERF-08) described in issue #276.
A full table scan and in-memory sort were previously performed during each session-switch or cache-load due to a missing index.
By adding a composite index on `(session_id, timestamp)` in the `ChatMessageEntity` and bumping the database version from 1 to 2 with a migration, the query for loading messages now avoids the full table scan, making chat loading latency independent of total message count.

Changes made:
- Added `indices` to `@Entity` in `ChatMessageEntity.kt` for `session_id` and `timestamp`.
- Bumped `version` to 2 in `HermesDatabase.kt`.
- Added explicit migration `MIGRATION_1_2` to create the index if it doesn't exist and added it to `.addMigrations()`.

Fixes #276

* style: fix ktlint formatting errors in HermesDatabase.kt

Fixed `standard:argument-list-wrapping` and `standard:max-line-length` ktlint errors in `app/src/main/java/com/m57/hermescontrol/data/local/HermesDatabase.kt`.
This ensures that the repository meets standard code style guidelines and fixes the GitHub CI build check failures.
This commit is contained in:
M57 authored and GitHub committed 2026-06-23 12:32:48 +03:00
1 parent fe46cb913c
commit 5e93fb2a4e
3 files changed
+102 -3

No files matched your search

@@ -12,7 +12,10 @@ import androidx.room.PrimaryKey
* thread. The [timestamp] field preserves original ordering even if Room
* reorders internally.
*/
@Entity(tableName = "chat_messages")
@Entity(
tableName = "chat_messages",
indices = [androidx.room.Index(value = ["session_id", "timestamp"])],
)
data class ChatMessageEntity(
@PrimaryKey
val id: String,
@@ -4,11 +4,13 @@ import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import com.m57.hermescontrol.BuildConfig
@Database(
entities = [ChatMessageEntity::class],
version = 1,
version = 2,
exportSchema = true,
)
abstract class HermesDatabase : RoomDatabase() {
@@ -18,6 +20,16 @@ abstract class HermesDatabase : RoomDatabase() {
@Volatile
private var instance: HermesDatabase? = null
private val MIGRATION_1_2 =
object : Migration(1, 2) {
override fun migrate(db: SupportSQLiteDatabase) {
db.execSQL(
"CREATE INDEX IF NOT EXISTS `index_chat_messages_session_id_timestamp` " +
"ON `chat_messages` (`session_id`, `timestamp`)",
)
}
}
fun get(context: Context): HermesDatabase =
instance ?: synchronized(this) {
instance ?: Room
@@ -25,7 +37,8 @@ abstract class HermesDatabase : RoomDatabase() {
context.applicationContext,
HermesDatabase::class.java,
"hermes_control.db",
).apply {
).addMigrations(MIGRATION_1_2)
.apply {
if (BuildConfig.DEBUG) {
fallbackToDestructiveMigration(false)
}