Skip to content
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

[Draft]Activate rollout metadata and send notification to Interop #12299

Closed
wants to merge 5 commits into from
Closed
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
54 changes: 54 additions & 0 deletions FirebaseRemoteConfig/Sources/FIRRemoteConfig.m
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
/// Notification when config is successfully activated
const NSNotificationName FIRRemoteConfigActivateNotification =
@"FIRRemoteConfigActivateNotification";
static NSString *const RolloutsStateDidChangeNotificationName =
@"RolloutsStateDidChangeNotification";

/// Listener for the get methods.
typedef void (^FIRRemoteConfigListener)(NSString *_Nonnull, NSDictionary *_Nonnull);
Expand Down Expand Up @@ -326,9 +328,14 @@ - (void)activateWithCompletion:(FIRRemoteConfigActivateChangeCompletion)completi
toSource:RCNDBSourceActive
forNamespace:self->_FIRNamespace];
strongSelf->_settings.lastApplyTimeInterval = [[NSDate date] timeIntervalSince1970];

// New config has been activated at this point
FIRLogDebug(kFIRLoggerRemoteConfig, @"I-RCN000069", @"Config activated.");
NSString *activeVersionNumber = [strongSelf->_settings updateLastActiveTemplateVersion];
[strongSelf->_configContent activatePersonalization];
NSArray<NSDictionary *> *activeRolloutMetadata =
[strongSelf->_configContent activateRolloutMetdata];
[self notifyRolloutsStateChange:activeRolloutMetadata versionNumber:activeVersionNumber];
// Update experiments only for 3p namespace
NSString *namespace = [strongSelf->_FIRNamespace
substringToIndex:[strongSelf->_FIRNamespace rangeOfString:@":"].location];
Expand Down Expand Up @@ -613,4 +620,51 @@ - (FIRConfigUpdateListenerRegistration *)addOnConfigUpdateListener:
return [self->_configRealtime addConfigUpdateListener:listener];
}

#pragma mark - Rollout

- (void)addRemoteConfigInteropSubscriber:(id<FIRRolloutsStateSubscriber>)subscriber {
[[NSNotificationCenter defaultCenter]
addObserverForName:RolloutsStateDidChangeNotificationName
object:self
queue:nil
usingBlock:^(NSNotification *_Nonnull notification) {
FIRRolloutsState *rolloutsState =
notification.userInfo[RolloutsStateDidChangeNotificationName];
[subscriber rolloutsStateDidChange:rolloutsState];
}];
}

- (void)notifyRolloutsStateChange:(NSArray<NSDictionary *> *)rolloutMetadata
versionNumber:(NSString *)versionNumber {
NSMutableArray<FIRRolloutAssignment *> *rolloutsAssignments = [[NSMutableArray alloc] init];
for (NSDictionary *metadata in rolloutMetadata) {
NSString *rolloutId = metadata[@"rollout_id"];
NSString *variantID = metadata[@"variant_id"];
NSArray<NSString *> *affectedParameterKeys = metadata[@"affected_parameter_keys"];
if (rolloutId && variantID && affectedParameterKeys) {
for (NSString *key in affectedParameterKeys) {
FIRRemoteConfigValue *value = [self configValueForKey:key];
if (value) {
FIRRolloutAssignment *assignment =
[[FIRRolloutAssignment alloc] initWithRolloutId:rolloutId
variantId:variantID
templateVersion:[versionNumber longLongValue]
parameterKey:key
parameterValue:value.stringValue];
[rolloutsAssignments addObject:assignment];
}
}
}
}
if (rolloutsAssignments.count > 0) {
FIRRolloutsState *rolloutsState =
[[FIRRolloutsState alloc] initWithAssignmentList:rolloutsAssignments];
FIRLogDebug(kFIRLoggerRemoteConfig, @"I-RCN000069", @"Send notification to Interop.");
[[NSNotificationCenter defaultCenter]
postNotificationName:RolloutsStateDidChangeNotificationName
object:self
userInfo:@{RolloutsStateDidChangeNotificationName : rolloutsState}];
}
}

@end
2 changes: 1 addition & 1 deletion FirebaseRemoteConfig/Sources/FIRRemoteConfigComponent.m
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ + (void)load {
- (void)registerRolloutsStateSubscriber:(id<FIRRolloutsStateSubscriber>)subscriber
for:(NSString * _Nonnull)namespace {
// TODO(Themisw): Adding the registered subscriber reference to the namespace instance
// [self.instances[namespace] addRemoteConfigInteropSubscriber:subscriber];
[self.instances[namespace] addRemoteConfigInteropSubscriber:subscriber];
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#import <FirebaseRemoteConfig/FIRRemoteConfig.h>
#import "RCNConfigSettings.h" // This import is needed to expose settings for the Swift API tests.

@import FirebaseRemoteConfigInterop;

@class FIROptions;
@class RCNConfigContent;
@class RCNConfigDBManager;
Expand Down Expand Up @@ -78,6 +80,8 @@ NS_ASSUME_NONNULL_BEGIN
configContent:(RCNConfigContent *)configContent
analytics:(nullable id<FIRAnalyticsInterop>)analytics;

- (void)addRemoteConfigInteropSubscriber:(id<FIRRolloutsStateSubscriber> _Nonnull)subscriber;

@end

NS_ASSUME_NONNULL_END
10 changes: 8 additions & 2 deletions FirebaseRemoteConfig/Sources/Private/RCNConfigSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,10 @@
@property(nonatomic, readwrite, assign) NSString *lastETag;
/// The timestamp of the last eTag update.
@property(nonatomic, readwrite, assign) NSTimeInterval lastETagUpdateTime;
// Last fetched template version.
@property(nonatomic, readwrite, assign) NSString *lastTemplateVersion;
/// Last fetched template version.
@property(nonatomic, readwrite, assign) NSString *lastFetchedTemplateVersion;
/// Last active template version.
@property(nonatomic, readwrite, assign) NSString *lastActiveTemplateVersion;

#pragma mark Throttling properties

Expand Down Expand Up @@ -134,6 +136,10 @@
/// indicates a server issue.
- (void)updateRealtimeExponentialBackoffTime;

/// Update last active template version from last fetched template version and return the active
/// template version number.
- (NSString *)updateLastActiveTemplateVersion;

/// Returns the difference between the Realtime backoff end time and the current time in a
/// NSTimeInterval format.
- (NSTimeInterval)getRealtimeBackoffInterval;
Expand Down
4 changes: 3 additions & 1 deletion FirebaseRemoteConfig/Sources/RCNConfigConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,7 @@ static NSString *const RCNFetchResponseKeyStateNoTemplate = @"NO_TEMPLATE";
static NSString *const RCNFetchResponseKeyStateNoChange = @"NO_CHANGE";
/// Template found, but evaluates to empty (e.g. all keys omitted).
static NSString *const RCNFetchResponseKeyStateEmptyConfig = @"EMPTY_CONFIG";
/// Template Version key
/// Fetched Template Version key
static NSString *const RCNFetchResponseKeyTemplateVersion = @"templateVersion";
/// Active Template Version key
static NSString *const RCNActiveKeyTemplateVersion = @"activeTemplateVersion";
3 changes: 3 additions & 0 deletions FirebaseRemoteConfig/Sources/RCNConfigContent.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ typedef NS_ENUM(NSInteger, RCNDBSource) {
/// Sets the fetched Personalization metadata to active.
- (void)activatePersonalization;

/// Sets the fetched rollout metadata to active and return the active rollout metadata.
- (NSArray<NSDictionary *> *)activateRolloutMetdata;

/// Gets the active config and Personalization metadata.
- (NSDictionary *)getConfigAndMetadataForNamespace:(NSString *)FIRNamespace;

Expand Down
19 changes: 19 additions & 0 deletions FirebaseRemoteConfig/Sources/RCNConfigContent.m
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ - (void)updateConfigContentWithResponse:(NSDictionary *)response
[self handleUpdateStateForConfigNamespace:currentNamespace
withEntries:response[RCNFetchResponseKeyEntries]];
[self handleUpdatePersonalization:response[RCNFetchResponseKeyPersonalizationMetadata]];
[self handleUpdateRolloutFetchedMetadata:response[RCNFetchResponseKeyRolloutMetadata]];
return;
}
}
Expand All @@ -290,6 +291,14 @@ - (void)activatePersonalization {
fromSource:RCNDBSourceActive];
}

- (NSArray<NSDictionary *> *)activateRolloutMetdata {
_activeRolloutMetadata = _fetchedRolloutMetadata;
[_DBManager insertOrUpdateRolloutTableWithKey:@RCNRolloutTableKeyActiveMetadata
value:_activeRolloutMetadata
completionHandler:nil];
return _activeRolloutMetadata;
}

#pragma mark State handling
- (void)handleNoChangeStateForConfigNamespace:(NSString *)currentNamespace {
if (!_fetchedConfig[currentNamespace]) {
Expand Down Expand Up @@ -353,6 +362,16 @@ - (void)handleUpdatePersonalization:(NSDictionary *)metadata {
[_DBManager insertOrUpdatePersonalizationConfig:metadata fromSource:RCNDBSourceFetched];
}

- (void)handleUpdateRolloutFetchedMetadata:(NSArray<NSDictionary *> *)metadata {
if (!metadata) {
return;
}
_fetchedRolloutMetadata = metadata;
[_DBManager insertOrUpdateRolloutTableWithKey:@RCNRolloutTableKeyFetchedMetadata
value:metadata
completionHandler:nil];
}

#pragma mark - getter/setter
- (NSDictionary *)fetchedConfig {
/// If this is the first time reading the fetchedConfig, we might still be reading it from the
Expand Down
2 changes: 1 addition & 1 deletion FirebaseRemoteConfig/Sources/RCNConfigFetch.m
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ - (instancetype)initWithContent:(RCNConfigContent *)content
_content = content;
_fetchSession = [self newFetchSession];
_options = options;
_templateVersionNumber = [self->_settings lastTemplateVersion];
_templateVersionNumber = [self->_settings lastFetchedTemplateVersion];
}
return self;
}
Expand Down
11 changes: 9 additions & 2 deletions FirebaseRemoteConfig/Sources/RCNConfigSettings.m
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ - (instancetype)initWithDatabaseManager:(RCNConfigDBManager *)manager
}

_isFetchInProgress = NO;
_lastTemplateVersion = [_userDefaultsManager lastTemplateVersion];
_lastFetchedTemplateVersion = [_userDefaultsManager lastFetchedTemplateVersion];
_lastActiveTemplateVersion = [_userDefaultsManager lastActiveTemplateVersion];
_realtimeExponentialBackoffRetryInterval =
[_userDefaultsManager currentRealtimeThrottlingRetryIntervalSeconds];
_realtimeExponentialBackoffThrottleEndTime = [_userDefaultsManager realtimeThrottleEndTime];
Expand Down Expand Up @@ -292,7 +293,7 @@ - (void)updateMetadataWithFetchSuccessStatus:(BOOL)fetchSuccess
[self updateLastFetchTimeInterval:[[NSDate date] timeIntervalSince1970]];
// Note: We expect the googleAppID to always be available.
_deviceContext = FIRRemoteConfigDeviceContextWithProjectIdentifier(_googleAppID);
[_userDefaultsManager setLastTemplateVersion:templateVersion];
[_userDefaultsManager setLastFetchedTemplateVersion:templateVersion];
}

[self updateMetadataTable];
Expand Down Expand Up @@ -377,6 +378,12 @@ - (void)updateMetadataTable {
[_DBManager insertMetadataTableWithValues:columnNameToValue completionHandler:nil];
}

- (NSString *)updateLastActiveTemplateVersion {
_lastActiveTemplateVersion = _lastFetchedTemplateVersion;
[_userDefaultsManager setLastActiveTemplateVersion:_lastActiveTemplateVersion];
return _lastActiveTemplateVersion;
}

#pragma mark - fetch request

/// Returns a fetch request with the latest device and config change.
Expand Down
4 changes: 3 additions & 1 deletion FirebaseRemoteConfig/Sources/RCNUserDefaultsManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ NS_ASSUME_NONNULL_BEGIN
/// Realtime retry count.
@property(nonatomic, assign) int realtimeRetryCount;
/// Last fetched template version.
@property(nonatomic, assign) NSString *lastTemplateVersion;
@property(nonatomic, assign) NSString *lastFetchedTemplateVersion;
/// Last active template version.
@property(nonatomic, assign) NSString *lastActiveTemplateVersion;

/// Designated initializer.
- (instancetype)initWithAppName:(NSString *)appName
Expand Down
19 changes: 17 additions & 2 deletions FirebaseRemoteConfig/Sources/RCNUserDefaultsManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ - (void)setLastETag:(NSString *)lastETag {
}
}

- (NSString *)lastTemplateVersion {
- (NSString *)lastFetchedTemplateVersion {
NSDictionary *userDefaults = [self instanceUserDefaults];
if ([userDefaults objectForKey:RCNFetchResponseKeyTemplateVersion]) {
return [userDefaults objectForKey:RCNFetchResponseKeyTemplateVersion];
Expand All @@ -120,12 +120,27 @@ - (NSString *)lastTemplateVersion {
return @"0";
}

- (void)setLastTemplateVersion:(NSString *)templateVersion {
- (void)setLastFetchedTemplateVersion:(NSString *)templateVersion {
if (templateVersion) {
[self setInstanceUserDefaultsValue:templateVersion forKey:RCNFetchResponseKeyTemplateVersion];
}
}

- (NSString *)lastActiveTemplateVersion {
NSDictionary *userDefaults = [self instanceUserDefaults];
if ([userDefaults objectForKey:RCNActiveKeyTemplateVersion]) {
return [userDefaults objectForKey:RCNActiveKeyTemplateVersion];
}

return @"0";
}

- (void)setLastActiveTemplateVersion:(NSString *)templateVersion {
if (templateVersion) {
[self setInstanceUserDefaultsValue:templateVersion forKey:RCNActiveKeyTemplateVersion];
}
}

- (NSTimeInterval)lastETagUpdateTime {
NSNumber *lastETagUpdateTime =
[[self instanceUserDefaults] objectForKey:kRCNUserDefaultsKeyNamelastETagUpdateTime];
Expand Down
Loading
Loading