Skip to content

Queue Storage Tasks on separate queue #1981

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,26 @@ - (void)testUnauthenticatedSimplePutData {
[self waitForExpectations];
}

- (void)testUnauthenticatedSimplePutDataInBackgroundQueue {
XCTestExpectation *expectation =
[self expectationWithDescription:@"testUnauthenticatedSimplePutDataInBackgroundQueue"];
FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/testBytesUpload"];

NSData *data = [@"Hello World" dataUsingEncoding:NSUTF8StringEncoding];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[ref putData:data
metadata:nil
completion:^(FIRStorageMetadata *metadata, NSError *error) {
XCTAssertNotNil(metadata, "Metadata should not be nil");
XCTAssertNil(error, "Error should be nil");
[expectation fulfill];
}];
});

[self waitForExpectations];
}

- (void)testUnauthenticatedSimplePutEmptyData {
XCTestExpectation *expectation =
[self expectationWithDescription:@"testUnauthenticatedSimplePutEmptyData"];
Expand Down Expand Up @@ -369,6 +389,24 @@ - (void)testUnauthenticatedSimpleGetData {
[self waitForExpectations];
}

- (void)testUnauthenticatedSimpleGetDataInBackgroundQueue {
XCTestExpectation *expectation =
[self expectationWithDescription:@"testUnauthenticatedSimpleGetDataInBackgroundQueue"];

FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/1mb"];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[ref dataWithMaxSize:1 * 1024 * 1024
completion:^(NSData *data, NSError *error) {
XCTAssertNotNil(data, "Data should not be nil");
XCTAssertNil(error, "Error should be nil");
[expectation fulfill];
}];
});

[self waitForExpectations];
}

- (void)testUnauthenticatedSimpleGetDataTooSmall {
XCTestExpectation *expectation =
[self expectationWithDescription:@"testUnauthenticatedSimpleGetDataTooSmall"];
Expand Down Expand Up @@ -615,6 +653,56 @@ - (void)testUnauthenticatedResumeGetFile {
XCTAssertEqualWithAccuracy(sqrt(INT_MAX - 499), computationResult, 0.1);
}

- (void)testUnauthenticatedResumeGetFileInBackgroundQueue {
XCTestExpectation *expectation =
[self expectationWithDescription:@"testUnauthenticatedResumeGetFileInBackgroundQueue"];

FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/1mb"];

NSURL *tmpDirURL = [NSURL fileURLWithPath:NSTemporaryDirectory()];
NSURL *fileURL =
[[tmpDirURL URLByAppendingPathComponent:@"hello"] URLByAppendingPathExtension:@"txt"];

__block long resumeAtBytes = 256 * 1024;
__block long downloadedBytes = 0;

FIRStorageDownloadTask *task = [ref writeToFile:fileURL];

[task observeStatus:FIRStorageTaskStatusSuccess
handler:^(FIRStorageTaskSnapshot *snapshot) {
XCTAssertEqualObjects([snapshot description], @"<State: Success>");
[expectation fulfill];
}];

[task observeStatus:FIRStorageTaskStatusProgress
handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) {
XCTAssertTrue([[snapshot description] containsString:@"State: Progress"] ||
[[snapshot description] containsString:@"State: Resume"]);
NSProgress *progress = snapshot.progress;
XCTAssertGreaterThanOrEqual(progress.completedUnitCount, downloadedBytes);
downloadedBytes = progress.completedUnitCount;
if (progress.completedUnitCount > resumeAtBytes) {
NSLog(@"Pausing");
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[task pause];
});
resumeAtBytes = INT_MAX;
}
}];

[task observeStatus:FIRStorageTaskStatusPause
handler:^(FIRStorageTaskSnapshot *snapshot) {
XCTAssertEqualObjects([snapshot description], @"<State: Paused>");
NSLog(@"Resuming");
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[task resume];
});
}];

[self waitForExpectations];
XCTAssertEqual(INT_MAX, resumeAtBytes);
}

- (void)waitForExpectations {
[self waitForExpectationsWithTimeout:kFIRStorageIntegrationTestTimeout
handler:^(NSError *_Nullable error) {
Expand Down
8 changes: 8 additions & 0 deletions Example/Storage/Tests/Unit/FIRStorageDeleteTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
@interface FIRStorageDeleteTests : XCTestCase

@property(strong, nonatomic) GTMSessionFetcherService *fetcherService;
@property(nonatomic) dispatch_queue_t dispatchQueue;
@property(strong, nonatomic) FIRStorageMetadata *metadata;
@property(strong, nonatomic) FIRStorage *storage;
@property(strong, nonatomic) id mockApp;
Expand Down Expand Up @@ -45,6 +46,8 @@ - (void)setUp {
fetcherService:self.fetcherService
authProvider:nil];

self.dispatchQueue = dispatch_queue_create("Test dispatch queue", DISPATCH_QUEUE_SERIAL);

self.storage = [FIRStorage storageForApp:self.mockApp];
}

Expand Down Expand Up @@ -76,6 +79,7 @@ - (void)testFetcherConfiguration {
FIRStorageReference *ref = [[FIRStorageReference alloc] initWithStorage:self.storage path:path];
FIRStorageDeleteTask *task = [[FIRStorageDeleteTask alloc] initWithReference:ref
fetcherService:self.fetcherService
dispatchQueue:self.dispatchQueue
completion:^(NSError *error) {
[expectation fulfill];
}];
Expand All @@ -92,6 +96,7 @@ - (void)testSuccessfulFetch {
FIRStorageReference *ref = [[FIRStorageReference alloc] initWithStorage:self.storage path:path];
FIRStorageDeleteTask *task = [[FIRStorageDeleteTask alloc] initWithReference:ref
fetcherService:self.fetcherService
dispatchQueue:self.dispatchQueue
completion:^(NSError *error) {
XCTAssertEqual(error, nil);
[expectation fulfill];
Expand All @@ -111,6 +116,7 @@ - (void)testUnsuccessfulFetchUnauthenticated {
FIRStorageDeleteTask *task = [[FIRStorageDeleteTask alloc]
initWithReference:ref
fetcherService:self.fetcherService
dispatchQueue:self.dispatchQueue
completion:^(NSError *error) {
XCTAssertEqual(error.code, FIRStorageErrorCodeUnauthenticated);
[expectation fulfill];
Expand All @@ -130,6 +136,7 @@ - (void)testUnsuccessfulFetchUnauthorized {
FIRStorageDeleteTask *task = [[FIRStorageDeleteTask alloc]
initWithReference:ref
fetcherService:self.fetcherService
dispatchQueue:self.dispatchQueue
completion:^(NSError *error) {
XCTAssertEqual(error.code, FIRStorageErrorCodeUnauthorized);
[expectation fulfill];
Expand All @@ -149,6 +156,7 @@ - (void)testUnsuccessfulFetchObjectDoesntExist {
FIRStorageDeleteTask *task = [[FIRStorageDeleteTask alloc]
initWithReference:ref
fetcherService:self.fetcherService
dispatchQueue:self.dispatchQueue
completion:^(NSError *error) {
XCTAssertEqual(error.code, FIRStorageErrorCodeObjectNotFound);
[expectation fulfill];
Expand Down
9 changes: 9 additions & 0 deletions Example/Storage/Tests/Unit/FIRStorageGetMetadataTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
@interface FIRStorageGetMetadataTests : XCTestCase

@property(strong, nonatomic) GTMSessionFetcherService *fetcherService;
@property(nonatomic) dispatch_queue_t dispatchQueue;
@property(strong, nonatomic) FIRStorageMetadata *metadata;
@property(strong, nonatomic) FIRStorage *storage;
@property(strong, nonatomic) id mockApp;
Expand Down Expand Up @@ -45,6 +46,8 @@ - (void)setUp {
fetcherService:self.fetcherService
authProvider:nil];

self.dispatchQueue = dispatch_queue_create("Test dispatch queue", DISPATCH_QUEUE_SERIAL);

self.storage = [FIRStorage storageForApp:self.mockApp];
}

Expand Down Expand Up @@ -77,6 +80,7 @@ - (void)testFetcherConfiguration {
FIRStorageGetMetadataTask *task = [[FIRStorageGetMetadataTask alloc]
initWithReference:ref
fetcherService:self.fetcherService
dispatchQueue:self.dispatchQueue
completion:^(FIRStorageMetadata *metadata, NSError *error) {
[expectation fulfill];
}];
Expand All @@ -94,6 +98,7 @@ - (void)testSuccessfulFetch {
FIRStorageGetMetadataTask *task = [[FIRStorageGetMetadataTask alloc]
initWithReference:ref
fetcherService:self.fetcherService
dispatchQueue:self.dispatchQueue
completion:^(FIRStorageMetadata *metadata, NSError *error) {
XCTAssertEqualObjects(self.metadata.bucket, metadata.bucket);
XCTAssertEqualObjects(self.metadata.name, metadata.name);
Expand All @@ -115,6 +120,7 @@ - (void)testUnsuccessfulFetchUnauthenticated {
FIRStorageGetMetadataTask *task = [[FIRStorageGetMetadataTask alloc]
initWithReference:ref
fetcherService:self.fetcherService
dispatchQueue:self.dispatchQueue
completion:^(FIRStorageMetadata *metadata, NSError *error) {
XCTAssertEqual(metadata, nil);
XCTAssertEqual(error.code, FIRStorageErrorCodeUnauthenticated);
Expand All @@ -135,6 +141,7 @@ - (void)testUnsuccessfulFetchUnauthorized {
FIRStorageGetMetadataTask *task = [[FIRStorageGetMetadataTask alloc]
initWithReference:ref
fetcherService:self.fetcherService
dispatchQueue:self.dispatchQueue
completion:^(FIRStorageMetadata *metadata, NSError *error) {
XCTAssertEqual(metadata, nil);
XCTAssertEqual(error.code, FIRStorageErrorCodeUnauthorized);
Expand All @@ -155,6 +162,7 @@ - (void)testUnsuccessfulFetchObjectDoesntExist {
FIRStorageGetMetadataTask *task = [[FIRStorageGetMetadataTask alloc]
initWithReference:ref
fetcherService:self.fetcherService
dispatchQueue:self.dispatchQueue
completion:^(FIRStorageMetadata *metadata, NSError *error) {
XCTAssertEqual(metadata, nil);
XCTAssertEqual(error.code, FIRStorageErrorCodeObjectNotFound);
Expand All @@ -175,6 +183,7 @@ - (void)testUnsuccessfulFetchBadJSON {
FIRStorageGetMetadataTask *task = [[FIRStorageGetMetadataTask alloc]
initWithReference:ref
fetcherService:self.fetcherService
dispatchQueue:self.dispatchQueue
completion:^(FIRStorageMetadata *metadata, NSError *error) {
XCTAssertEqual(metadata, nil);
XCTAssertEqual(error.code, FIRStorageErrorCodeUnknown);
Expand Down
9 changes: 9 additions & 0 deletions Example/Storage/Tests/Unit/FIRStorageUpdateMetadataTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
@interface FIRStorageUpdateMetadataTests : XCTestCase

@property(strong, nonatomic) GTMSessionFetcherService *fetcherService;
@property(nonatomic) dispatch_queue_t dispatchQueue;
@property(strong, nonatomic) FIRStorageMetadata *metadata;
@property(strong, nonatomic) FIRStorage *storage;
@property(strong, nonatomic) id mockApp;
Expand Down Expand Up @@ -46,6 +47,8 @@ - (void)setUp {
fetcherService:self.fetcherService
authProvider:nil];

self.dispatchQueue = dispatch_queue_create("Test dispatch queue", DISPATCH_QUEUE_SERIAL);

self.storage = [FIRStorage storageForApp:self.mockApp];
}

Expand Down Expand Up @@ -84,6 +87,7 @@ - (void)testFetcherConfiguration {
FIRStorageUpdateMetadataTask *task = [[FIRStorageUpdateMetadataTask alloc]
initWithReference:ref
fetcherService:self.fetcherService
dispatchQueue:self.dispatchQueue
metadata:self.metadata
completion:^(FIRStorageMetadata *_Nullable metadata, NSError *_Nullable error) {
[expectation fulfill];
Expand All @@ -102,6 +106,7 @@ - (void)testSuccessfulFetch {
FIRStorageUpdateMetadataTask *task = [[FIRStorageUpdateMetadataTask alloc]
initWithReference:ref
fetcherService:self.fetcherService
dispatchQueue:self.dispatchQueue
metadata:self.metadata
completion:^(FIRStorageMetadata *_Nullable metadata, NSError *_Nullable error) {
XCTAssertEqualObjects(self.metadata.bucket, metadata.bucket);
Expand All @@ -124,6 +129,7 @@ - (void)testUnsuccessfulFetchUnauthenticated {
FIRStorageUpdateMetadataTask *task = [[FIRStorageUpdateMetadataTask alloc]
initWithReference:ref
fetcherService:self.fetcherService
dispatchQueue:self.dispatchQueue
metadata:self.metadata
completion:^(FIRStorageMetadata *_Nullable metadata, NSError *_Nullable error) {
XCTAssertNil(metadata);
Expand All @@ -145,6 +151,7 @@ - (void)testUnsuccessfulFetchUnauthorized {
FIRStorageUpdateMetadataTask *task = [[FIRStorageUpdateMetadataTask alloc]
initWithReference:ref
fetcherService:self.fetcherService
dispatchQueue:self.dispatchQueue
metadata:self.metadata
completion:^(FIRStorageMetadata *_Nullable metadata, NSError *_Nullable error) {
XCTAssertNil(metadata);
Expand All @@ -166,6 +173,7 @@ - (void)testUnsuccessfulFetchObjectDoesntExist {
FIRStorageUpdateMetadataTask *task = [[FIRStorageUpdateMetadataTask alloc]
initWithReference:ref
fetcherService:self.fetcherService
dispatchQueue:self.dispatchQueue
metadata:self.metadata
completion:^(FIRStorageMetadata *_Nullable metadata, NSError *_Nullable error) {
XCTAssertNil(metadata);
Expand All @@ -187,6 +195,7 @@ - (void)testUnsuccessfulFetchBadJSON {
FIRStorageUpdateMetadataTask *task = [[FIRStorageUpdateMetadataTask alloc]
initWithReference:ref
fetcherService:self.fetcherService
dispatchQueue:self.dispatchQueue
metadata:self.metadata
completion:^(FIRStorageMetadata *_Nullable metadata, NSError *_Nullable error) {
XCTAssertNil(metadata);
Expand Down
1 change: 1 addition & 0 deletions Firebase/Storage/FIRStorage.m
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ - (instancetype)initWithApp:(FIRApp *)app
_app = app;
_auth = auth;
_storageBucket = bucket;
_dispatchQueue = dispatch_queue_create("com.google.firebase.storage", DISPATCH_QUEUE_SERIAL);
_fetcherServiceForApp = [FIRStorage fetcherServiceForApp:_app bucket:bucket auth:auth];
_maxDownloadRetryTime = 600.0;
_maxOperationRetryTime = 120.0;
Expand Down
52 changes: 31 additions & 21 deletions Firebase/Storage/FIRStorageDeleteTask.m
Original file line number Diff line number Diff line change
Expand Up @@ -30,43 +30,53 @@ - (void)dealloc {

- (instancetype)initWithReference:(FIRStorageReference *)reference
fetcherService:(GTMSessionFetcherService *)service
dispatchQueue:(dispatch_queue_t)queue
completion:(FIRStorageVoidError)completion {
self = [super initWithReference:reference fetcherService:service];
self = [super initWithReference:reference fetcherService:service dispatchQueue:queue];
if (self) {
_completion = [completion copy];
}
return self;
}

- (void)enqueue {
NSMutableURLRequest *request = [self.baseRequest mutableCopy];
request.HTTPMethod = @"DELETE";
request.timeoutInterval = self.reference.storage.maxOperationRetryTime;
__weak FIRStorageDeleteTask *weakSelf = self;

[self dispatchAsync:^() {
FIRStorageDeleteTask *strongSelf = weakSelf;

if (!strongSelf) {
return;
}

FIRStorageVoidError callback = _completion;
_completion = nil;
NSMutableURLRequest *request = [strongSelf.baseRequest mutableCopy];
request.HTTPMethod = @"DELETE";
request.timeoutInterval = strongSelf.reference.storage.maxOperationRetryTime;

GTMSessionFetcher *fetcher = [self.fetcherService fetcherWithRequest:request];
_fetcher = fetcher;
FIRStorageVoidError callback = strongSelf->_completion;
strongSelf->_completion = nil;

fetcher.comment = @"DeleteTask";
GTMSessionFetcher *fetcher = [strongSelf.fetcherService fetcherWithRequest:request];
strongSelf->_fetcher = fetcher;

fetcher.comment = @"DeleteTask";

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-retain-cycles"
_fetcherCompletion = ^(NSData *_Nullable data, NSError *_Nullable error) {
if (!self.error) {
self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference];
}
if (callback) {
callback(self.error);
}
self->_fetcherCompletion = nil;
};
strongSelf->_fetcherCompletion = ^(NSData *_Nullable data, NSError *_Nullable error) {
if (!self.error) {
self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference];
}
if (callback) {
callback(self.error);
}
self->_fetcherCompletion = nil;
};
#pragma clang diangostic pop

__weak FIRStorageDeleteTask *weakSelf = self;
[fetcher beginFetchWithCompletionHandler:^(NSData *_Nullable data, NSError *_Nullable error) {
weakSelf.fetcherCompletion(data, error);
[fetcher beginFetchWithCompletionHandler:^(NSData *_Nullable data, NSError *_Nullable error) {
weakSelf.fetcherCompletion(data, error);
}];
}];
}

Expand Down
Loading