Skip to content

Commit

Permalink
Merge pull request #11839 from wordpress-mobile/issue/11784-uploader-…
Browse files Browse the repository at this point in the history
…protocol-in-media-coordinator

Implements Uploader protocol in MediaCoordinator and PostCoordinator.
  • Loading branch information
diegoreymendez authored Jun 3, 2019
2 parents 63d0f4b + 90a8e2a commit ad2ed3b
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 27 deletions.
20 changes: 15 additions & 5 deletions WordPress/Classes/Services/MediaCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@ import WordPressFlux
/// items, independently of a specific view controller. It should be accessed
/// via the `shared` singleton.
///
class MediaCoordinator: NSObject, Uploader {
func resume() {
}


class MediaCoordinator: NSObject {
@objc static let shared = MediaCoordinator()

private(set) var backgroundContext: NSManagedObjectContext = {
Expand Down Expand Up @@ -606,6 +602,20 @@ extension MediaCoordinator: MediaProgressCoordinatorDelegate {
}
}

extension MediaCoordinator: Uploader {
func resume() {
let service = MediaService(managedObjectContext: mainContext)

service.getFailedMedia { [weak self] media in
guard let self = self else {
return
}

media.forEach() { self.retryMedia($0) }
}
}
}

extension Media {
var uploadID: String {
return objectID.uriRepresentation().absoluteString
Expand Down
6 changes: 6 additions & 0 deletions WordPress/Classes/Services/MediaService.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ typedef NS_ERROR_ENUM(MediaServiceErrorDomain, MediaServiceError) {
thumbnailCallback:(nullable void (^)(Media * __nonnull media, NSURL * __nonnull thumbnailURL))thumbnailCallback
completion:(nullable void (^)(Media * __nullable media, NSError * __nullable error))completion;

/**
Get all Media that failed to upload.
@param result a block that will be invoked to return the requested media.
*/
- (void)getFailedMedia:(nonnull void (^)( NSArray<Media *>* _Nonnull media))result;

/**
Get the Media object from the server using the blog and the mediaID as the identifier of the resource
Expand Down
18 changes: 18 additions & 0 deletions WordPress/Classes/Services/MediaService.m
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,24 @@ - (void)deleteMedia:(nonnull NSArray<Media *> *)mediaObjects

#pragma mark - Getting media

- (void)getFailedMedia:(void (^)( NSArray<Media *>* media))result {
[self.managedObjectContext performBlock:^{
NSString *entityName = NSStringFromClass([Media class]);
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entityName];

request.predicate = [NSPredicate predicateWithFormat:@"remoteStatusNumber == %d", MediaRemoteStatusFailed];

NSError *error = nil;
NSArray *results = [self.managedObjectContext executeFetchRequest:request error:&error];

if (!results) {
result(@[]);
} else {
result(results);
}
}];
}

- (void) getMediaWithID:(NSNumber *) mediaID inBlog:(Blog *) blog
success:(void (^)(Media *media))success
failure:(void (^)(NSError *error))failure
Expand Down
13 changes: 9 additions & 4 deletions WordPress/Classes/Services/PostCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,14 @@ class PostCoordinator: NSObject {

extension PostCoordinator: Uploader {
func resume() {
// Resume the upload of all posts that are not synched.
//
// 1. Query posts with status == .failed
// 2. Call retrySave() for each post
let service = PostService(managedObjectContext: mainContext)

service.getFailedPosts { [weak self] posts in
guard let self = self else {
return
}

posts.forEach() { self.retrySave(of: $0 ) }
}
}
}
7 changes: 7 additions & 0 deletions WordPress/Classes/Services/PostService.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ extern const NSUInteger PostServiceDefaultNumberToSync;
success:(void (^)(AbstractPost *post))success
failure:(void (^)(NSError *))failure;

/**
Get all posts that failed to upload.
@param result a block that will be invoked to return the requested posts.
*/
- (void)getFailedPosts:(nonnull void (^)( NSArray<AbstractPost *>* _Nonnull posts))result;

/**
Sync an initial batch of posts from the specified blog.
Please note that success and/or failure are called in the context of the
Expand Down
20 changes: 20 additions & 0 deletions WordPress/Classes/Services/PostService.m
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,26 @@ - (Page *)createDraftPageForBlog:(Blog *)blog {
return page;
}


- (void)getFailedPosts:(void (^)( NSArray<AbstractPost *>* posts))result {
[self.managedObjectContext performBlock:^{
NSString *entityName = NSStringFromClass([AbstractPost class]);
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entityName];

request.predicate = [NSPredicate predicateWithFormat:@"remoteStatusNumber == %d", AbstractPostRemoteStatusFailed];

NSError *error = nil;
NSArray *results = [self.managedObjectContext executeFetchRequest:request error:&error];

if (!results) {
result(@[]);
} else {
result(results);
}
}];
}


- (void)getPostWithID:(NSNumber *)postID
forBlog:(Blog *)blog
success:(void (^)(AbstractPost *post))success
Expand Down
30 changes: 12 additions & 18 deletions WordPress/Classes/Uploads/UploadsManager.swift
Original file line number Diff line number Diff line change
@@ -1,24 +1,11 @@
import Foundation
import Reachability

/// Takes care of coordinating all uploaders used by the app.
///
@objc
class UploadsManager: NSObject {
private let uploaders: [Uploader]
private lazy var reachabilityObserver: NSObjectProtocol = {
return NotificationCenter.default.addObserver(forName: .reachabilityChanged, object: nil, queue: nil) { [weak self] notification in

guard let self = self else {
return
}

let internetIsReachable = notification.userInfo?[Foundation.Notification.reachabilityKey] as? Bool ?? false

if internetIsReachable {
self.resume()
}
}
}()
private let reachability: Reachability = Reachability.forInternetConnection()

// MARK: Initialization & Finalization

Expand All @@ -31,17 +18,24 @@ class UploadsManager: NSObject {
self.uploaders = uploaders

super.init()

setupReachableBlock()
}

deinit {
NotificationCenter.default.removeObserver(reachabilityObserver)
// MARK: Reachability

private func setupReachableBlock() {
reachability.reachableBlock = { _ in
self.resume()
}

reachability.startNotifier()
}

// MARK: Interacting with Uploads

/// Resumes all uploads handled by the uploaders.
///
@objc
func resume() {
for uploader in uploaders {
uploader.resume()
Expand Down

0 comments on commit ad2ed3b

Please sign in to comment.