fix: prune stale assets

This commit is contained in:
shenlong-tanwen 2025-10-01 13:20:03 +05:30
parent 00ce6354f0
commit 2f1ec5b724
2 changed files with 36 additions and 2 deletions

View file

@ -130,9 +130,9 @@ class SyncStreamService {
// to acknowledge that the client has processed all the backfill events // to acknowledge that the client has processed all the backfill events
case SyncEntityType.syncAckV1: case SyncEntityType.syncAckV1:
return; return;
// No-op. SyncCompleteV1 is used to signal the completion of the sync process // SyncCompleteV1 is used to signal the completion of the sync process. Cleanup stale assets and signal completion
case SyncEntityType.syncCompleteV1: case SyncEntityType.syncCompleteV1:
return; return _syncStreamRepository.pruneAssets();
// Request to reset the client state. Clear everything related to remote entities // Request to reset the client state. Clear everything related to remote entities
case SyncEntityType.syncResetV1: case SyncEntityType.syncResetV1:
return _syncStreamRepository.reset(); return _syncStreamRepository.reset();

View file

@ -591,6 +591,40 @@ class SyncStreamRepository extends DriftDatabaseRepository {
rethrow; rethrow;
} }
} }
Future<void> pruneAssets() async {
try {
await _db.transaction(() async {
final authQuery = _db.authUserEntity.selectOnly()
..addColumns([_db.authUserEntity.id])
..limit(1);
final currentUserId = await authQuery.map((row) => row.read(_db.authUserEntity.id)).getSingleOrNull();
if (currentUserId == null) {
_logger.warning('No authenticated user found during pruneAssets. Skipping asset pruning.');
return;
}
final partnerQuery = _db.partnerEntity.selectOnly()
..addColumns([_db.partnerEntity.sharedById])
..where(_db.partnerEntity.sharedWithId.equals(currentUserId));
final partnerIds = await partnerQuery.map((row) => row.read(_db.partnerEntity.sharedById)).get();
final validUsers = {currentUserId, ...partnerIds.nonNulls};
// Asset is not owned by the current user or any of their partners and is not part of any (shared) album
// Likely a stale asset that was previously shared but has been removed
await _db.remoteAssetEntity.deleteWhere((asset) {
return asset.ownerId.isNotIn(validUsers) &
asset.id.isNotInQuery(
_db.remoteAlbumAssetEntity.selectOnly()..addColumns([_db.remoteAlbumAssetEntity.assetId]),
);
});
});
} catch (error, stack) {
_logger.severe('Error: pruneAssets', error, stack);
// We do not rethrow here as this is a client-only cleanup and should not affect the sync process
}
}
} }
extension on AssetTypeEnum { extension on AssetTypeEnum {