Skip to content

Commit 7fa0e43

Browse files
authored
Add 'upload packages' to allow prioritizers to pass arbitrary data to uploaders (#2470)
* Update some comments and move the event clock snapshot to the public header * Create the notion of an 'upload package' This will allow prioritizers to pass arbitrary data to the uploader that might be needed at upload time. * Make the -transportBytes protocol method required. * Make the rest of the framework use the upload package * Style * Remove cct.nanopb.c It was accidentally added.
1 parent 202c290 commit 7fa0e43

24 files changed

+350
-68
lines changed

GoogleDataTransport/GoogleDataTransport/Classes/GDTStorage.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ NS_ASSUME_NONNULL_BEGIN
5050
* @param eventHashes A set of event hashes to get the files of.
5151
* @return A set of equivalent length, containing all the filenames corresponding to the hashes.
5252
*/
53-
- (NSSet<NSURL *> *)eventHashesToFiles:(NSSet<NSNumber *> *)eventHashes;
53+
- (NSDictionary<NSNumber *, NSURL *> *)eventHashesToFiles:(NSSet<NSNumber *> *)eventHashes;
5454

5555
@end
5656

GoogleDataTransport/GoogleDataTransport/Classes/GDTStorage.m

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,16 +113,16 @@ - (void)removeEvents:(NSSet<NSNumber *> *)eventHashes target:(NSNumber *)target
113113
});
114114
}
115115

116-
- (NSSet<NSURL *> *)eventHashesToFiles:(NSSet<NSNumber *> *)eventHashes {
117-
NSMutableSet<NSURL *> *eventFiles = [[NSMutableSet alloc] init];
116+
- (NSDictionary<NSNumber *, NSURL *> *)eventHashesToFiles:(NSSet<NSNumber *> *)eventHashes {
117+
NSMutableDictionary<NSNumber *, NSURL *> *eventHashesToFiles = [[NSMutableDictionary alloc] init];
118118
dispatch_sync(_storageQueue, ^{
119119
for (NSNumber *hashNumber in eventHashes) {
120120
NSURL *eventURL = self.eventHashToFile[hashNumber];
121121
GDTAssert(eventURL, @"An event file URL couldn't be found for the given hash");
122-
[eventFiles addObject:eventURL];
122+
eventHashesToFiles[hashNumber] = eventURL;
123123
}
124124
});
125-
return eventFiles;
125+
return eventHashesToFiles;
126126
}
127127

128128
#pragma mark - Private helper methods

GoogleDataTransport/GoogleDataTransport/Classes/GDTUploadCoordinator.m

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#import "GDTConsoleLogger.h"
2323
#import "GDTRegistrar_Private.h"
2424
#import "GDTStorage.h"
25+
#import "GDTUploadPackage_Private.h"
2526

2627
@implementation GDTUploadCoordinator
2728

@@ -57,9 +58,10 @@ - (void)forceUploadEvents:(NSSet<NSNumber *> *)eventHashes target:(GDTTarget)tar
5758
GDTUploadCoordinatorForceUploadBlock forceUploadBlock = ^{
5859
GDTAssert(eventHashes.count, @"It doesn't make sense to force upload of 0 events");
5960
id<GDTUploader> uploader = registrar.targetToUploader[targetNumber];
60-
NSSet<NSURL *> *eventFiles = [self.storage eventHashesToFiles:eventHashes];
61+
GDTUploadPackage *package = [[GDTUploadPackage alloc] init];
62+
package.eventHashes = [eventHashes copy];
6163
GDTAssert(uploader, @"Target '%@' is missing an implementation", targetNumber);
62-
[uploader uploadEvents:eventFiles onComplete:self.onCompleteBlock];
64+
[uploader uploadPackage:package onComplete:self.onCompleteBlock];
6365
self->_targetToInFlightEventSet[targetNumber] = eventHashes;
6466
};
6567

@@ -157,16 +159,13 @@ - (void)checkPrioritizersAndUploadEvents {
157159
id<GDTUploader> uploader = strongSelf->_registrar.targetToUploader[target];
158160
GDTAssert(prioritizer && uploader, @"Target '%@' is missing an implementation", target);
159161
GDTUploadConditions conds = [self uploadConditions];
160-
NSSet<NSNumber *> *eventHashesToUpload =
161-
[[prioritizer eventsToUploadGivenConditions:conds] copy];
162-
if (eventHashesToUpload && eventHashesToUpload.count > 0) {
163-
NSAssert(eventHashesToUpload.count > 0, @"");
164-
NSSet<NSURL *> *eventFilesToUpload =
165-
[strongSelf.storage eventHashesToFiles:eventHashesToUpload];
166-
NSAssert(eventFilesToUpload.count == eventHashesToUpload.count,
162+
GDTUploadPackage *package = [[prioritizer uploadPackageWithConditions:conds] copy];
163+
package.storage = strongSelf.storage;
164+
if (package.eventHashes && package.eventHashes.count > 0) {
165+
NSAssert(package.eventHashesToFiles.count == package.eventHashes.count,
167166
@"There should be the same number of files to events");
168-
strongSelf->_targetToInFlightEventSet[target] = eventHashesToUpload;
169-
[uploader uploadEvents:eventFilesToUpload onComplete:self.onCompleteBlock];
167+
strongSelf->_targetToInFlightEventSet[target] = package.eventHashes;
168+
[uploader uploadPackage:package onComplete:self.onCompleteBlock];
170169
}
171170
}
172171
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright 2019 Google
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#import <GoogleDataTransport/GDTUploadPackage.h>
18+
19+
#import "GDTStorage_Private.h"
20+
#import "GDTUploadPackage_Private.h"
21+
22+
@implementation GDTUploadPackage
23+
24+
- (instancetype)init {
25+
self = [super init];
26+
if (self) {
27+
_storage = [GDTStorage sharedInstance];
28+
}
29+
return self;
30+
}
31+
32+
- (instancetype)copy {
33+
GDTUploadPackage *newPackage = [[GDTUploadPackage alloc] init];
34+
newPackage->_eventHashes = _eventHashes;
35+
return newPackage;
36+
}
37+
38+
- (NSUInteger)hash {
39+
return [_eventHashes hash];
40+
}
41+
42+
- (BOOL)isEqual:(id)object {
43+
return [self hash] == [object hash];
44+
}
45+
46+
- (void)setEventHashes:(NSSet<NSNumber *> *)eventHashes {
47+
if (eventHashes != _eventHashes) {
48+
_eventHashes = [eventHashes copy];
49+
}
50+
}
51+
52+
- (NSDictionary<NSNumber *, NSURL *> *)eventHashesToFiles {
53+
return [_storage eventHashesToFiles:_eventHashes];
54+
}
55+
56+
- (void)setStorage:(GDTStorage *)storage {
57+
if (storage != _storage) {
58+
_storage = storage;
59+
}
60+
}
61+
62+
@end

GoogleDataTransport/GoogleDataTransport/Classes/Private/GDTEvent_Private.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,6 @@ NS_ASSUME_NONNULL_BEGIN
2525
/** The serialized bytes of the event data object. */
2626
@property(nonatomic) NSData *dataObjectTransportBytes;
2727

28-
/** The clock snapshot at the time of the event. */
29-
@property(nonatomic) GDTClock *clockSnapshot;
30-
3128
@end
3229

3330
NS_ASSUME_NONNULL_END
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright 2019 Google
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#import <GoogleDataTransport/GDTUploadPackage.h>
18+
19+
@class GDTStorage;
20+
21+
@interface GDTUploadPackage ()
22+
23+
/** The storage object this upload package will use to resolve event hashes to files. */
24+
@property(nonatomic) GDTStorage *storage;
25+
26+
@end

GoogleDataTransport/GoogleDataTransport/Classes/Public/GDTEvent.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
#import "GDTEventDataObject.h"
2020

21+
@class GDTClock;
22+
2123
NS_ASSUME_NONNULL_BEGIN
2224

2325
/** The different possible quality of service specifiers. High values indicate high priority. */
@@ -56,6 +58,9 @@ typedef NS_ENUM(NSInteger, GDTEventQoS) {
5658
/** The quality of service tier this event belongs to. */
5759
@property(nonatomic) GDTEventQoS qosTier;
5860

61+
/** The clock snapshot at the time of the event. */
62+
@property(nonatomic) GDTClock *clockSnapshot;
63+
5964
/** A dictionary provided to aid prioritizers by allowing the passing of arbitrary data. It will be
6065
* retained by a copy in -copy, but not used for -hash.
6166
*/

GoogleDataTransport/GoogleDataTransport/Classes/Public/GDTEventDataObject.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ NS_ASSUME_NONNULL_BEGIN
2323
*/
2424
@protocol GDTEventDataObject <NSObject>
2525

26+
@required
27+
2628
/** Returns the serialized proto bytes of the implementing event proto.
2729
*
2830
* @return the serialized proto bytes of the implementing event proto.

GoogleDataTransport/GoogleDataTransport/Classes/Public/GDTPrioritizer.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
#import <Foundation/Foundation.h>
1818

19+
#import <GoogleDataTransport/GDTUploadPackage.h>
20+
1921
@class GDTEvent;
2022

2123
NS_ASSUME_NONNULL_BEGIN
@@ -46,7 +48,7 @@ typedef NS_OPTIONS(NSInteger, GDTUploadConditions) {
4648
*
4749
* @note A couple of things: 1. The event cannot be retained for longer than the execution time of
4850
* this method. 2. You should retain the event hashes, because those are returned in
49-
* -eventsForNextUpload.
51+
* -uploadPackageWithConditions.
5052
*
5153
* @param event The event to prioritize.
5254
*/
@@ -60,9 +62,10 @@ typedef NS_OPTIONS(NSInteger, GDTUploadConditions) {
6062
/** Returns a set of events to upload given a set of conditions.
6163
*
6264
* @param conditions A bit mask specifying the current upload conditions.
63-
* @return A set of events to upload with respect to the current conditions.
65+
* @return An object to be used by the uploader to determine file URLs to upload with respect to the
66+
* current conditions.
6467
*/
65-
- (NSSet<NSNumber *> *)eventsToUploadGivenConditions:(GDTUploadConditions)conditions;
68+
- (GDTUploadPackage *)uploadPackageWithConditions:(GDTUploadConditions)conditions;
6669

6770
@end
6871

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2019 Google
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#import <Foundation/Foundation.h>
18+
19+
/** This class is a container that's handed off to uploaders. */
20+
@interface GDTUploadPackage : NSObject
21+
22+
/** The set of event hashes in this upload package. */
23+
@property(nonatomic) NSSet<NSNumber *> *eventHashes;
24+
25+
/** A lazily-determined map of event hashes to their files. */
26+
@property(nonatomic, readonly) NSDictionary<NSNumber *, NSURL *> *eventHashesToFiles;
27+
28+
@end

GoogleDataTransport/GoogleDataTransport/Classes/Public/GDTUploader.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,13 @@ typedef void (^GDTUploaderCompletionBlock)(GDTTarget target,
3939

4040
/** Uploads events to the backend using this specific backend's chosen format.
4141
*
42-
* @param eventFiles The set of event files to upload.
43-
* @param onComplete A block to invoke upon completing the upload. Has two arguments:
44-
* - successfulUploads: The set of filenames uploaded successfully.
45-
* - unsuccessfulUploads: The set of filenames not uploaded successfully.
42+
* @param package The event package to upload.
43+
* @param onComplete A block to invoke upon completing the upload. Has three arguments:
44+
* - target: The GDTTarget that just uploaded.
45+
* - nextUploadAttemptUTC: A clock representing the next upload attempt.
46+
* - uploadError: An error object describing the upload error, or nil if upload was successful.
4647
*/
47-
- (void)uploadEvents:(NSSet<NSURL *> *)eventFiles onComplete:(GDTUploaderCompletionBlock)onComplete;
48+
- (void)uploadPackage:(GDTUploadPackage *)package onComplete:(GDTUploaderCompletionBlock)onComplete;
4849

4950
@end
5051

GoogleDataTransport/Tests/Integration/Helpers/GDTIntegrationTestPrioritizer.m

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
#import "GDTIntegrationTestPrioritizer.h"
1818

19+
#import "GDTIntegrationTestUploadPackage.h"
20+
1921
@interface GDTIntegrationTestPrioritizer ()
2022

2123
/** Events that are only supposed to be uploaded whilst on wifi. */
@@ -44,32 +46,35 @@ - (instancetype)init {
4446
}
4547

4648
- (void)prioritizeEvent:(GDTEvent *)event {
47-
dispatch_sync(_queue, ^{
48-
if (event.qosTier == GDTEventQoSWifiOnly) {
49-
[self.wifiOnlyEvents addObject:@(event.hash)];
49+
NSUInteger eventHash = event.hash;
50+
NSInteger qosTier = event.qosTier;
51+
dispatch_async(_queue, ^{
52+
if (qosTier == GDTEventQoSWifiOnly) {
53+
[self.wifiOnlyEvents addObject:@(eventHash)];
5054
} else {
51-
[self.nonWifiEvents addObject:@(event.hash)];
55+
[self.nonWifiEvents addObject:@(eventHash)];
5256
}
5357
});
5458
}
5559

5660
- (void)unprioritizeEvent:(NSNumber *)eventHash {
57-
dispatch_sync(_queue, ^{
61+
dispatch_async(_queue, ^{
5862
[self.wifiOnlyEvents removeObject:eventHash];
5963
[self.nonWifiEvents removeObject:eventHash];
6064
});
6165
}
6266

63-
- (nonnull NSSet<NSNumber *> *)eventsToUploadGivenConditions:(GDTUploadConditions)conditions {
64-
__block NSSet<NSNumber *> *events;
67+
- (GDTUploadPackage *)uploadPackageWithConditions:(GDTUploadConditions)conditions {
68+
__block GDTIntegrationTestUploadPackage *uploadPackage =
69+
[[GDTIntegrationTestUploadPackage alloc] init];
6570
dispatch_sync(_queue, ^{
6671
if ((conditions & GDTUploadConditionWifiData) == GDTUploadConditionWifiData) {
67-
events = self.wifiOnlyEvents;
72+
uploadPackage.eventHashes = self.wifiOnlyEvents;
6873
} else {
69-
events = self.nonWifiEvents;
74+
uploadPackage.eventHashes = self.nonWifiEvents;
7075
}
7176
});
72-
return events;
77+
return uploadPackage;
7378
}
7479

7580
@end
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* Copyright 2019 Google
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#import "GDTTestPrioritizer.h"
18+
19+
/** An upload package used in testing. */
20+
@interface GDTIntegrationTestUploadPackage : GDTUploadPackage
21+
22+
@end
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright 2019 Google
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#import "GDTIntegrationTestUploadPackage.h"
18+
19+
@implementation GDTIntegrationTestUploadPackage
20+
21+
@end

0 commit comments

Comments
 (0)