Skip to content

Commit

Permalink
fix: Prevent photo library from duplicating items in the upload queue (
Browse files Browse the repository at this point in the history
  • Loading branch information
adrien-coye authored Feb 21, 2025
2 parents a25fbfa + f60bc77 commit eef6ef3
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 27 deletions.
2 changes: 1 addition & 1 deletion kDriveCore/Data/UploadQueue/Queue/UploadQueue+Queue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ extension UploadQueue: UploadQueueable {

public func rebuildUploadQueueFromObjectsInRealm(_ caller: StaticString = #function) {
Log.uploadQueue("rebuildUploadQueueFromObjectsInRealm caller:\(caller)")
concurrentQueue.sync {
serialQueue.sync {
// Clean cache if necessary before we try to restart the uploads.
@InjectService var freeSpaceService: FreeSpaceService
freeSpaceService.cleanCacheIfAlmostFull()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,36 +34,39 @@ public extension PhotoLibraryUploader {

var newAssetsCount = 0

let options = PHFetchOptions()
options.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]

let typesPredicates = getAssetPredicates(forSettings: frozenSettings)
let datePredicate = getDatePredicate(with: frozenSettings)
let typePredicate = NSCompoundPredicate(orPredicateWithSubpredicates: typesPredicates)
options.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [datePredicate, typePredicate])

Log.photoLibraryUploader("Fetching new pictures/videos with predicate: \(options.predicate!.predicateFormat)")
let assetsFetchResult = PHAsset.fetchAssets(with: options)
let syncDate = Date()

try? uploadsDatabase.writeTransaction { writableRealm in
do {
try addImageAssetsToUploadQueue(
assetsFetchResult: assetsFetchResult,
initial: frozenSettings.lastSync.timeIntervalSince1970 == 0,
writableRealm: writableRealm
)
serialQueue.sync {
let options = PHFetchOptions()
options.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]

let typesPredicates = getAssetPredicates(forSettings: frozenSettings)
let datePredicate = getDatePredicate(with: frozenSettings)
let typePredicate = NSCompoundPredicate(orPredicateWithSubpredicates: typesPredicates)
options.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [datePredicate, typePredicate])

Log.photoLibraryUploader("Fetching new pictures/videos with predicate: \(options.predicate!.predicateFormat)")
let assetsFetchResult = PHAsset.fetchAssets(with: options)
let syncDate = Date()

updateLastSyncDate(syncDate, writableRealm: writableRealm)
try? uploadsDatabase.writeTransaction { writableRealm in
do {
try addImageAssetsToUploadQueue(
assetsFetchResult: assetsFetchResult,
initial: frozenSettings.lastSync.timeIntervalSince1970 == 0,
writableRealm: writableRealm
)

newAssetsCount = assetsFetchResult.count
Log.photoLibraryUploader("New assets count:\(newAssetsCount)")
} catch ErrorDomain.importCancelledBySystem {
Log.photoLibraryUploader("System is requesting to stop", level: .error)
} catch {
Log.photoLibraryUploader("addImageAssetsToUploadQueue error:\(error)", level: .error)
updateLastSyncDate(syncDate, writableRealm: writableRealm)

newAssetsCount = assetsFetchResult.count
Log.photoLibraryUploader("New assets count:\(newAssetsCount)")
} catch ErrorDomain.importCancelledBySystem {
Log.photoLibraryUploader("System is requesting to stop", level: .error)
} catch {
Log.photoLibraryUploader("addImageAssetsToUploadQueue error:\(error)", level: .error)
}
}
}

return newAssetsCount
}

Expand Down Expand Up @@ -151,6 +154,12 @@ public extension PhotoLibraryUploader {
return
}

guard !assetAlreadyPendingUpload(bestResourceSHA256: bestResourceSHA256,
writableRealm: writableRealm) else {
Log.photoLibraryUploader("Asset already in pending upload")
return
}

let algorithmImportVersion = currentDiffAlgorithmVersion

// New UploadFile to be uploaded. Priority is `.low`, first sync is `.normal`
Expand Down Expand Up @@ -193,6 +202,17 @@ public extension PhotoLibraryUploader {
}
}

private func assetAlreadyPendingUpload(bestResourceSHA256: String?,
writableRealm: Realm) -> Bool {
guard let bestResourceSHA256 else {
return false
}
guard !writableRealm.objects(UploadFile.self).filter("bestResourceSHA256 == %@", bestResourceSHA256).isEmpty else {
return false
}
return true
}

private func getPhotoLibraryName(
forAsset asset: PHAsset,
settings: PhotoSyncSettings,
Expand Down
10 changes: 10 additions & 0 deletions kDriveCore/Data/UploadQueue/Servicies/PhotoLibraryUploader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ public final class PhotoLibraryUploader {
@LazyInjectService var uploadQueue: UploadQueue
@LazyInjectService(customTypeIdentifier: kDriveDBID.uploads) var uploadsDatabase: Transactionable

let serialQueue: DispatchQueue = {
@LazyInjectService var appContextService: AppContextServiceable
let autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency = appContextService.isExtension ? .workItem : .inherit

return DispatchQueue(
label: "com.infomaniak.drive.photo-library",
autoreleaseFrequency: autoreleaseFrequency
)
}()

/// Threshold value to trigger cleaning of photo roll if enabled
static let removeAssetsCountThreshold = 10

Expand Down

0 comments on commit eef6ef3

Please sign in to comment.