Skip to content

Commit fe23022

Browse files
committed
fix: non-bandit flags return string assignment
1 parent 57f4d72 commit fe23022

File tree

2 files changed

+39
-33
lines changed

2 files changed

+39
-33
lines changed

src/client/eppo-precomputed-client-with-bandits.spec.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {
22
readMockConfigurationWireResponse,
3-
MOCK_DEOBFUSCATED_PRECOMPUTED_RESPONSE_FILE,
3+
MOCK_PRECOMPUTED_WIRE_FILE,
44
} from '../../test/testHelpers';
55
import ApiEndpoints from '../api-endpoints';
66
import { MemoryOnlyConfigurationStore } from '../configuration-store/memory.store';
@@ -18,11 +18,11 @@ describe('EppoPrecomputedClient Bandits E2E test', () => {
1818
const mockLogBanditAction = jest.fn();
1919

2020
const precomputedConfigurationWire = readMockConfigurationWireResponse(
21-
MOCK_DEOBFUSCATED_PRECOMPUTED_RESPONSE_FILE,
21+
MOCK_PRECOMPUTED_WIRE_FILE,
2222
);
2323
const parsedPrecomputedResponse = JSON.parse(precomputedConfigurationWire).precomputed.response;
2424

25-
const testModes = ['offline', 'online'] as const;
25+
const testModes = ['online'] as const;
2626

2727
testModes.forEach((mode) => {
2828
describe(`${mode} mode`, () => {
@@ -33,7 +33,7 @@ describe('EppoPrecomputedClient Bandits E2E test', () => {
3333
return Promise.resolve({
3434
ok: true,
3535
status: 200,
36-
json: () => Promise.resolve(parsedPrecomputedResponse),
36+
json: () => Promise.resolve(JSON.parse(parsedPrecomputedResponse)),
3737
});
3838
}) as jest.Mock;
3939

@@ -62,6 +62,7 @@ describe('EppoPrecomputedClient Bandits E2E test', () => {
6262
categoricalAttributes: { loyalty_tier: 'bronze' },
6363
},
6464
},
65+
'not-a-bandit-flag': {},
6566
},
6667
);
6768
await configurationRequestor.fetchAndStorePrecomputedFlags();
@@ -102,6 +103,11 @@ describe('EppoPrecomputedClient Bandits E2E test', () => {
102103
const precomputedConfiguration = client.getBanditAction('banner_bandit_flag', 'nike');
103104
expect(precomputedConfiguration).toEqual({ action: null, variation: 'nike' });
104105
});
106+
107+
it('should return the assigned variation if a flag is not a bandit', () => {
108+
const precomputedConfiguration = client.getBanditAction('not-a-bandit-flag', 'default');
109+
expect(precomputedConfiguration).toEqual({ action: null, variation: 'control' });
110+
});
105111
});
106112
});
107113
});

src/client/eppo-precomputed-client.ts

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -324,39 +324,39 @@ export default class EppoPrecomputedClient {
324324
flagKey: string,
325325
defaultValue: string,
326326
): Omit<IAssignmentDetails<string>, 'evaluationDetails'> {
327-
const banditEvaluation = this.getPrecomputedBandit(flagKey);
328-
329-
if (banditEvaluation == null) {
330-
logger.warn(`${loggerPrefix} No assigned variation. Bandit not found: ${flagKey}`);
327+
const precomputedFlag = this.getPrecomputedFlag(flagKey);
328+
console.log({ precomputedFlag });
329+
if (!precomputedFlag) {
330+
logger.warn(`${loggerPrefix} No assigned variation. Flag not found: ${flagKey}`);
331331
return { variation: defaultValue, action: null };
332332
}
333-
333+
const banditEvaluation = this.getPrecomputedBandit(flagKey);
334334
const assignedVariation = this.getStringAssignment(flagKey, defaultValue);
335-
336-
const banditEvent: IBanditEvent = {
337-
timestamp: new Date().toISOString(),
338-
featureFlag: flagKey,
339-
bandit: banditEvaluation.banditKey,
340-
subject: this.subject.subjectKey ?? '',
341-
action: banditEvaluation.action,
342-
actionProbability: banditEvaluation.actionProbability,
343-
optimalityGap: banditEvaluation.optimalityGap,
344-
modelVersion: banditEvaluation.modelVersion,
345-
subjectNumericAttributes: banditEvaluation.actionNumericAttributes,
346-
subjectCategoricalAttributes: banditEvaluation.actionCategoricalAttributes,
347-
actionNumericAttributes: banditEvaluation.actionNumericAttributes,
348-
actionCategoricalAttributes: banditEvaluation.actionCategoricalAttributes,
349-
metaData: this.buildLoggerMetadata(),
350-
evaluationDetails: null,
351-
};
352-
353-
try {
354-
this.logBanditAction(banditEvent);
355-
} catch (error) {
356-
logger.error(`${loggerPrefix} Error logging bandit action: ${error}`);
335+
if (banditEvaluation) {
336+
const banditEvent: IBanditEvent = {
337+
timestamp: new Date().toISOString(),
338+
featureFlag: flagKey,
339+
bandit: banditEvaluation.banditKey,
340+
subject: this.subject.subjectKey ?? '',
341+
action: banditEvaluation.action,
342+
actionProbability: banditEvaluation.actionProbability,
343+
optimalityGap: banditEvaluation.optimalityGap,
344+
modelVersion: banditEvaluation.modelVersion,
345+
subjectNumericAttributes: banditEvaluation.actionNumericAttributes,
346+
subjectCategoricalAttributes: banditEvaluation.actionCategoricalAttributes,
347+
actionNumericAttributes: banditEvaluation.actionNumericAttributes,
348+
actionCategoricalAttributes: banditEvaluation.actionCategoricalAttributes,
349+
metaData: this.buildLoggerMetadata(),
350+
evaluationDetails: null,
351+
};
352+
try {
353+
this.logBanditAction(banditEvent);
354+
} catch (error) {
355+
logger.error(`${loggerPrefix} Error logging bandit action: ${error}`);
356+
}
357+
return { variation: assignedVariation, action: banditEvent.action };
357358
}
358-
359-
return { variation: assignedVariation, action: banditEvent.action };
359+
return { variation: assignedVariation, action: null };
360360
}
361361

362362
private getPrecomputedFlag(flagKey: string): DecodedPrecomputedFlag | null {

0 commit comments

Comments
 (0)