Skip to content

Commit c955ba9

Browse files
author
Mike Davis
authored
Add OptimizelyFactory and update config notification. (#298)
* Add UpdateConfigNotification * Add NotificationCenter to builder. * Create OptimizelyFactory for basic default configurability. * Add PropertyUtils to standardize on default overrides by environment.
1 parent 7284937 commit c955ba9

File tree

18 files changed

+943
-67
lines changed

18 files changed

+943
-67
lines changed

core-api/src/main/java/com/optimizely/ab/Optimizely.java

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ public class Optimizely implements AutoCloseable {
8585

8686
private final ProjectConfigManager projectConfigManager;
8787

88-
public final NotificationCenter notificationCenter = new NotificationCenter();
88+
// TODO should be private
89+
public final NotificationCenter notificationCenter;
8990

9091
@Nullable
9192
private final UserProfileService userProfileService;
@@ -94,15 +95,17 @@ private Optimizely(@Nonnull EventHandler eventHandler,
9495
@Nonnull EventFactory eventFactory,
9596
@Nonnull ErrorHandler errorHandler,
9697
@Nonnull DecisionService decisionService,
97-
@Nonnull UserProfileService userProfileService,
98-
@Nonnull ProjectConfigManager projectConfigManager
98+
@Nullable UserProfileService userProfileService,
99+
@Nonnull ProjectConfigManager projectConfigManager,
100+
@Nonnull NotificationCenter notificationCenter
99101
) {
100102
this.decisionService = decisionService;
101103
this.eventHandler = eventHandler;
102104
this.eventFactory = eventFactory;
103105
this.errorHandler = errorHandler;
104106
this.userProfileService = userProfileService;
105107
this.projectConfigManager = projectConfigManager;
108+
this.notificationCenter = notificationCenter;
106109
}
107110

108111
/**
@@ -951,17 +954,34 @@ public NotificationCenter getNotificationCenter() {
951954
* Convenience method for adding DecisionNotification Handlers
952955
*/
953956
public int addDecisionNotificationHandler(NotificationHandler<DecisionNotification> handler) {
954-
NotificationManager<DecisionNotification> manager = notificationCenter
955-
.getNotificationManager(DecisionNotification.class);
956-
return manager.addHandler(handler);
957+
return addNotificationHandler(DecisionNotification.class, handler);
957958
}
958959

959960
/**
960961
* Convenience method for adding TrackNotification Handlers
961962
*/
962963
public int addTrackNotificationHandler(NotificationHandler<TrackNotification> handler) {
963-
NotificationManager<TrackNotification> notificationManager =
964-
notificationCenter.getNotificationManager(TrackNotification.class);
964+
return addNotificationHandler(TrackNotification.class, handler);
965+
}
966+
967+
/**
968+
* Convenience method for adding UpdateConfigNotification Handlers
969+
*/
970+
public int addUpdateConfigNotificationHandler(NotificationHandler<UpdateConfigNotification> handler) {
971+
return addNotificationHandler(UpdateConfigNotification.class, handler);
972+
}
973+
974+
/**
975+
* Convenience method for adding UpdateConfigNotification Handlers
976+
*/
977+
private <T> int addNotificationHandler(Class<T> clazz, NotificationHandler<T> handler) {
978+
NotificationManager<T> notificationManager = notificationCenter.getNotificationManager(clazz);
979+
980+
if (notificationManager == null) {
981+
logger.warn("{} not supported by the NotificationCenter.", clazz);
982+
return -1;
983+
}
984+
965985
return notificationManager.addHandler(handler);
966986
}
967987

@@ -999,6 +1019,7 @@ public static class Builder {
9991019
private ProjectConfig projectConfig;
10001020
private ProjectConfigManager projectConfigManager;
10011021
private UserProfileService userProfileService;
1022+
private NotificationCenter notificationCenter;
10021023

10031024
// For backwards compatibility
10041025
private AtomicProjectConfigManager fallbackConfigManager = new AtomicProjectConfigManager();
@@ -1063,6 +1084,11 @@ protected Builder withEventBuilder(EventFactory eventFactory) {
10631084
return this;
10641085
}
10651086

1087+
protected Builder withNotificationCenter(NotificationCenter notificationCenter) {
1088+
this.notificationCenter = notificationCenter;
1089+
return this;
1090+
}
1091+
10661092
public Optimizely build() {
10671093

10681094
if (clientEngine == null) {
@@ -1112,7 +1138,11 @@ public Optimizely build() {
11121138
projectConfigManager = fallbackConfigManager;
11131139
}
11141140

1115-
return new Optimizely(eventHandler, eventFactory, errorHandler, decisionService, userProfileService, projectConfigManager);
1141+
if (notificationCenter == null) {
1142+
notificationCenter = new NotificationCenter();
1143+
}
1144+
1145+
return new Optimizely(eventHandler, eventFactory, errorHandler, decisionService, userProfileService, projectConfigManager, notificationCenter);
11161146
}
11171147
}
11181148
}

core-api/src/main/java/com/optimizely/ab/config/PollingProjectConfigManager.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
*/
1717
package com.optimizely.ab.config;
1818

19+
import com.optimizely.ab.notification.NotificationCenter;
20+
import com.optimizely.ab.notification.UpdateConfigNotification;
1921
import org.slf4j.Logger;
2022
import org.slf4j.LoggerFactory;
2123

@@ -38,27 +40,35 @@
3840
public abstract class PollingProjectConfigManager implements ProjectConfigManager, AutoCloseable {
3941

4042
private static final Logger logger = LoggerFactory.getLogger(PollingProjectConfigManager.class);
43+
private static final UpdateConfigNotification SIGNAL = new UpdateConfigNotification();
4144

4245
private final AtomicReference<ProjectConfig> currentProjectConfig = new AtomicReference<>();
4346
private final ScheduledExecutorService scheduledExecutorService;
4447
private final long period;
4548
private final TimeUnit timeUnit;
4649
private final long blockingTimeoutPeriod;
4750
private final TimeUnit blockingTimeoutUnit;
51+
private final NotificationCenter notificationCenter;
52+
4853
private final CountDownLatch countDownLatch = new CountDownLatch(1);
4954

5055
private volatile boolean started;
5156
private ScheduledFuture<?> scheduledFuture;
5257

5358
public PollingProjectConfigManager(long period, TimeUnit timeUnit) {
54-
this(period, timeUnit, Long.MAX_VALUE, TimeUnit.MILLISECONDS);
59+
this(period, timeUnit, Long.MAX_VALUE, TimeUnit.MILLISECONDS, new NotificationCenter());
60+
}
61+
62+
public PollingProjectConfigManager(long period, TimeUnit timeUnit, NotificationCenter notificationCenter) {
63+
this(period, timeUnit, Long.MAX_VALUE, TimeUnit.MILLISECONDS, notificationCenter);
5564
}
5665

57-
public PollingProjectConfigManager(long period, TimeUnit timeUnit, long blockingTimeoutPeriod, TimeUnit blockingTimeoutUnit) {
66+
public PollingProjectConfigManager(long period, TimeUnit timeUnit, long blockingTimeoutPeriod, TimeUnit blockingTimeoutUnit, NotificationCenter notificationCenter) {
5867
this.period = period;
5968
this.timeUnit = timeUnit;
6069
this.blockingTimeoutPeriod = blockingTimeoutPeriod;
6170
this.blockingTimeoutUnit = blockingTimeoutUnit;
71+
this.notificationCenter = notificationCenter;
6272

6373
final ThreadFactory threadFactory = Executors.defaultThreadFactory();
6474
this.scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(runnable -> {
@@ -89,9 +99,14 @@ void setConfig(ProjectConfig projectConfig) {
8999
logger.info("New datafile set with revision: {}. Old revision: {}", projectConfig.getRevision(), previousRevision);
90100

91101
currentProjectConfig.set(projectConfig);
102+
notificationCenter.send(SIGNAL);
92103
countDownLatch.countDown();
93104
}
94105

106+
public NotificationCenter getNotificationCenter() {
107+
return notificationCenter;
108+
}
109+
95110
/**
96111
* If the instance was never started, then call getConfig() directly from the inner ProjectConfigManager.
97112
* else, wait until the ProjectConfig is set or the timeout expires.

0 commit comments

Comments
 (0)