From 19753ca0052b212c0e24da292ffb2ea858c7aedd Mon Sep 17 00:00:00 2001 From: zarzet Date: Sat, 1 Aug 2026 17:39:45 +0700 Subject: [PATCH] fix(database): make playback session migration idempotent --- lib/services/app_state_database.dart | 5 ++++- test/models_and_utils_test.dart | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/lib/services/app_state_database.dart b/lib/services/app_state_database.dart index 054f96ac..d16978c1 100644 --- a/lib/services/app_state_database.dart +++ b/lib/services/app_state_database.dart @@ -103,8 +103,11 @@ class AppStateDatabase { } static Future _createPlaybackSessionTable(Database db) { + // Keep this idempotent so an interrupted migration or a database restored + // from an intermediate build can resume v1 -> v2 without losing queue + // state merely because the table was already created. return db.execute(''' - CREATE TABLE $_playbackSessionTable ( + CREATE TABLE IF NOT EXISTS $_playbackSessionTable ( id INTEGER PRIMARY KEY CHECK (id = 1), session_json TEXT NOT NULL, updated_at TEXT NOT NULL diff --git a/test/models_and_utils_test.dart b/test/models_and_utils_test.dart index a8c570a9..72fd3aa7 100644 --- a/test/models_and_utils_test.dart +++ b/test/models_and_utils_test.dart @@ -139,6 +139,26 @@ void main() { }); }); + group('app state database migrations', () { + final source = File( + 'lib/services/app_state_database.dart', + ).readAsStringSync(); + + test('v1 to v2 tolerates an existing playback session table', () { + expect( + source, + contains('CREATE TABLE IF NOT EXISTS \$_playbackSessionTable'), + ); + expect( + RegExp( + r'if \(oldVersion < 2\)\s*\{\s*' + r'await _createPlaybackSessionTable\(db\);', + ).hasMatch(source), + isTrue, + ); + }); + }); + group('native worker contracts', () { final finalizerSource = File( 'android/app/src/main/kotlin/com/zarz/spotiflac/'