refactor(profiles): remove dead registry surface
Delete unused registry members (ProfileConnectionRegistry.insertIfAbsent / removeAllForProfile, ProfileRegistry.reorder, ProfilesView.countFor, ConnectionRegistry.getDefault) and their orphan tests, refreshing the stale docs that named removeAllForProfile as the profile-delete cleanup path. Repair the "one default per profile" join-row invariant: the connectionId FK cascade (foreign_keys=ON) silently drops a profile's default row while its other rows survive, leaving it defaultless. Add promoteMissingDefaults, share a deterministic re-promotion helper with remove(), and re-promote in removeAllForConnection.
This commit is contained in:
@@ -118,13 +118,6 @@ class ProfileConnectionRegistry {
|
||||
);
|
||||
}
|
||||
|
||||
/// Insert a new join row only if `(profileId, connectionId)` doesn't
|
||||
/// already exist. Used by [ProfileSyncService] to surface new Plex Home
|
||||
/// users without clobbering tokens cached by prior switches.
|
||||
Future<void> insertIfAbsent(ProfileConnection pc) async {
|
||||
await _db.into(_db.profileConnections).insert(await _companion(pc), mode: InsertMode.insertOrIgnore);
|
||||
}
|
||||
|
||||
/// Cache the freshly-acquired user token (e.g. after a `/home/users/switch`
|
||||
/// call). Updates `tokenAcquiredAt` to now.
|
||||
Future<void> recordToken(String profileId, String connectionId, String token) async {
|
||||
@@ -149,12 +142,30 @@ class ProfileConnectionRegistry {
|
||||
await (_db.delete(
|
||||
_db.profileConnections,
|
||||
)..where((t) => t.profileId.equals(profileId) & t.connectionId.equals(connectionId))).go();
|
||||
// If we just removed the default, promote the oldest remaining row.
|
||||
final remaining = await (_db.select(_db.profileConnections)..where((t) => t.profileId.equals(profileId))).get();
|
||||
if (remaining.isNotEmpty && !remaining.any((r) => r.isDefault)) {
|
||||
await (_db.update(_db.profileConnections)
|
||||
..where((t) => t.profileId.equals(profileId) & t.connectionId.equals(remaining.first.connectionId)))
|
||||
.write(const ProfileConnectionsCompanion(isDefault: Value(true)));
|
||||
await _promoteDefaultIfMissing(profileId);
|
||||
}
|
||||
|
||||
/// Re-promote a default for [profileId] when it has join rows but none is
|
||||
/// flagged default — removing the default row would otherwise leave the
|
||||
/// profile defaultless. Deterministic: picks the lowest connectionId,
|
||||
/// matching [listForProfile]'s secondary ordering.
|
||||
Future<void> _promoteDefaultIfMissing(String profileId) async {
|
||||
final rows = await (_db.select(_db.profileConnections)..where((t) => t.profileId.equals(profileId))).get();
|
||||
if (rows.isEmpty || rows.any((r) => r.isDefault)) return;
|
||||
final pick = rows.map((r) => r.connectionId).reduce((a, b) => a.compareTo(b) <= 0 ? a : b);
|
||||
await (_db.update(_db.profileConnections)
|
||||
..where((t) => t.profileId.equals(profileId) & t.connectionId.equals(pick)))
|
||||
.write(const ProfileConnectionsCompanion(isDefault: Value(true)));
|
||||
}
|
||||
|
||||
/// Repair the "exactly one default per profile" invariant across every
|
||||
/// profile. The `connectionId` FK cascade (PRAGMA foreign_keys=ON) deletes
|
||||
/// join rows silently when a Connection is removed, so a profile can be left
|
||||
/// with surviving rows but no default flag.
|
||||
Future<void> promoteMissingDefaults() async {
|
||||
final profileIds = (await _db.select(_db.profileConnections).get()).map((r) => r.profileId).toSet();
|
||||
for (final profileId in profileIds) {
|
||||
await _promoteDefaultIfMissing(profileId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,16 +183,14 @@ class ProfileConnectionRegistry {
|
||||
}
|
||||
|
||||
/// Remove every join row referencing [connectionId] (e.g. when a Connection
|
||||
/// is deleted). Drift's referential integrity isn't enabled by default for
|
||||
/// SQLite without `PRAGMA foreign_keys=ON`, so we cascade explicitly.
|
||||
/// is deleted). The `connectionId` FK (PRAGMA foreign_keys=ON) already
|
||||
/// cascades these rows away when the Connection row itself is deleted; this
|
||||
/// stays the explicit path for callers that drop the rows first, and either
|
||||
/// way repairs any profile the removal left without a default.
|
||||
Future<int> removeAllForConnection(String connectionId) async {
|
||||
return await (_db.delete(_db.profileConnections)..where((t) => t.connectionId.equals(connectionId))).go();
|
||||
}
|
||||
|
||||
/// Wipe every join row for [profileId] (e.g. when a Plex Home profile's
|
||||
/// parent connection is removed).
|
||||
Future<int> removeAllForProfile(String profileId) async {
|
||||
return await (_db.delete(_db.profileConnections)..where((t) => t.profileId.equals(profileId))).go();
|
||||
final removed = await (_db.delete(_db.profileConnections)..where((t) => t.connectionId.equals(connectionId))).go();
|
||||
await promoteMissingDefaults();
|
||||
return removed;
|
||||
}
|
||||
|
||||
/// Wipe the entire join table. Used by sign-out so a fresh sign-in starts
|
||||
|
||||
Reference in New Issue
Block a user