Skip to content

Commit 98e0f52

Browse files
authored
Merge pull request #32 from optimizely/josh.wang/datafile_manager/download_datafile
Download and persist datafile in datafile manager
2 parents c5b99b9 + fb0fb9f commit 98e0f52

24 files changed

+695
-35
lines changed

OptimizelySDKDatafileManager/OptimizelySDKDatafileManager.xcodeproj/project.pbxproj

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,22 @@
1616
2DB3D1891DC818EC00ECF72E /* OPTLYDatafileManagerBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 2DB3D1831DC8187900ECF72E /* OPTLYDatafileManagerBuilder.m */; };
1717
2DB3D18A1DC818F200ECF72E /* OPTLYDatafileManagerBuilderTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 2DB3D1861DC818D500ECF72E /* OPTLYDatafileManagerBuilderTest.m */; };
1818
2DB3D18B1DC818F200ECF72E /* OPTLYDatafileManagerBuilderTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 2DB3D1861DC818D500ECF72E /* OPTLYDatafileManagerBuilderTest.m */; };
19+
2DCC50D31DDA7D81006C9815 /* OPTLYDatafileManagerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 2DCC50D21DDA7D81006C9815 /* OPTLYDatafileManagerTest.m */; };
20+
2DCC50D41DDA7D81006C9815 /* OPTLYDatafileManagerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 2DCC50D21DDA7D81006C9815 /* OPTLYDatafileManagerTest.m */; };
21+
2DCC50EF1DDBD19C006C9815 /* OPTLYTestHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 2DCC50EC1DDBD183006C9815 /* OPTLYTestHelper.m */; };
22+
2DCC50F01DDBD19D006C9815 /* OPTLYTestHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 2DCC50EC1DDBD183006C9815 /* OPTLYTestHelper.m */; };
23+
2DCC51001DDBD7DD006C9815 /* BucketerTestsDatafile.json in Resources */ = {isa = PBXBuildFile; fileRef = 2DCC50F41DDBD219006C9815 /* BucketerTestsDatafile.json */; };
24+
2DCC51011DDBD7DD006C9815 /* datafile_6372300739.json in Resources */ = {isa = PBXBuildFile; fileRef = 2DCC50F51DDBD219006C9815 /* datafile_6372300739.json */; };
25+
2DCC51021DDBD7DD006C9815 /* test_data_10_experiments.json in Resources */ = {isa = PBXBuildFile; fileRef = 2DCC50F61DDBD219006C9815 /* test_data_10_experiments.json */; };
26+
2DCC51031DDBD7DD006C9815 /* test_data_25_experiments.json in Resources */ = {isa = PBXBuildFile; fileRef = 2DCC50F71DDBD219006C9815 /* test_data_25_experiments.json */; };
27+
2DCC51041DDBD7DD006C9815 /* test_data_50_experiments.json in Resources */ = {isa = PBXBuildFile; fileRef = 2DCC50F81DDBD219006C9815 /* test_data_50_experiments.json */; };
28+
2DCC51051DDBD7DD006C9815 /* validator_whitelisting_test_datafile.json in Resources */ = {isa = PBXBuildFile; fileRef = 2DCC50F91DDBD219006C9815 /* validator_whitelisting_test_datafile.json */; };
29+
2DCC51061DDBD7DD006C9815 /* BucketerTestsDatafile.json in Resources */ = {isa = PBXBuildFile; fileRef = 2DCC50F41DDBD219006C9815 /* BucketerTestsDatafile.json */; };
30+
2DCC51071DDBD7DD006C9815 /* datafile_6372300739.json in Resources */ = {isa = PBXBuildFile; fileRef = 2DCC50F51DDBD219006C9815 /* datafile_6372300739.json */; };
31+
2DCC51081DDBD7DD006C9815 /* test_data_10_experiments.json in Resources */ = {isa = PBXBuildFile; fileRef = 2DCC50F61DDBD219006C9815 /* test_data_10_experiments.json */; };
32+
2DCC51091DDBD7DD006C9815 /* test_data_25_experiments.json in Resources */ = {isa = PBXBuildFile; fileRef = 2DCC50F71DDBD219006C9815 /* test_data_25_experiments.json */; };
33+
2DCC510A1DDBD7DD006C9815 /* test_data_50_experiments.json in Resources */ = {isa = PBXBuildFile; fileRef = 2DCC50F81DDBD219006C9815 /* test_data_50_experiments.json */; };
34+
2DCC510B1DDBD7DD006C9815 /* validator_whitelisting_test_datafile.json in Resources */ = {isa = PBXBuildFile; fileRef = 2DCC50F91DDBD219006C9815 /* validator_whitelisting_test_datafile.json */; };
1935
6D5CBB24D7CD0C622634D15B /* Pods_OptimizelySDKDatafileManagerTVOSTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E878B599943D437831DAA7F /* Pods_OptimizelySDKDatafileManagerTVOSTests.framework */; };
2036
7C30D664EDAC58887076AE8E /* Pods_OptimizelySDKDatafileManageriOSTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F11A4F80C7960C4907845910 /* Pods_OptimizelySDKDatafileManageriOSTests.framework */; };
2137
8160880F9C1EE3663169C1F5 /* Pods_OptimizelySDKDatafileManageriOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8E531AA1D0D78410E6B99080 /* Pods_OptimizelySDKDatafileManageriOS.framework */; };
@@ -97,6 +113,15 @@
97113
2DB3D1821DC8187900ECF72E /* OPTLYDatafileManagerBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OPTLYDatafileManagerBuilder.h; sourceTree = "<group>"; };
98114
2DB3D1831DC8187900ECF72E /* OPTLYDatafileManagerBuilder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OPTLYDatafileManagerBuilder.m; sourceTree = "<group>"; };
99115
2DB3D1861DC818D500ECF72E /* OPTLYDatafileManagerBuilderTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OPTLYDatafileManagerBuilderTest.m; sourceTree = "<group>"; };
116+
2DCC50D21DDA7D81006C9815 /* OPTLYDatafileManagerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OPTLYDatafileManagerTest.m; sourceTree = "<group>"; };
117+
2DCC50EB1DDBD183006C9815 /* OPTLYTestHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OPTLYTestHelper.h; sourceTree = "<group>"; };
118+
2DCC50EC1DDBD183006C9815 /* OPTLYTestHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OPTLYTestHelper.m; sourceTree = "<group>"; };
119+
2DCC50F41DDBD219006C9815 /* BucketerTestsDatafile.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = BucketerTestsDatafile.json; path = TestData/BucketerTestsDatafile.json; sourceTree = "<group>"; };
120+
2DCC50F51DDBD219006C9815 /* datafile_6372300739.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = datafile_6372300739.json; path = TestData/datafile_6372300739.json; sourceTree = "<group>"; };
121+
2DCC50F61DDBD219006C9815 /* test_data_10_experiments.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = test_data_10_experiments.json; path = TestData/test_data_10_experiments.json; sourceTree = "<group>"; };
122+
2DCC50F71DDBD219006C9815 /* test_data_25_experiments.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = test_data_25_experiments.json; path = TestData/test_data_25_experiments.json; sourceTree = "<group>"; };
123+
2DCC50F81DDBD219006C9815 /* test_data_50_experiments.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = test_data_50_experiments.json; path = TestData/test_data_50_experiments.json; sourceTree = "<group>"; };
124+
2DCC50F91DDBD219006C9815 /* validator_whitelisting_test_datafile.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = validator_whitelisting_test_datafile.json; path = TestData/validator_whitelisting_test_datafile.json; sourceTree = "<group>"; };
100125
2FEFFF84C21046FA94F7615A /* Pods-OptimizelySDKDatafileManageriOSTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OptimizelySDKDatafileManageriOSTests.release.xcconfig"; path = "../Pods/Target Support Files/Pods-OptimizelySDKDatafileManageriOSTests/Pods-OptimizelySDKDatafileManageriOSTests.release.xcconfig"; sourceTree = "<group>"; };
101126
3C0F2EF1551F96713F44A84E /* Pods-OptimizelySDKDatafileManagerTVOSTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OptimizelySDKDatafileManagerTVOSTests.release.xcconfig"; path = "../Pods/Target Support Files/Pods-OptimizelySDKDatafileManagerTVOSTests/Pods-OptimizelySDKDatafileManagerTVOSTests.release.xcconfig"; sourceTree = "<group>"; };
102127
57C3406734E932C4DD563494 /* Pods_OptimizelySDKDatafileManagerTVOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_OptimizelySDKDatafileManagerTVOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -168,6 +193,19 @@
168193
/* End PBXFrameworksBuildPhase section */
169194

