Skip to content

Commit 7ba2540

Browse files
Queue Storage Tasks on separate queue
1 parent 91297fd commit 7ba2540

23 files changed

+565
-359
lines changed

Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,26 @@ - (void)testUnauthenticatedSimplePutData {
198198
[self waitForExpectations];
199199
}
200200

201+
- (void)testUnauthenticatedSimplePutDataInBackgroundQueue {
202+
XCTestExpectation *expectation =
203+
[self expectationWithDescription:@"testUnauthenticatedSimplePutDataInBackgroundQueue"];
204+
FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/testBytesUpload"];
205+
206+
NSData *data = [@"Hello World" dataUsingEncoding:NSUTF8StringEncoding];
207+
208+
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
209+
[ref putData:data
210+
metadata:nil
211+
completion:^(FIRStorageMetadata *metadata, NSError *error) {
212+
XCTAssertNotNil(metadata, "Metadata should not be nil");
213+
XCTAssertNil(error, "Error should be nil");
214+
[expectation fulfill];
215+
}];
216+
});
217+
218+
[self waitForExpectations];
219+
}
220+
201221
- (void)testUnauthenticatedSimplePutEmptyData {
202222
XCTestExpectation *expectation =
203223
[self expectationWithDescription:@"testUnauthenticatedSimplePutEmptyData"];
@@ -369,6 +389,24 @@ - (void)testUnauthenticatedSimpleGetData {
369389
[self waitForExpectations];
370390
}
371391

392+
- (void)testUnauthenticatedSimpleGetDataInBackgroundQueue {
393+
XCTestExpectation *expectation =
394+
[self expectationWithDescription:@"testUnauthenticatedSimpleGetDataInBackgroundQueue"];
395+
396+
FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/1mb"];
397+
398+
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
399+
[ref dataWithMaxSize:1 * 1024 * 1024
400+
completion:^(NSData *data, NSError *error) {
401+
XCTAssertNotNil(data, "Data should not be nil");
402+
XCTAssertNil(error, "Error should be nil");
403+
[expectation fulfill];
404+
}];
405+
});
406+
407+
[self waitForExpectations];
408+
}
409+
372410
- (void)testUnauthenticatedSimpleGetDataTooSmall {
373411
XCTestExpectation *expectation =
374412
[self expectationWithDescription:@"testUnauthenticatedSimpleGetDataTooSmall"];
@@ -615,6 +653,58 @@ - (void)testUnauthenticatedResumeGetFile {
615653
XCTAssertEqualWithAccuracy(sqrt(INT_MAX - 499), computationResult, 0.1);
616654
}
617655

656+
- (void)testUnauthenticatedResumeGetFileInBackgroundQueue {
657+
XCTestExpectation *expectation =
658+
[self expectationWithDescription:@"testUnauthenticatedResumeGetFileInBackgroundQueue"];
659+
660+
FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/1mb"];
661+
662+
NSURL *tmpDirURL = [NSURL fileURLWithPath:NSTemporaryDirectory()];
663+
NSURL *fileURL =
664+
[[tmpDirURL URLByAppendingPathComponent:@"hello"] URLByAppendingPathExtension:@"txt"];
665+
666+
__block long resumeAtBytes = 256 * 1024;
667+
__block long downloadedBytes = 0;
668+
__block double computationResult = 0;
669+
670+
FIRStorageDownloadTask *task = [ref writeToFile:fileURL];
671+
672+
[task observeStatus:FIRStorageTaskStatusSuccess
673+
handler:^(FIRStorageTaskSnapshot *snapshot) {
674+
XCTAssertEqualObjects([snapshot description], @"<State: Success>");
675+
[expectation fulfill];
676+
}];
677+
678+
[task observeStatus:FIRStorageTaskStatusProgress
679+
handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) {
680+
XCTAssertTrue([[snapshot description] containsString:@"State: Progress"] ||
681+
[[snapshot description] containsString:@"State: Resume"]);
682+
NSProgress *progress = snapshot.progress;
683+
XCTAssertGreaterThanOrEqual(progress.completedUnitCount, downloadedBytes);
684+
downloadedBytes = progress.completedUnitCount;
685+
if (progress.completedUnitCount > resumeAtBytes) {
686+
NSLog(@"Pausing");
687+
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
688+
[task pause];
689+
});
690+
resumeAtBytes = INT_MAX;
691+
}
692+
}];
693+
694+
[task observeStatus:FIRStorageTaskStatusPause
695+
handler:^(FIRStorageTaskSnapshot *snapshot) {
696+
XCTAssertEqualObjects([snapshot description], @"<State: Paused>");
697+
NSLog(@"Resuming");
698+
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
699+
[task resume];
700+
});
701+
}];
702+
703+
[self waitForExpectations];
704+
XCTAssertEqual(INT_MAX, resumeAtBytes);
705+
XCTAssertEqualWithAccuracy(sqrt(INT_MAX - 499), computationResult, 0.1);
706+
}
707+
618708
- (void)waitForExpectations {
619709
[self waitForExpectationsWithTimeout:kFIRStorageIntegrationTestTimeout
620710
handler:^(NSError *_Nullable error) {

Example/Storage/Tests/Unit/FIRStorageDeleteTests.m

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
@interface FIRStorageDeleteTests : XCTestCase
1919

2020
@property(strong, nonatomic) GTMSessionFetcherService *fetcherService;
21+
@property(nonatomic) dispatch_queue_t dispatchQueue;
2122
@property(strong, nonatomic) FIRStorageMetadata *metadata;
2223
@property(strong, nonatomic) FIRStorage *storage;
2324
@property(strong, nonatomic) id mockApp;
@@ -45,6 +46,8 @@ - (void)setUp {
4546
fetcherService:self.fetcherService
4647
authProvider:nil];
4748

49+
self.dispatchQueue = dispatch_queue_create("Test dispatch queue", DISPATCH_QUEUE_SERIAL);
50+
4851
self.storage = [FIRStorage storageForApp:self.mockApp];
4952
}
5053

@@ -76,6 +79,7 @@ - (void)testFetcherConfiguration {
7679
FIRStorageReference *ref = [[FIRStorageReference alloc] initWithStorage:self.storage path:path];
7780
FIRStorageDeleteTask *task = [[FIRStorageDeleteTask alloc] initWithReference:ref
7881
fetcherService:self.fetcherService
82+
dispatchQueue:self.dispatchQueue
7983
completion:^(NSError *error) {
8084
[expectation fulfill];
8185
}];
@@ -92,6 +96,7 @@ - (void)testSuccessfulFetch {
9296
FIRStorageReference *ref = [[FIRStorageReference alloc] initWithStorage:self.storage path:path];
9397
FIRStorageDeleteTask *task = [[FIRStorageDeleteTask alloc] initWithReference:ref
9498
fetcherService:self.fetcherService
99+
dispatchQueue:self.dispatchQueue
95100
completion:^(NSError *error) {
96101
XCTAssertEqual(error, nil);
97102
[expectation fulfill];
@@ -111,6 +116,7 @@ - (void)testUnsuccessfulFetchUnauthenticated {
111116
FIRStorageDeleteTask *task = [[FIRStorageDeleteTask alloc]
112117
initWithReference:ref
113118
fetcherService:self.fetcherService
119+
dispatchQueue:self.dispatchQueue
114120
completion:^(NSError *error) {
115121
XCTAssertEqual(error.code, FIRStorageErrorCodeUnauthenticated);
116122
[expectation fulfill];
@@ -130,6 +136,7 @@ - (void)testUnsuccessfulFetchUnauthorized {
130136
FIRStorageDeleteTask *task = [[FIRStorageDeleteTask alloc]
131137
initWithReference:ref
132138
fetcherService:self.fetcherService
139+
dispatchQueue:self.dispatchQueue
133140
completion:^(NSError *error) {
134141
XCTAssertEqual(error.code, FIRStorageErrorCodeUnauthorized);
135142
[expectation fulfill];
@@ -149,6 +156,7 @@ - (void)testUnsuccessfulFetchObjectDoesntExist {
149156
FIRStorageDeleteTask *task = [[FIRStorageDeleteTask alloc]
150157
initWithReference:ref
151158
fetcherService:self.fetcherService
159+
dispatchQueue:self.dispatchQueue
152160
completion:^(NSError *error) {
153161
XCTAssertEqual(error.code, FIRStorageErrorCodeObjectNotFound);
154162
[expectation fulfill];

Example/Storage/Tests/Unit/FIRStorageGetMetadataTests.m

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
@interface FIRStorageGetMetadataTests : XCTestCase
1919

2020
@property(strong, nonatomic) GTMSessionFetcherService *fetcherService;
21+
@property(nonatomic) dispatch_queue_t dispatchQueue;
2122
@property(strong, nonatomic) FIRStorageMetadata *metadata;
2223
@property(strong, nonatomic) FIRStorage *storage;
2324
@property(strong, nonatomic) id mockApp;
@@ -45,6 +46,8 @@ - (void)setUp {
4546
fetcherService:self.fetcherService
4647
authProvider:nil];
4748

49+
self.dispatchQueue = dispatch_queue_create("Test dispatch queue", DISPATCH_QUEUE_SERIAL);
50+
4851
self.storage = [FIRStorage storageForApp:self.mockApp];
4952
}
5053

@@ -77,6 +80,7 @@ - (void)testFetcherConfiguration {
7780
FIRStorageGetMetadataTask *task = [[FIRStorageGetMetadataTask alloc]
7881
initWithReference:ref
7982
fetcherService:self.fetcherService
83+
dispatchQueue:self.dispatchQueue
8084
completion:^(FIRStorageMetadata *metadata, NSError *error) {
8185
[expectation fulfill];
8286
}];
@@ -94,6 +98,7 @@ - (void)testSuccessfulFetch {
9498
FIRStorageGetMetadataTask *task = [[FIRStorageGetMetadataTask alloc]
9599
initWithReference:ref
96100
fetcherService:self.fetcherService
101+
dispatchQueue:self.dispatchQueue
97102
completion:^(FIRStorageMetadata *metadata, NSError *error) {
98103
XCTAssertEqualObjects(self.metadata.bucket, metadata.bucket);
99104
XCTAssertEqualObjects(self.metadata.name, metadata.name);
@@ -115,6 +120,7 @@ - (void)testUnsuccessfulFetchUnauthenticated {
115120
FIRStorageGetMetadataTask *task = [[FIRStorageGetMetadataTask alloc]
116121
initWithReference:ref
117122
fetcherService:self.fetcherService
123+
dispatchQueue:self.dispatchQueue
118124
completion:^(FIRStorageMetadata *metadata, NSError *error) {
119125
XCTAssertEqual(metadata, nil);
120126
XCTAssertEqual(error.code, FIRStorageErrorCodeUnauthenticated);
@@ -135,6 +141,7 @@ - (void)testUnsuccessfulFetchUnauthorized {
135141
FIRStorageGetMetadataTask *task = [[FIRStorageGetMetadataTask alloc]
136142
initWithReference:ref
137143
fetcherService:self.fetcherService
144+
dispatchQueue:self.dispatchQueue
138145
completion:^(FIRStorageMetadata *metadata, NSError *error) {
139146
XCTAssertEqual(metadata, nil);
140147
XCTAssertEqual(error.code, FIRStorageErrorCodeUnauthorized);
@@ -155,6 +162,7 @@ - (void)testUnsuccessfulFetchObjectDoesntExist {
155162
FIRStorageGetMetadataTask *task = [[FIRStorageGetMetadataTask alloc]
156163
initWithReference:ref
157164
fetcherService:self.fetcherService
165+
dispatchQueue:self.dispatchQueue
158166
completion:^(FIRStorageMetadata *metadata, NSError *error) {
159167
XCTAssertEqual(metadata, nil);
160168
XCTAssertEqual(error.code, FIRStorageErrorCodeObjectNotFound);
@@ -175,6 +183,7 @@ - (void)testUnsuccessfulFetchBadJSON {
175183
FIRStorageGetMetadataTask *task = [[FIRStorageGetMetadataTask alloc]
176184
initWithReference:ref
177185
fetcherService:self.fetcherService
186+
dispatchQueue:self.dispatchQueue
178187
completion:^(FIRStorageMetadata *metadata, NSError *error) {
179188
XCTAssertEqual(metadata, nil);
180189
XCTAssertEqual(error.code, FIRStorageErrorCodeUnknown);

Example/Storage/Tests/Unit/FIRStorageUpdateMetadataTests.m

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
@interface FIRStorageUpdateMetadataTests : XCTestCase
2020

2121
@property(strong, nonatomic) GTMSessionFetcherService *fetcherService;
22+
@property(nonatomic) dispatch_queue_t dispatchQueue;
2223
@property(strong, nonatomic) FIRStorageMetadata *metadata;
2324
@property(strong, nonatomic) FIRStorage *storage;
2425
@property(strong, nonatomic) id mockApp;
@@ -46,6 +47,8 @@ - (void)setUp {
4647
fetcherService:self.fetcherService
4748
authProvider:nil];
4849

50+
self.dispatchQueue = dispatch_queue_create("Test dispatch queue", DISPATCH_QUEUE_SERIAL);
51+
4952
self.storage = [FIRStorage storageForApp:self.mockApp];
5053
}
5154

@@ -84,6 +87,7 @@ - (void)testFetcherConfiguration {
8487
FIRStorageUpdateMetadataTask *task = [[FIRStorageUpdateMetadataTask alloc]
8588
initWithReference:ref
8689
fetcherService:self.fetcherService
90+
dispatchQueue:self.dispatchQueue
8791
metadata:self.metadata
8892
completion:^(FIRStorageMetadata *_Nullable metadata, NSError *_Nullable error) {
8993
[expectation fulfill];
@@ -102,6 +106,7 @@ - (void)testSuccessfulFetch {
102106
FIRStorageUpdateMetadataTask *task = [[FIRStorageUpdateMetadataTask alloc]
103107
initWithReference:ref
104108
fetcherService:self.fetcherService
109+
dispatchQueue:self.dispatchQueue
105110
metadata:self.metadata
106111
completion:^(FIRStorageMetadata *_Nullable metadata, NSError *_Nullable error) {
107112
XCTAssertEqualObjects(self.metadata.bucket, metadata.bucket);
@@ -124,6 +129,7 @@ - (void)testUnsuccessfulFetchUnauthenticated {
124129
FIRStorageUpdateMetadataTask *task = [[FIRStorageUpdateMetadataTask alloc]
125130
initWithReference:ref
126131
fetcherService:self.fetcherService
132+
dispatchQueue:self.dispatchQueue
127133
metadata:self.metadata
128134
completion:^(FIRStorageMetadata *_Nullable metadata, NSError *_Nullable error) {
129135
XCTAssertNil(metadata);
@@ -145,6 +151,7 @@ - (void)testUnsuccessfulFetchUnauthorized {
145151
FIRStorageUpdateMetadataTask *task = [[FIRStorageUpdateMetadataTask alloc]
146152
initWithReference:ref
147153
fetcherService:self.fetcherService
154+
dispatchQueue:self.dispatchQueue
148155
metadata:self.metadata
149156
completion:^(FIRStorageMetadata *_Nullable metadata, NSError *_Nullable error) {
150157
XCTAssertNil(metadata);
@@ -166,6 +173,7 @@ - (void)testUnsuccessfulFetchObjectDoesntExist {
166173
FIRStorageUpdateMetadataTask *task = [[FIRStorageUpdateMetadataTask alloc]
167174
initWithReference:ref
168175
fetcherService:self.fetcherService
176+
dispatchQueue:self.dispatchQueue
169177
metadata:self.metadata
170178
completion:^(FIRStorageMetadata *_Nullable metadata, NSError *_Nullable error) {
171179
XCTAssertNil(metadata);
@@ -187,6 +195,7 @@ - (void)testUnsuccessfulFetchBadJSON {
187195
FIRStorageUpdateMetadataTask *task = [[FIRStorageUpdateMetadataTask alloc]
188196
initWithReference:ref
189197
fetcherService:self.fetcherService
198+
dispatchQueue:self.dispatchQueue
190199
metadata:self.metadata
191200
completion:^(FIRStorageMetadata *_Nullable metadata, NSError *_Nullable error) {
192201
XCTAssertNil(metadata);

Firebase/Storage/FIRStorage.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ - (instancetype)initWithApp:(FIRApp *)app
149149
_app = app;
150150
_auth = auth;
151151
_storageBucket = bucket;
152+
_dispatchQueue = dispatch_queue_create("com.google.firebase.storage", DISPATCH_QUEUE_SERIAL);
152153
_fetcherServiceForApp = [FIRStorage fetcherServiceForApp:_app bucket:bucket auth:auth];
153154
_maxDownloadRetryTime = 600.0;
154155
_maxOperationRetryTime = 120.0;

Firebase/Storage/FIRStorageDeleteTask.m

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,43 +30,53 @@ - (void)dealloc {
3030

3131
- (instancetype)initWithReference:(FIRStorageReference *)reference
3232
fetcherService:(GTMSessionFetcherService *)service
33+
dispatchQueue:(dispatch_queue_t)queue
3334
completion:(FIRStorageVoidError)completion {
34-
self = [super initWithReference:reference fetcherService:service];
35+
self = [super initWithReference:reference fetcherService:service dispatchQueue:queue];
3536
if (self) {
3637
_completion = [completion copy];
3738
}
3839
return self;
3940
}
4041

4142
- (void)enqueue {
42-
NSMutableURLRequest *request = [self.baseRequest mutableCopy];
43-
request.HTTPMethod = @"DELETE";
44-
request.timeoutInterval = self.reference.storage.maxOperationRetryTime;
43+
__weak FIRStorageDeleteTask *weakSelf = self;
44+
45+
[self dispatchAsync:^() {
46+
FIRStorageDeleteTask *strongSelf = weakSelf;
47+
48+
if (!strongSelf) {
49+
return;
50+
}
4551

46-
FIRStorageVoidError callback = _completion;
47-
_completion = nil;
52+
NSMutableURLRequest *request = [self.baseRequest mutableCopy];
53+
request.HTTPMethod = @"DELETE";
54+
request.timeoutInterval = self.reference.storage.maxOperationRetryTime;
4855

49-
GTMSessionFetcher *fetcher = [self.fetcherService fetcherWithRequest:request];
50-
_fetcher = fetcher;
56+
FIRStorageVoidError callback = strongSelf->_completion;
57+
strongSelf->_completion = nil;
5158

52-
fetcher.comment = @"DeleteTask";
59+
GTMSessionFetcher *fetcher = [self.fetcherService fetcherWithRequest:request];
60+
strongSelf->_fetcher = fetcher;
61+
62+
fetcher.comment = @"DeleteTask";
5363

5464
#pragma clang diagnostic push
5565
#pragma clang diagnostic ignored "-Warc-retain-cycles"
56-
_fetcherCompletion = ^(NSData *_Nullable data, NSError *_Nullable error) {
57-
if (!self.error) {
58-
self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference];
59-
}
60-
if (callback) {
61-
callback(self.error);
62-
}
63-
self->_fetcherCompletion = nil;
64-
};
66+
strongSelf->_fetcherCompletion = ^(NSData *_Nullable data, NSError *_Nullable error) {
67+
if (!self.error) {
68+
self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference];
69+
}
70+
if (callback) {
71+
callback(self.error);
72+
}
73+
self->_fetcherCompletion = nil;
74+
};
6575
#pragma clang diangostic pop
6676

67-
__weak FIRStorageDeleteTask *weakSelf = self;
68-
[fetcher beginFetchWithCompletionHandler:^(NSData *_Nullable data, NSError *_Nullable error) {
69-
weakSelf.fetcherCompletion(data, error);
77+
[fetcher beginFetchWithCompletionHandler:^(NSData *_Nullable data, NSError *_Nullable error) {
78+
weakSelf.fetcherCompletion(data, error);
79+
}];
7080
}];
7181
}
7282

0 commit comments

Comments
 (0)