mirror of
https://github.com/immich-app/immich
synced 2025-11-14 17:36:12 +00:00
reuse exist checksums on trash data update
handle restoration errors fix import
This commit is contained in:
parent
172102c438
commit
44ec7744ba
3 changed files with 34 additions and 10 deletions
|
|
@ -300,7 +300,6 @@ class LocalSyncService {
|
||||||
return Future.value();
|
return Future.value();
|
||||||
}
|
}
|
||||||
final trashedAssets = <TrashedAsset>[];
|
final trashedAssets = <TrashedAsset>[];
|
||||||
//todo try to reuse exist checksums from local assets table before they updated
|
|
||||||
for (final update in trashUpdates) {
|
for (final update in trashUpdates) {
|
||||||
final albums = delta.assetAlbums.cast<String, List<Object?>>();
|
final albums = delta.assetAlbums.cast<String, List<Object?>>();
|
||||||
for (final String id in albums[update.id]!.cast<String?>().nonNulls) {
|
for (final String id in albums[update.id]!.cast<String?>().nonNulls) {
|
||||||
|
|
@ -329,13 +328,19 @@ class LocalSyncService {
|
||||||
|
|
||||||
Future<void> _applyRemoteRestoreToLocal() async {
|
Future<void> _applyRemoteRestoreToLocal() async {
|
||||||
final remoteAssetsToRestore = await _trashedLocalAssetRepository.getToRestore();
|
final remoteAssetsToRestore = await _trashedLocalAssetRepository.getToRestore();
|
||||||
|
final toRestoreIds = <String>[];
|
||||||
if (remoteAssetsToRestore.isNotEmpty) {
|
if (remoteAssetsToRestore.isNotEmpty) {
|
||||||
_log.info("remoteAssetsToRestore: $remoteAssetsToRestore");
|
_log.info("remoteAssetsToRestore: $remoteAssetsToRestore");
|
||||||
for (final asset in remoteAssetsToRestore) {
|
for (final asset in remoteAssetsToRestore) {
|
||||||
_log.info("Restoring from trash, localId: ${asset.id}, remoteId: ${asset.checksum}");
|
_log.info("Restoring from trash, localId: ${asset.id}, remoteId: ${asset.checksum}");
|
||||||
|
try {
|
||||||
await _localFilesManager.restoreFromTrashById(asset.id, asset.type.index);
|
await _localFilesManager.restoreFromTrashById(asset.id, asset.type.index);
|
||||||
|
toRestoreIds.add(asset.id);
|
||||||
|
} catch (e) {
|
||||||
|
_log.warning("Restoring failure: $e");
|
||||||
}
|
}
|
||||||
await _trashedLocalAssetRepository.restoreLocalAssets(remoteAssetsToRestore.map((e) => e.id));
|
}
|
||||||
|
await _trashedLocalAssetRepository.restoreLocalAssets(toRestoreIds);
|
||||||
} else {
|
} else {
|
||||||
_log.info("No remote assets found for restoration");
|
_log.info("No remote assets found for restoration");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,14 +63,15 @@ class DriftTrashedLocalAssetRepository extends DriftDatabaseRepository {
|
||||||
await _db.delete(_db.trashedLocalAssetEntity).go();
|
await _db.delete(_db.trashedLocalAssetEntity).go();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Map<String, String> localChecksumById = await _getCachedChecksums(assets);
|
||||||
return _db.transaction(() async {
|
return _db.transaction(() async {
|
||||||
await _db.batch((batch) {
|
await _db.batch((batch) {
|
||||||
for (final asset in assets) {
|
for (final asset in assets) {
|
||||||
|
final effectiveChecksum = localChecksumById[asset.id] ?? asset.checksum;
|
||||||
final companion = TrashedLocalAssetEntityCompanion.insert(
|
final companion = TrashedLocalAssetEntityCompanion.insert(
|
||||||
id: asset.id,
|
id: asset.id,
|
||||||
albumId: albumId,
|
albumId: albumId,
|
||||||
checksum: asset.checksum == null ? const Value.absent() : Value(asset.checksum),
|
checksum: effectiveChecksum == null ? const Value.absent() : Value(effectiveChecksum),
|
||||||
name: asset.name,
|
name: asset.name,
|
||||||
type: asset.type,
|
type: asset.type,
|
||||||
createdAt: Value(asset.createdAt),
|
createdAt: Value(asset.createdAt),
|
||||||
|
|
@ -109,19 +110,22 @@ class DriftTrashedLocalAssetRepository extends DriftDatabaseRepository {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> saveTrashedAssets(Iterable<TrashedAsset> trashUpdates) async {
|
Future<void> saveTrashedAssets(Iterable<TrashedAsset> assets) async {
|
||||||
if (trashUpdates.isEmpty) {
|
if (assets.isEmpty) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Map<String, String> localChecksumById = await _getCachedChecksums(assets);
|
||||||
|
|
||||||
await _db.batch((batch) {
|
await _db.batch((batch) {
|
||||||
for (final asset in trashUpdates) {
|
for (final asset in assets) {
|
||||||
|
final effectiveChecksum = localChecksumById[asset.id] ?? asset.checksum;
|
||||||
final companion = TrashedLocalAssetEntityCompanion.insert(
|
final companion = TrashedLocalAssetEntityCompanion.insert(
|
||||||
id: asset.id,
|
id: asset.id,
|
||||||
albumId: asset.albumId,
|
albumId: asset.albumId,
|
||||||
name: asset.name,
|
name: asset.name,
|
||||||
type: asset.type,
|
type: asset.type,
|
||||||
checksum: asset.checksum == null ? const Value.absent() : Value(asset.checksum),
|
checksum: effectiveChecksum == null ? const Value.absent() : Value(effectiveChecksum),
|
||||||
createdAt: Value(asset.createdAt),
|
createdAt: Value(asset.createdAt),
|
||||||
width: Value(asset.width),
|
width: Value(asset.width),
|
||||||
height: Value(asset.height),
|
height: Value(asset.height),
|
||||||
|
|
@ -175,6 +179,8 @@ class DriftTrashedLocalAssetRepository extends DriftDatabaseRepository {
|
||||||
durationInSeconds: Value(asset.durationInSeconds),
|
durationInSeconds: Value(asset.durationInSeconds),
|
||||||
isFavorite: Value(asset.isFavorite),
|
isFavorite: Value(asset.isFavorite),
|
||||||
orientation: Value(asset.orientation),
|
orientation: Value(asset.orientation),
|
||||||
|
createdAt: Value(asset.createdAt),
|
||||||
|
updatedAt: Value(asset.updatedAt),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -229,4 +235,18 @@ class DriftTrashedLocalAssetRepository extends DriftDatabaseRepository {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//attempt to reuse existing checksums
|
||||||
|
Future<Map<String, String>> _getCachedChecksums(Iterable<TrashedAsset> trashUpdates) async {
|
||||||
|
final ids = trashUpdates.map((e) => e.id).toSet();
|
||||||
|
final rows = await (_db.selectOnly(_db.localAssetEntity)
|
||||||
|
..where(_db.localAssetEntity.id.isIn(ids) & _db.localAssetEntity.checksum.isNotNull())
|
||||||
|
..addColumns([_db.localAssetEntity.id, _db.localAssetEntity.checksum]))
|
||||||
|
.get();
|
||||||
|
|
||||||
|
final localChecksumById = {
|
||||||
|
for (final r in rows) r.read(_db.localAssetEntity.id)!: r.read(_db.localAssetEntity.checksum)!
|
||||||
|
};
|
||||||
|
return localChecksumById;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1
mobile/test/fixtures/asset.stub.dart
vendored
1
mobile/test/fixtures/asset.stub.dart
vendored
|
|
@ -1,5 +1,4 @@
|
||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/asset/trashed_asset.model.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/exif.model.dart';
|
import 'package:immich_mobile/domain/models/exif.model.dart';
|
||||||
import 'package:immich_mobile/entities/asset.entity.dart' as old;
|
import 'package:immich_mobile/entities/asset.entity.dart' as old;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue