Skip to content

Commit d74dae0

Browse files
authored
Save activated ExperimentsDescriptions in DB (#11259)
* Add activated experiment metadata and payload keys to experiments table * Call updateActivatedExperiments in activation method * Update key name for experiments table * Update test to include activation call * Update DB manager for Active experiments payload and metadata * Fix metadata naming * add comment * Don't save experiments metadata b/c it isn't required to diff experiments * Add extra assertion for test * Address PR comments
1 parent 304b6af commit d74dae0

File tree

5 files changed

+91
-2
lines changed

5 files changed

+91
-2
lines changed

FirebaseRemoteConfig/Sources/RCNConfigDBManager.m

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -827,12 +827,22 @@ - (void)loadExperimentWithCompletionHandler:(RCNDBCompletion)handler {
827827
experimentMetadata = [[NSMutableDictionary alloc] init];
828828
}
829829

830+
/// Load activated experiments payload.
831+
NSMutableArray *activeExperimentPayloads =
832+
[strongSelf loadExperimentTableFromKey:@RCNExperimentTableKeyActivePayload];
833+
if (!activeExperimentPayloads) {
834+
activeExperimentPayloads = [[NSMutableArray alloc] init];
835+
}
836+
830837
if (handler) {
831838
dispatch_async(dispatch_get_main_queue(), ^{
832839
handler(
833840
YES, @{
834841
@RCNExperimentTableKeyPayload : [experimentPayloads copy],
835-
@RCNExperimentTableKeyMetadata : [experimentMetadata copy]
842+
@RCNExperimentTableKeyMetadata : [experimentMetadata copy],
843+
/// Activated experiments only need ExperimentsDescriptions data, which
844+
/// experimentPayloads contains.
845+
@RCNExperimentTableKeyActivePayload : [activeExperimentPayloads copy]
836846
});
837847
});
838848
}

FirebaseRemoteConfig/Sources/RCNConfigDefines.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,6 @@
3030

3131
#define RCNExperimentTableKeyPayload "experiment_payload"
3232
#define RCNExperimentTableKeyMetadata "experiment_metadata"
33+
#define RCNExperimentTableKeyActivePayload "experiment_active_payload"
3334

3435
#endif

FirebaseRemoteConfig/Sources/RCNConfigExperiment.m

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ @interface RCNConfigExperiment ()
3232
NSMutableArray<NSData *> *experimentPayloads; ///< Experiment payloads.
3333
@property(nonatomic, strong)
3434
NSMutableDictionary<NSString *, id> *experimentMetadata; ///< Experiment metadata
35-
@property(nonatomic, strong) RCNConfigDBManager *DBManager; ///< Database Manager.
35+
@property(nonatomic, strong)
36+
NSMutableArray<NSData *> *activeExperimentPayloads; ///< Activated experiment payloads.
37+
@property(nonatomic, strong) RCNConfigDBManager *DBManager; ///< Database Manager.
3638
@property(nonatomic, strong) FIRExperimentController *experimentController;
3739
@property(nonatomic, strong) NSDateFormatter *experimentStartTimeDateFormatter;
3840
@end
@@ -45,6 +47,7 @@ - (instancetype)initWithDBManager:(RCNConfigDBManager *)DBManager
4547
if (self) {
4648
_experimentPayloads = [[NSMutableArray alloc] init];
4749
_experimentMetadata = [[NSMutableDictionary alloc] init];
50+
_activeExperimentPayloads = [[NSMutableArray alloc] init];
4851
_experimentStartTimeDateFormatter = [[NSDateFormatter alloc] init];
4952
[_experimentStartTimeDateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"];
5053
[_experimentStartTimeDateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
@@ -89,6 +92,23 @@ - (void)loadExperimentFromTable {
8992
if (result[@RCNExperimentTableKeyMetadata]) {
9093
strongSelf->_experimentMetadata = [result[@RCNExperimentTableKeyMetadata] mutableCopy];
9194
}
95+
96+
/// Load activated experiments payload and metadata.
97+
if (result[@RCNExperimentTableKeyActivePayload]) {
98+
[strongSelf->_activeExperimentPayloads removeAllObjects];
99+
for (NSData *experiment in result[@RCNExperimentTableKeyActivePayload]) {
100+
NSError *error;
101+
id experimentPayloadJSON = [NSJSONSerialization JSONObjectWithData:experiment
102+
options:kNilOptions
103+
error:&error];
104+
if (!experimentPayloadJSON || error) {
105+
FIRLogWarning(kFIRLoggerRemoteConfig, @"I-RCN000031",
106+
@"Activated experiment payload could not be parsed as JSON.");
107+
} else {
108+
[strongSelf->_activeExperimentPayloads addObject:experiment];
109+
}
110+
}
111+
}
92112
};
93113
[_DBManager loadExperimentWithCompletionHandler:completionHandler];
94114
}
@@ -131,6 +151,9 @@ - (void)updateExperimentsWithHandler:(void (^)(NSError *_Nullable))handler {
131151
lastStartTime:lastStartTime
132152
payloads:_experimentPayloads
133153
completionHandler:handler];
154+
155+
/// Update activated experiments payload and metadata in DB.
156+
[self updateActiveExperimentsInDB];
134157
}
135158

136159
- (void)updateExperimentStartTime {
@@ -157,6 +180,18 @@ - (void)updateExperimentStartTime {
157180
completionHandler:nil];
158181
}
159182

183+
- (void)updateActiveExperimentsInDB {
184+
/// Put current fetched experiment payloads into activated experiment DB.
185+
[_activeExperimentPayloads removeAllObjects];
186+
[_DBManager deleteExperimentTableForKey:@RCNExperimentTableKeyActivePayload];
187+
for (NSData *experiment in _experimentPayloads) {
188+
[_activeExperimentPayloads addObject:experiment];
189+
[_DBManager insertExperimentTableWithKey:@RCNExperimentTableKeyActivePayload
190+
value:experiment
191+
completionHandler:nil];
192+
}
193+
}
194+
160195
- (NSTimeInterval)latestStartTimeWithExistingLastStartTime:(NSTimeInterval)existingLastStartTime {
161196
return [self.experimentController
162197
latestExperimentStartTimestampBetweenTimestamp:existingLastStartTime

FirebaseRemoteConfig/Tests/Unit/RCNConfigDBManagerTest.m

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,45 @@ - (void)testWriteAndLoadExperiments {
504504
[self waitForExpectationsWithTimeout:_expectionTimeout handler:nil];
505505
}
506506

507+
- (void)testWriteAndLoadActivatedExperiments {
508+
XCTestExpectation *updateAndLoadExperimentExpectation =
509+
[self expectationWithDescription:@"Update and load experiment in database successfully"];
510+
511+
NSError *error;
512+
NSArray *payload2 = @[ @"ab", @"cd" ];
513+
NSData *payloadData2 = [NSJSONSerialization dataWithJSONObject:payload2
514+
options:NSJSONWritingPrettyPrinted
515+
error:&error];
516+
NSDictionary *payload3 =
517+
@{@"experiment_ID" : @"35667", @"experiment_activate_name" : @"activate_game"};
518+
NSData *payloadData3 = [NSJSONSerialization dataWithJSONObject:payload3
519+
options:NSJSONWritingPrettyPrinted
520+
error:&error];
521+
NSArray *payloads = @[ [[NSData alloc] init], payloadData2, payloadData3 ];
522+
523+
RCNDBCompletion writePayloadCompletion = ^(BOOL success, NSDictionary *result) {
524+
XCTAssertTrue(success);
525+
RCNDBCompletion readCompletion = ^(BOOL success, NSDictionary *experimentResults) {
526+
XCTAssertTrue(success);
527+
XCTAssertNotNil(experimentResults[@RCNExperimentTableKeyActivePayload]);
528+
XCTAssertEqualObjects(payloads, experimentResults[@RCNExperimentTableKeyActivePayload]);
529+
[updateAndLoadExperimentExpectation fulfill];
530+
};
531+
[self->_DBManager loadExperimentWithCompletionHandler:readCompletion];
532+
};
533+
[_DBManager insertExperimentTableWithKey:@RCNExperimentTableKeyActivePayload
534+
value:[[NSData alloc] init]
535+
completionHandler:nil];
536+
[_DBManager insertExperimentTableWithKey:@RCNExperimentTableKeyActivePayload
537+
value:payloadData2
538+
completionHandler:nil];
539+
[_DBManager insertExperimentTableWithKey:@RCNExperimentTableKeyActivePayload
540+
value:payloadData3
541+
completionHandler:writePayloadCompletion];
542+
543+
[self waitForExpectationsWithTimeout:_expectionTimeout handler:nil];
544+
}
545+
507546
- (void)testWriteAndLoadMetadataMultipleTimes {
508547
XCTestExpectation *updateAndLoadMetadataExpectation = [self
509548
expectationWithDescription:@"Update and load experiment metadata in database successfully"];

FirebaseRemoteConfig/Tests/Unit/RCNConfigExperimentTest.m

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,11 @@ - (instancetype)initWithAnalytics:(nullable id<FIRAnalyticsInterop>)analytics;
3838
@interface RCNConfigExperiment ()
3939
@property(nonatomic, copy) NSMutableArray *experimentPayloads;
4040
@property(nonatomic, copy) NSMutableDictionary *experimentMetadata;
41+
@property(nonatomic, copy) NSMutableArray *activeExperimentPayloads;
4142
@property(nonatomic, strong) RCNConfigDBManager *DBManager;
4243
- (NSTimeInterval)updateExperimentStartTime;
4344
- (void)loadExperimentFromTable;
45+
- (void)updateActiveExperimentsInDB;
4446
@end
4547

4648
@interface RCNConfigExperimentTest : XCTestCase {
@@ -232,6 +234,8 @@ - (void)testUpdateExperiments {
232234
XCTAssertNil(error);
233235
XCTAssertEqualObjects(experiment.experimentMetadata[@"last_experiment_start_time"],
234236
@(12345678));
237+
OCMVerify([experiment updateActiveExperimentsInDB]);
238+
XCTAssertEqualObjects(experiment.activeExperimentPayloads, @[ payloadData ]);
235239
}];
236240
}
237241

0 commit comments

Comments
 (0)