fix(database): restore api_cache.cached_at read by the playback freshness gate

Main stopped compiling: the v21 column drop treated cached_at as
never-read, but the fresh-cache-first playback metadata gate
(ApiCacheSingleton.getIfFresh, from the playback start-latency fix)
reads it on every Plex and Jellyfin playback start, and a later
cleanup removed the put() stamp the gate depends on.

Reinstate the column, keep the v21 migration to the connections
half only (it never shipped in a release), restore the explicit
put() timestamp - on conflict the upsert only updates the
companion's columns, so without it a refreshed row would keep its
original write time and read as permanently stale - and copy
cached_at through the pinned-metadata rescope statement again. The
v21 migration test now pins that api_cache is left untouched.
This commit is contained in:
edde746
2026-08-17 20:47:40 +02:00
parent 86498547ba
commit efd33b3a4e
5 changed files with 107 additions and 21 deletions
+9 -7
View File
@@ -926,7 +926,7 @@ class _AppDatabaseTestSuite {
db = AppDatabase.forTesting(NativeDatabase.memory());
}
});
test('v21 migration drops connections.is_default and api_cache.cached_at without losing rows', () async {
test('v21 migration drops connections.is_default without touching api_cache.cached_at', () async {
await db.close();
final tempDir = await Directory.systemTemp.createTemp('plezy_db_v21_migration_test_');
final file = File('${tempDir.path}/plezy_downloads.db');
@@ -947,12 +947,11 @@ class _AppDatabaseTestSuite {
createdAt: 1000,
),
);
await seeded.customStatement('INSERT INTO api_cache (cache_key, data, pinned) VALUES (?, ?, 1)', [
'srv:/library/metadata/1',
'{}',
]);
await seeded.customStatement(
'INSERT INTO api_cache (cache_key, data, pinned, cached_at) VALUES (?, ?, 1, 12345)',
['srv:/library/metadata/1', '{}'],
);
await seeded.customStatement('ALTER TABLE connections ADD COLUMN is_default INTEGER NOT NULL DEFAULT 1');
await seeded.customStatement('ALTER TABLE api_cache ADD COLUMN cached_at INTEGER NOT NULL DEFAULT 0');
await seeded.customStatement('PRAGMA user_version = 20');
await seeded.close();
seeded = null;
@@ -965,7 +964,9 @@ class _AppDatabaseTestSuite {
.map((row) => row.read<String>('name'))
.toSet();
expect(connectionColumns, isNot(contains('is_default')));
expect(cacheColumns, isNot(contains('cached_at')));
// cached_at is load-bearing (ApiCacheSingleton.getIfFresh); the
// migration must leave it, and its values, alone.
expect(cacheColumns, contains('cached_at'));
final connection = await reopened.select(reopened.connections).getSingle();
expect(connection.id, 'c1');
@@ -973,6 +974,7 @@ class _AppDatabaseTestSuite {
final cacheRow = await reopened.select(reopened.apiCache).getSingle();
expect(cacheRow.cacheKey, 'srv:/library/metadata/1');
expect(cacheRow.pinned, isTrue);
expect(cacheRow.cachedAt.millisecondsSinceEpoch ~/ 1000, 12345);
// The drift table recreation must restore the kind index.
final indexRows = await reopened