[mob][photos] Fix free up space failing when trying to delete lot of files at one shot (#6518)

## Description

If the number of files to be deleted exceeds 20,000, the deletion will
be performed in batches, with a maximum of 20,000 files per batch. If a
batch of 20,000 files fails, it will retry with 10,000 files (half the
previous batch size). If failures continue, the batch size will keep
reducing until it is over 2,000 files.

## Tests
Tested and works as expected.
This commit is contained in:
Ashil
2025-07-12 11:56:04 +05:30
committed by GitHub

View File

@@ -339,6 +339,9 @@ Future<bool> deleteLocalFiles(
final List<String> deletedIDs = [];
final List<String> localAssetIDs = [];
final List<String> localSharedMediaIDs = [];
const largeCountThreshold = 20000;
final tooManyAssets = localIDs.length > largeCountThreshold;
try {
for (String id in localIDs) {
if (id.startsWith(sharedMediaIdentifier)) {
@@ -350,11 +353,23 @@ Future<bool> deleteLocalFiles(
deletedIDs.addAll(await _tryDeleteSharedMediaFiles(localSharedMediaIDs));
final bool shouldDeleteInBatches =
await isAndroidSDKVersionLowerThan(android11SDKINT);
await isAndroidSDKVersionLowerThan(android11SDKINT) || tooManyAssets;
if (shouldDeleteInBatches) {
_logger.info("Deleting in batches");
deletedIDs
.addAll(await deleteLocalFilesInBatches(context, localAssetIDs));
if (tooManyAssets) {
_logger.info(
"Too many assets (${localIDs.length}) to delete in one shot, deleting in batches",
);
await _recursivelyReduceBatchSizeAndRetryDeletion(
batchSize: largeCountThreshold,
context: context,
localIDs: localIDs,
deletedIDs: deletedIDs,
);
} else {
_logger.info("Deleting in batches");
deletedIDs
.addAll(await deleteLocalFilesInBatches(context, localAssetIDs));
}
} else {
_logger.info("Deleting in one shot");
deletedIDs
@@ -625,6 +640,45 @@ Future<List<String>> deleteLocalFilesInBatches(
return deletedIDs;
}
Future<void> _recursivelyReduceBatchSizeAndRetryDeletion({
required int batchSize,
required BuildContext context,
required List<String> localIDs,
required List<String> deletedIDs,
int minimumBatchSizeThresholdToStopRetry = 2000,
}) async {
if (batchSize < minimumBatchSizeThresholdToStopRetry) {
_logger.warning(
"Batch size is too small ($batchSize), stopping further retries.",
);
throw Exception(
"Batch size is too small ($batchSize), stopping further retries.",
);
}
try {
deletedIDs.addAll(
await deleteLocalFilesInBatches(
context,
localIDs,
minimumBatchSize: 1,
maximumBatchSize: batchSize,
minimumParts: 1,
),
);
} catch (e) {
_logger.warning(
"Failed to delete local files in batches of $batchSize. Reducing batch size and retrying.",
e,
);
await _recursivelyReduceBatchSizeAndRetryDeletion(
batchSize: (batchSize / 2).floor(),
context: context,
localIDs: localIDs,
deletedIDs: deletedIDs,
);
}
}
Future<bool> _localFileExist(EnteFile file) {
if (file.isSharedMediaToAppSandbox) {
final localFile = File(getSharedMediaFilePath(file));