Skip to content

Commit ec87564

Browse files
yfrancisgreghuels
authored andcommitted
Add local override functionality
1 parent f6c3d4f commit ec87564

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(
@@ -192,6 +205,10 @@ export default class EppoClient {
192205
this.isObfuscated = isObfuscated;
193206
}
194207

208+
setOverridesStore(store: IConfigurationStore<Variation>): void {
209+
this.overridesStore = store;
210+
}
211+
195212
async fetchFlagConfigurations() {
196213
if (!this.configurationRequestParameters) {
197214
throw new Error(
@@ -939,6 +956,34 @@ export default class EppoClient {
939956
validateNotBlank(subjectKey, 'Invalid argument: subjectKey cannot be blank');
940957
validateNotBlank(flagKey, 'Invalid argument: flagKey cannot be blank');
941958

959+
// Check for override early
960+
const overrideVariation = this.overridesStore?.get(flagKey);
961+
if (overrideVariation) {
962+
const configFormat = this.overridesStore?.getFormat() ?? '';
963+
const flagEvaluationDetailsBuilder = this.newFlagEvaluationDetailsBuilder(flagKey);
964+
const flagEvaluationDetails = flagEvaluationDetailsBuilder
965+
.setMatch(
966+
0,
967+
overrideVariation,
968+
{ key: overrideVariation.key, splits: [], doLog: false },
969+
null,
970+
undefined,
971+
)
972+
.build('MATCH', 'Flag override applied');
973+
974+
return {
975+
flagKey,
976+
subjectKey,
977+
variation: overrideVariation,
978+
subjectAttributes,
979+
flagEvaluationDetails,
980+
doLog: false,
981+
format: configFormat,
982+
allocationKey: 'override',
983+
extraLogging: {},
984+
};
985+
}
986+
942987
const flagEvaluationDetailsBuilder = this.newFlagEvaluationDetailsBuilder(flagKey);
943988
const configDetails = this.getConfigDetails();
944989
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)