170195
/* Begin PBXGroup section */
196+
2DCC50F31DDBD20E006C9815 /* TestData */ = {
197+
isa = PBXGroup;
198+
children = (
199+
2DCC50F41DDBD219006C9815 /* BucketerTestsDatafile.json */,
200+
2DCC50F51DDBD219006C9815 /* datafile_6372300739.json */,
201+
2DCC50F61DDBD219006C9815 /* test_data_10_experiments.json */,
202+
2DCC50F71DDBD219006C9815 /* test_data_25_experiments.json */,
203+
2DCC50F81DDBD219006C9815 /* test_data_50_experiments.json */,
204+
2DCC50F91DDBD219006C9815 /* validator_whitelisting_test_datafile.json */,
205+
);
206+
name = TestData;
207+
sourceTree = "<group>";
208+
};
171209
6AE0BFC884AFE1AFC12765CF /* Pods */ = {
172210
isa = PBXGroup;
173211
children = (
@@ -231,8 +269,12 @@
231269
isa = PBXGroup;
232270
children = (
233271
EA3C68CC1DC1E75900C578CA /* OptimizelySDKDatafileManagerTests-Info.plist */,
272+
2DCC50EB1DDBD183006C9815 /* OPTLYTestHelper.h */,
273+
2DCC50EC1DDBD183006C9815 /* OPTLYTestHelper.m */,
234274
EA3C68CA1DC1E75900C578CA /* OptimizelySDKDatafileManagerTests.m */,
235275
2DB3D1861DC818D500ECF72E /* OPTLYDatafileManagerBuilderTest.m */,
276+
2DCC50D21DDA7D81006C9815 /* OPTLYDatafileManagerTest.m */,
277+
2DCC50F31DDBD20E006C9815 /* TestData */,
236278
);
237279
path = OptimizelySDKDatafileManagerTests;
238280
sourceTree = "<group>";
@@ -466,6 +508,12 @@
466508
isa = PBXResourcesBuildPhase;
467509
buildActionMask = 2147483647;
468510
files = (
511+
2DCC51041DDBD7DD006C9815 /* test_data_50_experiments.json in Resources */,
512+
2DCC51021DDBD7DD006C9815 /* test_data_10_experiments.json in Resources */,
513+
2DCC51001DDBD7DD006C9815 /* BucketerTestsDatafile.json in Resources */,
514+
2DCC51011DDBD7DD006C9815 /* datafile_6372300739.json in Resources */,
515+
2DCC51031DDBD7DD006C9815 /* test_data_25_experiments.json in Resources */,
516+
2DCC51051DDBD7DD006C9815 /* validator_whitelisting_test_datafile.json in Resources */,
469517
);
470518
runOnlyForDeploymentPostprocessing = 0;
471519
};
@@ -480,6 +528,12 @@
480528
isa = PBXResourcesBuildPhase;
481529
buildActionMask = 2147483647;
482530
files = (
531+
2DCC510A1DDBD7DD006C9815 /* test_data_50_experiments.json in Resources */,
532+
2DCC51081DDBD7DD006C9815 /* test_data_10_experiments.json in Resources */,
533+
2DCC51061DDBD7DD006C9815 /* BucketerTestsDatafile.json in Resources */,
534+
2DCC51071DDBD7DD006C9815 /* datafile_6372300739.json in Resources */,
535+
2DCC51091DDBD7DD006C9815 /* test_data_25_experiments.json in Resources */,
536+
2DCC510B1DDBD7DD006C9815 /* validator_whitelisting_test_datafile.json in Resources */,
483537
);
484538
runOnlyForDeploymentPostprocessing = 0;
485539
};
@@ -652,8 +706,10 @@
652706
isa = PBXSourcesBuildPhase;
653707
buildActionMask = 2147483647;
654708
files = (
709+
2DCC50EF1DDBD19C006C9815 /* OPTLYTestHelper.m in Sources */,
655710
2DB3D18A1DC818F200ECF72E /* OPTLYDatafileManagerBuilderTest.m in Sources */,
656711
2DB3D1751DC816C600ECF72E /* OptimizelySDKDatafileManagerTests.m in Sources */,
712+
2DCC50D31DDA7D81006C9815 /* OPTLYDatafileManagerTest.m in Sources */,
657713
);
658714
runOnlyForDeploymentPostprocessing = 0;
659715
};
@@ -670,8 +726,10 @@
670726
isa = PBXSourcesBuildPhase;
671727
buildActionMask = 2147483647;
672728
files = (
729+
2DCC50F01DDBD19D006C9815 /* OPTLYTestHelper.m in Sources */,
673730
2DB3D18B1DC818F200ECF72E /* OPTLYDatafileManagerBuilderTest.m in Sources */,
674731
2DB3D1791DC816C700ECF72E /* OptimizelySDKDatafileManagerTests.m in Sources */,
732+
2DCC50D41DDA7D81006C9815 /* OPTLYDatafileManagerTest.m in Sources */,
675733
);
676734
runOnlyForDeploymentPostprocessing = 0;
677735
};

