Sync issue fix, added error code, handled enque failure

Sync issue fix, added error code, handled enque failure
This commit is contained in:
sridhar
2019-10-12 10:51:52 +05:30
parent b7452e84a5
commit 9fef9d38c7
6 changed files with 337 additions and 243 deletions

View File

@@ -22,6 +22,7 @@ static CompletionHandler storedCompletionHandler;
NSMutableDictionary<NSString *, NSNumber *> *idToPercentMap;
NSMutableDictionary<NSString *, NSDictionary *> *progressReports;
NSDate *lastProgressReport;
NSNumber *sharedLock;
}
RCT_EXPORT_MODULE();
@@ -66,6 +67,7 @@ RCT_EXPORT_MODULE();
sessionConfig = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:sessonIdentifier];
progressReports = [[NSMutableDictionary alloc] init];
lastProgressReport = [[NSDate alloc] init];
sharedLock = [NSNumber numberWithInt:1];
}
return self;
}
@@ -77,19 +79,21 @@ RCT_EXPORT_MODULE();
}
- (void)removeTaskFromMap: (NSURLSessionTask *)task {
NSNumber *taskId = @(task.taskIdentifier);
RNBGDTaskConfig *taskConfig = taskToConfigMap[taskId];
@synchronized (taskToConfigMap) {
@synchronized (sharedLock) {
NSNumber *taskId = @(task.taskIdentifier);
RNBGDTaskConfig *taskConfig = taskToConfigMap[taskId];
[taskToConfigMap removeObjectForKey:taskId];
[[NSUserDefaults standardUserDefaults] setObject:[self serialize: taskToConfigMap] forKey:ID_TO_CONFIG_MAP_KEY];
}
if (taskConfig) {
[idToTaskMap removeObjectForKey:taskConfig.id];
[idToPercentMap removeObjectForKey:taskConfig.id];
}
if (taskToConfigMap.count == 0) {
[urlSession invalidateAndCancel];
urlSession = nil;
if (taskConfig) {
[idToTaskMap removeObjectForKey:taskConfig.id];
[idToPercentMap removeObjectForKey:taskConfig.id];
}
if (taskToConfigMap.count == 0) {
[urlSession invalidateAndCancel];
urlSession = nil;
}
}
}
@@ -121,37 +125,45 @@ RCT_EXPORT_METHOD(download: (NSDictionary *) options) {
}
}
NSURLSessionDownloadTask __strong *task = [urlSession downloadTaskWithRequest:request];
RNBGDTaskConfig *taskConfig = [[RNBGDTaskConfig alloc] initWithDictionary: @{@"id": identifier, @"destination": destination}];
@synchronized(taskToConfigMap) {
@synchronized (sharedLock) {
NSURLSessionDownloadTask __strong *task = [urlSession downloadTaskWithRequest:request];
RNBGDTaskConfig *taskConfig = [[RNBGDTaskConfig alloc] initWithDictionary: @{@"id": identifier, @"destination": destination}];
taskToConfigMap[@(task.taskIdentifier)] = taskConfig;
[[NSUserDefaults standardUserDefaults] setObject:[self serialize: taskToConfigMap] forKey:ID_TO_CONFIG_MAP_KEY];
}
idToTaskMap[identifier] = task;
idToPercentMap[identifier] = @0.0;
[task resume];
}
RCT_EXPORT_METHOD(pauseTask: (NSString *)identifier) {
NSURLSessionDownloadTask *task = idToTaskMap[identifier];
if (task != nil && task.state == NSURLSessionTaskStateRunning) {
[task suspend];
}
}
RCT_EXPORT_METHOD(resumeTask: (NSString *)identifier) {
NSURLSessionDownloadTask *task = idToTaskMap[identifier];
if (task != nil && task.state == NSURLSessionTaskStateSuspended) {
idToTaskMap[identifier] = task;
idToPercentMap[identifier] = @0.0;
[task resume];
}
}
RCT_EXPORT_METHOD(pauseTask: (NSString *)identifier) {
@synchronized (sharedLock) {
NSURLSessionDownloadTask *task = idToTaskMap[identifier];
if (task != nil && task.state == NSURLSessionTaskStateRunning) {
[task suspend];
}
}
}
RCT_EXPORT_METHOD(resumeTask: (NSString *)identifier) {
@synchronized (sharedLock) {
NSURLSessionDownloadTask *task = idToTaskMap[identifier];
if (task != nil && task.state == NSURLSessionTaskStateSuspended) {
[task resume];
}
}
}
RCT_EXPORT_METHOD(stopTask: (NSString *)identifier) {
NSURLSessionDownloadTask *task = idToTaskMap[identifier];
if (task != nil) {
[task cancel];
[self removeTaskFromMap:task];
@synchronized (sharedLock) {
NSURLSessionDownloadTask *task = idToTaskMap[identifier];
if (task != nil) {
[task cancel];
[self removeTaskFromMap:task];
}
}
}
@@ -159,56 +171,60 @@ RCT_EXPORT_METHOD(checkForExistingDownloads: (RCTPromiseResolveBlock)resolve rej
[self lazyInitSession];
[urlSession getTasksWithCompletionHandler:^(NSArray<NSURLSessionDataTask *> * _Nonnull dataTasks, NSArray<NSURLSessionUploadTask *> * _Nonnull uploadTasks, NSArray<NSURLSessionDownloadTask *> * _Nonnull downloadTasks) {
NSMutableArray *idsFound = [[NSMutableArray alloc] init];
for (NSURLSessionDownloadTask *foundTask in downloadTasks) {
NSURLSessionDownloadTask __strong *task = foundTask;
RNBGDTaskConfig *taskConfig = taskToConfigMap[@(task.taskIdentifier)];
if (taskConfig) {
if (task.state == NSURLSessionTaskStateCompleted && task.countOfBytesReceived < task.countOfBytesExpectedToReceive) {
if (task.error && task.error.code == -999 && task.error.userInfo[NSURLSessionDownloadTaskResumeData] != nil) {
task = [urlSession downloadTaskWithResumeData:task.error.userInfo[NSURLSessionDownloadTaskResumeData]];
} else {
task = [urlSession downloadTaskWithURL:foundTask.currentRequest.URL];
@synchronized (sharedLock) {
for (NSURLSessionDownloadTask *foundTask in downloadTasks) {
NSURLSessionDownloadTask __strong *task = foundTask;
RNBGDTaskConfig *taskConfig = taskToConfigMap[@(task.taskIdentifier)];
if (taskConfig) {
if (task.state == NSURLSessionTaskStateCompleted && task.countOfBytesReceived < task.countOfBytesExpectedToReceive) {
if (task.error && task.error.code == -999 && task.error.userInfo[NSURLSessionDownloadTaskResumeData] != nil) {
task = [urlSession downloadTaskWithResumeData:task.error.userInfo[NSURLSessionDownloadTaskResumeData]];
} else {
task = [urlSession downloadTaskWithURL:foundTask.currentRequest.URL];
}
[task resume];
}
[task resume];
NSNumber *percent = foundTask.countOfBytesExpectedToReceive > 0 ? [NSNumber numberWithFloat:(float)task.countOfBytesReceived/(float)foundTask.countOfBytesExpectedToReceive] : @0.0;
[idsFound addObject:@{
@"id": taskConfig.id,
@"state": [NSNumber numberWithInt: task.state],
@"bytesWritten": [NSNumber numberWithLongLong:task.countOfBytesReceived],
@"totalBytes": [NSNumber numberWithLongLong:foundTask.countOfBytesExpectedToReceive],
@"percent": percent
}];
taskConfig.reportedBegin = YES;
taskToConfigMap[@(task.taskIdentifier)] = taskConfig;
idToTaskMap[taskConfig.id] = task;
idToPercentMap[taskConfig.id] = percent;
} else {
[task cancel];
}
NSNumber *percent = foundTask.countOfBytesExpectedToReceive > 0 ? [NSNumber numberWithFloat:(float)task.countOfBytesReceived/(float)foundTask.countOfBytesExpectedToReceive] : @0.0;
[idsFound addObject:@{
@"id": taskConfig.id,
@"state": [NSNumber numberWithInt: task.state],
@"bytesWritten": [NSNumber numberWithLongLong:task.countOfBytesReceived],
@"totalBytes": [NSNumber numberWithLongLong:foundTask.countOfBytesExpectedToReceive],
@"percent": percent
}];
taskConfig.reportedBegin = YES;
taskToConfigMap[@(task.taskIdentifier)] = taskConfig;
idToTaskMap[taskConfig.id] = task;
idToPercentMap[taskConfig.id] = percent;
} else {
[task cancel];
}
resolve(idsFound);
}
resolve(idsFound);
}];
}
#pragma mark - NSURLSessionDownloadDelegate methods
- (void)URLSession:(nonnull NSURLSession *)session downloadTask:(nonnull NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(nonnull NSURL *)location {
RNBGDTaskConfig *taskCofig = taskToConfigMap[@(downloadTask.taskIdentifier)];
if (taskCofig != nil) {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *destURL = [NSURL fileURLWithPath:taskCofig.destination];
[fileManager createDirectoryAtURL:[destURL URLByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:nil];
[fileManager removeItemAtURL:destURL error:nil];
NSError *moveError;
BOOL moved = [fileManager moveItemAtURL:location toURL:destURL error:&moveError];
if (self.bridge) {
if (moved) {
[self sendEventWithName:@"downloadComplete" body:@{@"id": taskCofig.id}];
} else {
[self sendEventWithName:@"downloadFailed" body:@{@"id": taskCofig.id, @"error": [moveError localizedDescription]}];
@synchronized (sharedLock) {
RNBGDTaskConfig *taskCofig = taskToConfigMap[@(downloadTask.taskIdentifier)];
if (taskCofig != nil) {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *destURL = [NSURL fileURLWithPath:taskCofig.destination];
[fileManager createDirectoryAtURL:[destURL URLByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:nil];
[fileManager removeItemAtURL:destURL error:nil];
NSError *moveError;
BOOL moved = [fileManager moveItemAtURL:location toURL:destURL error:&moveError];
if (self.bridge) {
if (moved) {
[self sendEventWithName:@"downloadComplete" body:@{@"id": taskCofig.id}];
} else {
[self sendEventWithName:@"downloadFailed" body:@{@"id": taskCofig.id, @"error": [moveError localizedDescription]}];
}
}
[self removeTaskFromMap:downloadTask];
}
[self removeTaskFromMap:downloadTask];
}
}
@@ -216,7 +232,7 @@ RCT_EXPORT_METHOD(checkForExistingDownloads: (RCTPromiseResolveBlock)resolve rej
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
@synchronized (self) {
@synchronized (sharedLock) {
RNBGDTaskConfig *taskCofig = taskToConfigMap[@(downloadTask.taskIdentifier)];
if (taskCofig != nil) {
if (!taskCofig.reportedBegin) {
@@ -244,12 +260,14 @@ RCT_EXPORT_METHOD(checkForExistingDownloads: (RCTPromiseResolveBlock)resolve rej
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
RNBGDTaskConfig *taskCofig = taskToConfigMap[@(task.taskIdentifier)];
if (error != nil && error.code != -999 && taskCofig != nil) {
if (self.bridge) {
[self sendEventWithName:@"downloadFailed" body:@{@"id": taskCofig.id, @"error": [error localizedDescription]}];
@synchronized (sharedLock) {
RNBGDTaskConfig *taskCofig = taskToConfigMap[@(task.taskIdentifier)];
if (error != nil && error.code != -999 && taskCofig != nil) {
if (self.bridge) {
[self sendEventWithName:@"downloadFailed" body:@{@"id": taskCofig.id, @"error": [error localizedDescription]}];
}
[self removeTaskFromMap:task];
}
[self removeTaskFromMap:task];
}
}