-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Expand file tree
/
Copy pathMedia+Sync.swift
More file actions
69 lines (62 loc) · 3.75 KB
/
Copy pathMedia+Sync.swift
File metadata and controls
69 lines (62 loc) · 3.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import Foundation
import CoreData
import WordPressData
extension Media {
/// Returns a list of Media objects that should be uploaded for the given input parameters.
///
/// - Parameters:
/// - automatedRetry: whether the media to upload is the result of an automated retry.
///
/// - Returns: the Media objects that should be uploaded for the given input parameters.
///
static func failedMediaForUpload(automatedRetry: Bool, in context: NSManagedObjectContext) -> [Media] {
let request = NSFetchRequest<Media>(entityName: Media.entityName())
let failedMediaPredicate = NSPredicate(format: "\(#keyPath(Media.remoteStatusNumber)) == %d", MediaRemoteStatus.failed.rawValue)
if automatedRetry {
let autoUploadFailureCountPredicate = NSPredicate(format: "\(#keyPath(Media.autoUploadFailureCount)) < %d", Media.maxAutoUploadFailureCount)
request.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [failedMediaPredicate, autoUploadFailureCountPredicate])
} else {
request.predicate = failedMediaPredicate
}
let media = (try? context.fetch(request)) ?? []
return media
}
/// This method checks the status of all media objects and updates them to the correct status if needed.
/// The main cause of wrong status is the app being killed while uploads of media are happening.
///
/// - Parameters:
/// - onCompletion: block to invoke when status update is finished.
/// - onError: block to invoke if any error occurs while the update is being made.
///
static func refreshMediaStatus(using coreDataStack: CoreDataStackSwift, onCompletion: (() -> Void)? = nil, onError: ((Error) -> Void)? = nil) {
coreDataStack.performAndSave({ context in
let fetch = NSFetchRequest<Media>(entityName: Media.classNameWithoutNamespaces())
let pushingPredicate = NSPredicate(format: "remoteStatusNumber = %@", NSNumber(value: MediaRemoteStatus.pushing.rawValue))
let processingPredicate = NSPredicate(format: "remoteStatusNumber = %@", NSNumber(value: MediaRemoteStatus.processing.rawValue))
let errorPredicate = NSPredicate(format: "remoteStatusNumber = %@", NSNumber(value: MediaRemoteStatus.failed.rawValue))
fetch.predicate = NSCompoundPredicate(orPredicateWithSubpredicates: [pushingPredicate, processingPredicate, errorPredicate])
let mediaPushing = try context.fetch(fetch)
for media in mediaPushing {
// If file were in the middle of being pushed or being processed they now are failed.
if media.remoteStatus == .pushing || media.remoteStatus == .processing {
media.remoteStatus = .failed
}
// If they failed to upload themselves because no local copy exists then we need to delete this media object
// This scenario can happen when media objects were created based on an asset that failed to import to the WordPress App.
// For example a that is stored on the iCloud storage and because of the network connection failed the import process.
if media.remoteStatus == .failed,
let error = media.error as NSError?, error.domain == MediaServiceErrorDomain && error.code == MediaServiceError.fileDoesNotExist.rawValue {
context.delete(media)
}
}
}, completion: { result in
switch result {
case .success:
onCompletion?()
case let .failure(error):
DDLogError("Error while attempting to clean local media: \(error.localizedDescription)")
onError?(error)
}
}, on: .main)
}
}