OptimizelySDKDatafileManager/OptimizelySDKDatafileManager/OPTLYDatafileManager.h

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,29 +16,22 @@
1616

1717
#import <Foundation/Foundation.h>
1818
#import "OPTLYDatafileManagerBuilder.h"
19-
#import <OptimizelySDKShared/OPTLYHTTPRequestManager.h>
19+
#import <OptimizelySDKCore/OPTLYErrorHandler.h>
2020
#import <OptimizelySDKCore/OPTLYLogger.h>
21+
#import <OptimizelySDKShared/OPTLYDatafileManager.h>
22+
#import <OptimizelySDKShared/OPTLYHTTPRequestManager.h>
2123

22-
@protocol OPTLYLogger;
23-
24-
@protocol OPTLYDatafileManager <NSObject>
25-
26-
/**
27-
* Request the datafile for the project ID
28-
* @param projectId The project ID of the datafile to request.
29-
* @param completion Completion handler.
30-
*/
31-
- (void)requestDatafile:(nonnull NSString *)projectId
32-
completionHandler:(nullable OPTLYHTTPRequestManagerResponse)completion;
3324

34-
@end
25+
@protocol OPTLYErrorHandler, OPTLYLogger;
3526

3627
@interface OPTLYDatafileManager : NSObject<OPTLYDatafileManager>
3728

