mirror of
https://github.com/immich-app/immich
synced 2025-11-07 17:27:20 +00:00
refactor(trash-sync): optimize performance and fix minor issues
This commit is contained in:
parent
5582a08c3a
commit
d47a2b5669
7 changed files with 44 additions and 24 deletions
2
mobile/drift_schemas/main/drift_schema_v13.json
generated
2
mobile/drift_schemas/main/drift_schema_v13.json
generated
File diff suppressed because one or more lines are too long
|
|
@ -5,6 +5,7 @@ import 'package:immich_mobile/infrastructure/utils/asset.mixin.dart';
|
||||||
import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
|
import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
|
||||||
|
|
||||||
@TableIndex.sql('CREATE INDEX IF NOT EXISTS idx_trashed_local_asset_checksum ON trashed_local_asset_entity (checksum)')
|
@TableIndex.sql('CREATE INDEX IF NOT EXISTS idx_trashed_local_asset_checksum ON trashed_local_asset_entity (checksum)')
|
||||||
|
@TableIndex.sql('CREATE INDEX IF NOT EXISTS idx_trashed_local_asset_album ON trashed_local_asset_entity (album_id)')
|
||||||
class TrashedLocalAssetEntity extends Table with DriftDefaultsMixin, AssetEntityMixin {
|
class TrashedLocalAssetEntity extends Table with DriftDefaultsMixin, AssetEntityMixin {
|
||||||
const TrashedLocalAssetEntity();
|
const TrashedLocalAssetEntity();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1073,3 +1073,8 @@ class TrashedLocalAssetEntityCompanion
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i0.Index get idxTrashedLocalAssetAlbum => i0.Index(
|
||||||
|
'idx_trashed_local_asset_album',
|
||||||
|
'CREATE INDEX IF NOT EXISTS idx_trashed_local_asset_album ON trashed_local_asset_entity (album_id)',
|
||||||
|
);
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,7 @@ abstract class $Drift extends i0.GeneratedDatabase {
|
||||||
trashedLocalAssetEntity,
|
trashedLocalAssetEntity,
|
||||||
i11.idxLatLng,
|
i11.idxLatLng,
|
||||||
i19.idxTrashedLocalAssetChecksum,
|
i19.idxTrashedLocalAssetChecksum,
|
||||||
|
i19.idxTrashedLocalAssetAlbum,
|
||||||
];
|
];
|
||||||
@override
|
@override
|
||||||
i0.StreamQueryUpdateRules
|
i0.StreamQueryUpdateRules
|
||||||
|
|
|
||||||
|
|
@ -5067,6 +5067,7 @@ final class Schema13 extends i0.VersionedSchema {
|
||||||
trashedLocalAssetEntity,
|
trashedLocalAssetEntity,
|
||||||
idxLatLng,
|
idxLatLng,
|
||||||
idxTrashedLocalAssetChecksum,
|
idxTrashedLocalAssetChecksum,
|
||||||
|
idxTrashedLocalAssetAlbum,
|
||||||
];
|
];
|
||||||
late final Shape20 userEntity = Shape20(
|
late final Shape20 userEntity = Shape20(
|
||||||
source: i0.VersionedTable(
|
source: i0.VersionedTable(
|
||||||
|
|
@ -5443,6 +5444,10 @@ final class Schema13 extends i0.VersionedSchema {
|
||||||
'idx_trashed_local_asset_checksum',
|
'idx_trashed_local_asset_checksum',
|
||||||
'CREATE INDEX IF NOT EXISTS idx_trashed_local_asset_checksum ON trashed_local_asset_entity (checksum)',
|
'CREATE INDEX IF NOT EXISTS idx_trashed_local_asset_checksum ON trashed_local_asset_entity (checksum)',
|
||||||
);
|
);
|
||||||
|
final i1.Index idxTrashedLocalAssetAlbum = i1.Index(
|
||||||
|
'idx_trashed_local_asset_album',
|
||||||
|
'CREATE INDEX IF NOT EXISTS idx_trashed_local_asset_album ON trashed_local_asset_entity (album_id)',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Shape23 extends i0.VersionedTable {
|
class Shape23 extends i0.VersionedTable {
|
||||||
|
|
|
||||||
|
|
@ -14,17 +14,17 @@ class DriftTrashedLocalAssetRepository extends DriftDatabaseRepository {
|
||||||
final Drift _db;
|
final Drift _db;
|
||||||
|
|
||||||
const DriftTrashedLocalAssetRepository(this._db) : super(_db);
|
const DriftTrashedLocalAssetRepository(this._db) : super(_db);
|
||||||
|
static const _chunk = 32000;
|
||||||
|
|
||||||
Future<void> updateHashes(Map<String, String> hashes) {
|
Future<void> updateHashes(Map<String, String> hashes) {
|
||||||
if (hashes.isEmpty) {
|
if (hashes.isEmpty) {
|
||||||
return Future.value();
|
return Future.value();
|
||||||
}
|
}
|
||||||
final now = DateTime.now();
|
|
||||||
return _db.batch((batch) async {
|
return _db.batch((batch) async {
|
||||||
for (final entry in hashes.entries) {
|
for (final entry in hashes.entries) {
|
||||||
batch.update(
|
batch.update(
|
||||||
_db.trashedLocalAssetEntity,
|
_db.trashedLocalAssetEntity,
|
||||||
TrashedLocalAssetEntityCompanion(checksum: Value(entry.value), updatedAt: Value(now)),
|
TrashedLocalAssetEntityCompanion(checksum: Value(entry.value)),
|
||||||
where: (e) => e.id.equals(entry.key),
|
where: (e) => e.id.equals(entry.key),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -102,18 +102,16 @@ class DriftTrashedLocalAssetRepository extends DriftDatabaseRepository {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (assetIds.length <= 32000) {
|
if (assetIds.length <= _chunk) {
|
||||||
await (_db.delete(_db.trashedLocalAssetEntity)..where((row) => row.id.isNotIn(assetIds))).go();
|
await (_db.delete(_db.trashedLocalAssetEntity)..where((row) => row.id.isNotIn(assetIds))).go();
|
||||||
} else {
|
} else {
|
||||||
final existingIds = await (_db.selectOnly(
|
final existingIds = await (_db.selectOnly(
|
||||||
_db.trashedLocalAssetEntity,
|
_db.trashedLocalAssetEntity,
|
||||||
)..addColumns([_db.trashedLocalAssetEntity.id])).map((r) => r.read(_db.trashedLocalAssetEntity.id)!).get();
|
)..addColumns([_db.trashedLocalAssetEntity.id])).map((r) => r.read(_db.trashedLocalAssetEntity.id)!).get();
|
||||||
final idToDelete = existingIds.where((id) => !assetIds.contains(id));
|
final idToDelete = existingIds.where((id) => !assetIds.contains(id));
|
||||||
await _db.batch((batch) {
|
for (final slice in idToDelete.slices(_chunk)) {
|
||||||
for (final id in idToDelete) {
|
await (_db.delete(_db.trashedLocalAssetEntity)..where((t) => t.id.isIn(slice))).go();
|
||||||
batch.deleteWhere(_db.trashedLocalAssetEntity, (row) => row.id.equals(id));
|
}
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -181,7 +179,7 @@ class DriftTrashedLocalAssetRepository extends DriftDatabaseRepository {
|
||||||
id: Value(asset.id),
|
id: Value(asset.id),
|
||||||
name: Value(asset.name),
|
name: Value(asset.name),
|
||||||
albumId: Value(entry.key),
|
albumId: Value(entry.key),
|
||||||
checksum: asset.checksum == null ? const Value.absent() : Value(asset.checksum),
|
checksum: Value(asset.checksum),
|
||||||
type: Value(asset.type),
|
type: Value(asset.type),
|
||||||
width: Value(asset.width),
|
width: Value(asset.width),
|
||||||
height: Value(asset.height),
|
height: Value(asset.height),
|
||||||
|
|
@ -200,24 +198,29 @@ class DriftTrashedLocalAssetRepository extends DriftDatabaseRepository {
|
||||||
await _db.into(_db.trashedLocalAssetEntity).insertOnConflictUpdate(companion);
|
await _db.into(_db.trashedLocalAssetEntity).insertOnConflictUpdate(companion);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (final id in idToDelete) {
|
for (final slice in idToDelete.slices(_chunk)) {
|
||||||
await (_db.delete(_db.localAssetEntity)..where((row) => row.id.equals(id))).go();
|
await (_db.delete(_db.trashedLocalAssetEntity)..where((t) => t.id.isIn(slice))).go();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> applyRestoredAssets(Iterable<String> ids) async {
|
Future<void> applyRestoredAssets(List<String> idList) async {
|
||||||
if (ids.isEmpty) {
|
if (idList.isEmpty) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final trashedAssets = await (_db.select(_db.trashedLocalAssetEntity)..where((tbl) => tbl.id.isIn(ids))).get();
|
final trashedAssets = <TrashedLocalAssetEntityData>[];
|
||||||
|
|
||||||
|
for (final slice in idList.slices(_chunk)) {
|
||||||
|
final q = _db.select(_db.trashedLocalAssetEntity)..where((t) => t.id.isIn(slice));
|
||||||
|
trashedAssets.addAll(await q.get());
|
||||||
|
}
|
||||||
|
|
||||||
if (trashedAssets.isEmpty) {
|
if (trashedAssets.isEmpty) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final localAssets = trashedAssets.map((e) {
|
final companions = trashedAssets.map((e) {
|
||||||
return LocalAssetEntityCompanion.insert(
|
return LocalAssetEntityCompanion.insert(
|
||||||
id: e.id,
|
id: e.id,
|
||||||
name: e.name,
|
name: e.name,
|
||||||
|
|
@ -231,15 +234,15 @@ class DriftTrashedLocalAssetRepository extends DriftDatabaseRepository {
|
||||||
isFavorite: Value(e.isFavorite),
|
isFavorite: Value(e.isFavorite),
|
||||||
orientation: Value(e.orientation),
|
orientation: Value(e.orientation),
|
||||||
);
|
);
|
||||||
}).toList();
|
});
|
||||||
|
|
||||||
await _db.transaction(() async {
|
await _db.transaction(() async {
|
||||||
await _db.batch((batch) {
|
for (final companion in companions) {
|
||||||
batch.insertAllOnConflictUpdate(_db.localAssetEntity, localAssets);
|
await _db.into(_db.localAssetEntity).insertOnConflictUpdate(companion);
|
||||||
for (final id in ids) {
|
}
|
||||||
batch.deleteWhere(_db.trashedLocalAssetEntity, (row) => row.id.equals(id));
|
for (final slice in idList.slices(_chunk)) {
|
||||||
}
|
await (_db.delete(_db.trashedLocalAssetEntity)..where((t) => t.id.isIn(slice))).go();
|
||||||
});
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -247,7 +250,7 @@ class DriftTrashedLocalAssetRepository extends DriftDatabaseRepository {
|
||||||
Future<Map<String, String>> _getCachedChecksums(Set<String> assetIds) async {
|
Future<Map<String, String>> _getCachedChecksums(Set<String> assetIds) async {
|
||||||
final localChecksumById = <String, String>{};
|
final localChecksumById = <String, String>{};
|
||||||
|
|
||||||
for (final slice in assetIds.slices(32000)) {
|
for (final slice in assetIds.slices(_chunk)) {
|
||||||
final rows =
|
final rows =
|
||||||
await (_db.selectOnly(_db.localAssetEntity)
|
await (_db.selectOnly(_db.localAssetEntity)
|
||||||
..where(_db.localAssetEntity.id.isIn(slice) & _db.localAssetEntity.checksum.isNotNull())
|
..where(_db.localAssetEntity.id.isIn(slice) & _db.localAssetEntity.checksum.isNotNull())
|
||||||
|
|
|
||||||
5
mobile/test/drift/main/generated/schema_v13.dart
generated
5
mobile/test/drift/main/generated/schema_v13.dart
generated
|
|
@ -7720,6 +7720,10 @@ class DatabaseAtV13 extends GeneratedDatabase {
|
||||||
'idx_trashed_local_asset_checksum',
|
'idx_trashed_local_asset_checksum',
|
||||||
'CREATE INDEX IF NOT EXISTS idx_trashed_local_asset_checksum ON trashed_local_asset_entity (checksum)',
|
'CREATE INDEX IF NOT EXISTS idx_trashed_local_asset_checksum ON trashed_local_asset_entity (checksum)',
|
||||||
);
|
);
|
||||||
|
late final Index idxTrashedLocalAssetAlbum = Index(
|
||||||
|
'idx_trashed_local_asset_album',
|
||||||
|
'CREATE INDEX IF NOT EXISTS idx_trashed_local_asset_album ON trashed_local_asset_entity (album_id)',
|
||||||
|
);
|
||||||
@override
|
@override
|
||||||
Iterable<TableInfo<Table, Object?>> get allTables =>
|
Iterable<TableInfo<Table, Object?>> get allTables =>
|
||||||
allSchemaEntities.whereType<TableInfo<Table, Object?>>();
|
allSchemaEntities.whereType<TableInfo<Table, Object?>>();
|
||||||
|
|
@ -7751,6 +7755,7 @@ class DatabaseAtV13 extends GeneratedDatabase {
|
||||||
trashedLocalAssetEntity,
|
trashedLocalAssetEntity,
|
||||||
idxLatLng,
|
idxLatLng,
|
||||||
idxTrashedLocalAssetChecksum,
|
idxTrashedLocalAssetChecksum,
|
||||||
|
idxTrashedLocalAssetAlbum,
|
||||||
];
|
];
|
||||||
@override
|
@override
|
||||||
int get schemaVersion => 13;
|
int get schemaVersion => 13;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue