Skip to content

Commit 01948c4

Browse files
committed
Add local override functionality
1 parent 29e95b7 commit 01948c4

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

src/client/eppo-client.ts

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ export default class EppoClient {
124124
private isObfuscated: boolean;
125125
private requestPoller?: IPoller;
126126
private readonly evaluator = new Evaluator();
127+
protected overridesStore?: IConfigurationStore<Variation>;
127128

128129
constructor({
129130
eventDispatcher = new NoOpEventDispatcher(),
@@ -132,13 +133,25 @@ export default class EppoClient {
132133
banditVariationConfigurationStore,
133134
banditModelConfigurationStore,
134135
configurationRequestParameters,
135-
}: EppoClientParameters) {
136+
overridesStore,
137+
}: {
138+
// Dispatcher for arbitrary, application-level events (not to be confused with Eppo specific assignment
139+
// or bandit events). These events are application-specific and captures by EppoClient#track API.
140+
eventDispatcher?: EventDispatcher;
141+
flagConfigurationStore: IConfigurationStore<Flag | ObfuscatedFlag>;
142+
banditVariationConfigurationStore?: IConfigurationStore<BanditVariation[]>;
143+
banditModelConfigurationStore?: IConfigurationStore<BanditParameters>;
144+
configurationRequestParameters?: FlagConfigurationRequestParameters;
145+
isObfuscated?: boolean;
146+
overridesStore?: IConfigurationStore<Variation>;
147+
}) {
136148
this.eventDispatcher = eventDispatcher;
137149
this.flagConfigurationStore = flagConfigurationStore;
138150
this.banditVariationConfigurationStore = banditVariationConfigurationStore;
139151
this.banditModelConfigurationStore = banditModelConfigurationStore;
140152
this.configurationRequestParameters = configurationRequestParameters;
141153
this.isObfuscated = isObfuscated;
154+
this.overridesStore = overridesStore;
142155
}
143156

144157
setConfigurationRequestParameters(
@@ -177,6 +190,10 @@ export default class EppoClient {
177190
this.isObfuscated = isObfuscated;
178191
}
179192

193+
setOverridesStore(store: IConfigurationStore<Variation>): void {
194+
this.overridesStore = store;
195+
}
196+
180197
async fetchFlagConfigurations() {
181198
if (!this.configurationRequestParameters) {
182199
throw new Error(
@@ -924,6 +941,34 @@ export default class EppoClient {
924941
validateNotBlank(subjectKey, 'Invalid argument: subjectKey cannot be blank');
925942
validateNotBlank(flagKey, 'Invalid argument: flagKey cannot be blank');
926943

944+
// Check for override early
945+
const overrideVariation = this.overridesStore?.get(flagKey);
946+
if (overrideVariation) {
947+
const configFormat = this.overridesStore?.getFormat() ?? '';
948+
const flagEvaluationDetailsBuilder = this.newFlagEvaluationDetailsBuilder(flagKey);
949+
const flagEvaluationDetails = flagEvaluationDetailsBuilder
950+
.setMatch(
951+
0,
952+
overrideVariation,
953+
{ key: overrideVariation.key, splits: [], doLog: false },
954+
null,
955+
undefined,
956+
)
957+
.build('MATCH', 'Flag override applied');
958+
959+
return {
960+
flagKey,
961+
subjectKey,
962+
variation: overrideVariation,
963+
subjectAttributes,
964+
flagEvaluationDetails,
965+
doLog: false,
966+
format: configFormat,
967+
allocationKey: 'override',
968+
extraLogging: {},
969+
};
970+
}
971+
927972
const flagEvaluationDetailsBuilder = this.newFlagEvaluationDetailsBuilder(flagKey);
928973
const configDetails = this.getConfigDetails();
929974
const flag = this.getFlag(flagKey);

src/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ export const NULL_SENTINEL = 'EPPO_NULL';
1515
export const MAX_EVENT_QUEUE_SIZE = 100;
1616
export const BANDIT_ASSIGNMENT_SHARDS = 10000;
1717
export const DEFAULT_TLRU_TTL_MS = 600_000;
18+
export const OVERRIDES_KEY = 'eppo-overrides';

0 commit comments

Comments
 (0)