3829
/// The time interval to regularly fetch the datafile.
3930
@property (nonatomic, readonly) NSTimeInterval datafileFetchInterval;
4031
/// The project ID of the datafile this datafile manager will monitor
4132
@property (nonatomic, readonly, strong, nonnull) NSString *projectId;
33+
/// The error handler to be used for the manager, client, and all subcomponents
34+
@property (nonatomic, readonly, strong, nullable) id<OPTLYErrorHandler> errorHandler;
4235
/// A logger for the OPTLYDatafileManager to log messages.
4336
@property (nonatomic, readonly, strong, nonnull) id<OPTLYLogger> logger;
4437

OptimizelySDKDatafileManager/OptimizelySDKDatafileManager/OPTLYDatafileManager.m

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,19 @@
1515
***************************************************************************/
1616

1717
#import "OPTLYDatafileManager.h"
18+
#import <OptimizelySDKShared/OPTLYDataStore.h>
19+
#import <OptimizelySDKShared/OPTLYNetworkService.h>
1820

1921
static NSString *const kCDNAddressFormat = @"https://cdn.optimizely.com/json/%@.json";
2022
NSTimeInterval const kDefaultDatafileFetchInterval = 0;
2123

24+
@interface OPTLYDatafileManager ()
25+
26+
@property OPTLYDataStore *dataStore;
27+
@property OPTLYNetworkService *networkService;
28+
29+
@end
30+
2231
@implementation OPTLYDatafileManager
2332

2433
+ (nullable instancetype)initWithBuilderBlock:(nonnull OPTLYDatafileManagerBuilderBlock)block {
@@ -32,7 +41,14 @@ - (instancetype)initWithBuilder:(OPTLYDatafileManagerBuilder *)builder {
3241
_datafileFetchInterval = kDefaultDatafileFetchInterval;
3342
_datafileFetchInterval = builder.datafileFetchInterval;
3443
_projectId = builder.projectId;
44+
_errorHandler = builder.errorHandler;
3545
_logger = builder.logger;
46+
_networkService = [OPTLYNetworkService new];
47+
_dataStore = [OPTLYDataStore new];
48+
49+
// download datafile when we start the datafile manager
50+
[self downloadDatafile:self.projectId completionHandler:nil];
51+
3652
// Only fetch the datafile if the polling interval is greater than 0
3753
if (self.datafileFetchInterval > 0) {
3854
// TODO: Josh W. start timer to poll for the datafile
@@ -45,12 +61,32 @@ - (instancetype)initWithBuilder:(OPTLYDatafileManagerBuilder *)builder {
4561
}
4662
}
4763

48-
- (NSString *)datafileURLForProject:(NSString *)projectID {
49-
return [NSString stringWithFormat:kCDNAddressFormat, projectID];
64+
- (void)downloadDatafile:(NSString *)projectId completionHandler:(OPTLYHTTPRequestManagerResponse)completion {
65+
[self.networkService downloadProjectConfig:self.projectId
66+
completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
67+
if (error != nil) {
68+
[self.errorHandler handleError:error];
69+
}
70+
else if ([(NSHTTPURLResponse *)response statusCode] == 200) { // got datafile OK
71+
[self saveDatafile:data];
72+
}
73+
else {
74+
// TODO: Josh W. handle bad response
75+
}
76+
// call the completion handler
77+
if (completion != nil) {
78+
completion(data, response, error);
79+
}
80+
}];
5081
}
5182

52-
- (void)requestDatafile:(NSString *)projectId completionHandler:(OPTLYHTTPRequestManagerResponse)completion {
53-
83+
- (void)saveDatafile:(NSData *)datafile {
84+
NSError *error;
85+
[self.dataStore saveFile:self.projectId
86+
data:datafile
87+
type:OPTLYDataStoreDataTypeDatafile
88+
error:&error];
89+
5490
}
5591

5692
@end

OptimizelySDKDatafileManager/OptimizelySDKDatafileManager/OPTLYDatafileManagerBuilder.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#import <Foundation/Foundation.h>
1818

1919
@class OPTLYDatafileManagerBuilder;
20-
@protocol OPTLYLogger;
20+
@protocol OPTLYErrorHandler, OPTLYLogger;
2121

2222
/// This is a block that takes the biulder values
2323
typedef void (^OPTLYDatafileManagerBuilderBlock)(OPTLYDatafileManagerBuilder * _Nullable builder);
@@ -30,10 +30,11 @@ typedef void (^OPTLYDatafileManagerBuilderBlock)(OPTLYDatafileManagerBuilder * _
3030
@property (nonatomic, readwrite) NSTimeInterval datafileFetchInterval;
3131
/// The projectID of the project we want to get the datafile for.
3232
@property (nonatomic, readwrite, strong, nonnull) NSString *projectId;
33+
/// The error handler to be used for the manager, client, and all subcomponents
34+
@property (nonatomic, readwrite, strong, nullable) id<OPTLYErrorHandler> errorHandler;
3335
/// A logger to inject for purposes of error logging. If none is passed in, a default logger with log level `All` will be created.
3436
@property (nonatomic, readwrite, strong, nonnull) id<OPTLYLogger> logger;
3537

36-
3738
/// Create an Optimizely Datafile Manager Builder object.
3839
+ (nullable instancetype)builderWithBlock:(nonnull OPTLYDatafileManagerBuilderBlock)block;
3940

OptimizelySDKDatafileManager/OptimizelySDKDatafileManager/OPTLYDatafileManagerBuilder.m

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
***************************************************************************/
1616

1717
#import "OPTLYDatafileManagerBuilder.h"
18+
#import <OptimizelySDKCore/OPTLYErrorHandler.h>
1819
#import <OptimizelySDKCore/OPTLYLogger.h>
1920
#import <OptimizelySDKCore/OPTLYLoggerMessages.h>
2021

@@ -62,4 +63,11 @@ - (NSTimeInterval)datafileFetchInterval {
6263
return _logger;
6364
}
6465

66+
- (id<OPTLYErrorHandler>)errorHandler {
67+
if (!_errorHandler) {
68+
_errorHandler = [[OPTLYErrorHandlerNoOp alloc] init];
69+
}
70+
return _errorHandler;
71+
}
72+
6573
@end

0 commit comments

Comments
 (0)