mirror of
https://github.com/immich-app/immich.git
synced 2026-06-23 15:16:42 -07:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1ee679f832 |
@@ -280,8 +280,7 @@ class SyncStreamService {
|
||||
return;
|
||||
// SyncCompleteV1 is used to signal the completion of the sync process. Cleanup stale assets and signal completion
|
||||
case SyncEntityType.syncCompleteV1:
|
||||
return;
|
||||
// return _syncStreamRepository.pruneAssets();
|
||||
return _syncStreamRepository.pruneAssets();
|
||||
// Request to reset the client state. Clear everything related to remote entities
|
||||
case SyncEntityType.syncResetV1:
|
||||
return _syncStreamRepository.reset();
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/sync_stream.repository.dart';
|
||||
|
||||
import '../repository_context.dart';
|
||||
|
||||
void main() {
|
||||
late MediumRepositoryContext ctx;
|
||||
late SyncStreamRepository sut;
|
||||
|
||||
setUp(() {
|
||||
ctx = MediumRepositoryContext();
|
||||
sut = SyncStreamRepository(ctx.db);
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await ctx.dispose();
|
||||
});
|
||||
|
||||
group('pruneAssets', () {
|
||||
test('deletes foreign orphans and keeps owned, partner, and in-album assets', () async {
|
||||
final me = await ctx.newUser();
|
||||
final partner = await ctx.newUser();
|
||||
final stranger = await ctx.newUser();
|
||||
await ctx.newAuthUser(id: me.id);
|
||||
await ctx.newPartner(sharedById: partner.id, sharedWithId: me.id);
|
||||
|
||||
final own = await ctx.newRemoteAsset(ownerId: me.id);
|
||||
final fromPartner = await ctx.newRemoteAsset(ownerId: partner.id);
|
||||
final shared = await ctx.newRemoteAsset(ownerId: stranger.id);
|
||||
await ctx.newRemoteAsset(ownerId: stranger.id);
|
||||
|
||||
final album = await ctx.newRemoteAlbum(ownerId: me.id);
|
||||
await ctx.newRemoteAlbumAsset(albumId: album.id, assetId: shared.id);
|
||||
|
||||
await sut.pruneAssets();
|
||||
|
||||
final remaining = await ctx.db.select(ctx.db.remoteAssetEntity).get();
|
||||
expect(remaining.map((a) => a.id), unorderedEquals([own.id, fromPartner.id, shared.id]));
|
||||
});
|
||||
|
||||
test('does nothing when there is no authenticated user', () async {
|
||||
final stranger = await ctx.newUser();
|
||||
final orphan = await ctx.newRemoteAsset(ownerId: stranger.id);
|
||||
|
||||
await sut.pruneAssets();
|
||||
|
||||
final remaining = await ctx.db.select(ctx.db.remoteAssetEntity).get();
|
||||
expect(remaining.map((a) => a.id), [orphan.id]);
|
||||
});
|
||||
|
||||
test('prunes every stale foreign asset in a large data set', () async {
|
||||
final stranger = await ctx.newUser();
|
||||
await ctx.newAuthUser();
|
||||
for (var i = 0; i < 600; i++) {
|
||||
await ctx.newRemoteAsset(ownerId: stranger.id);
|
||||
}
|
||||
|
||||
await sut.pruneAssets();
|
||||
|
||||
final remaining = await ctx.db.select(ctx.db.remoteAssetEntity).get();
|
||||
expect(remaining, isEmpty);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/domain/models/memory.model.dart';
|
||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/asset_face.entity.drift.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/auth_user.entity.drift.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/local_album.entity.drift.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/local_album_asset.entity.drift.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/local_asset.entity.drift.dart';
|
||||
@@ -72,6 +73,20 @@ class MediumRepositoryContext {
|
||||
);
|
||||
}
|
||||
|
||||
Future<AuthUserEntityData> newAuthUser({String? id, String? email, AvatarColor? avatarColor}) async {
|
||||
id ??= TestUtils.uuid();
|
||||
return await db
|
||||
.into(db.authUserEntity)
|
||||
.insertReturning(
|
||||
AuthUserEntityCompanion(
|
||||
id: .new(id),
|
||||
email: .new(email ?? '$id@test.com'),
|
||||
name: .new('user_$id'),
|
||||
avatarColor: .new(avatarColor ?? TestUtils.randElement(AvatarColor.values)),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> newPartner({required String sharedById, required String sharedWithId, bool? inTimeline}) {
|
||||
return db
|
||||
.into(db.partnerEntity)
|
||||
|
||||
Reference in New Issue
Block a user