Skip to content

Conversation

sameerank
Copy link
Contributor

@sameerank sameerank commented Nov 18, 2024


labels: mergeable

Fixes: #issue

Motivation and Context

An edge compute function will generate and return a JSON of precomputed assignments for each flag. This created a new client to handle this format. The benefits of precomputing assignments is 1) smaller payloads and 2) greater security, because targeting rules with potentially sensitive information would no longer need to be sent over a public network.

Description

The EppoPrecomputedClient is a separate singleton from EppoClient so that we can run both simultaneously for dogfooding. In order to do this, EppoPrecomputedClient comes with its own distinct "configuration store" and precomputed flags requestor, so that these wouldn't overlap with the EppoClient instance. I also wrote tests to verify the core functionality -- most are similar to the EppoClient tests but modified slightly to be compatible with the EppoPrecomputedClient format.

How has this been tested?

package.json Outdated
{
"name": "@eppo/js-client-sdk-common",
"version": "4.3.0",
"version": "4.3.1-alpha.0",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will bump this pre-release version with the following changes:

  • export the PrecomputedFlag interface for setting up the memory only store's type
  • update the PRECOMPUTED_BASE_URL and PRECOMPUTED_FLAGS_ENDPOINT

@sameerank sameerank marked this pull request as ready for review November 21, 2024 21:22
Copy link
Member

@leoromanovsky leoromanovsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

top notch specs.

just want to mentioned once more at the top-level that the server is not currently obfuscating. would you prefer it did or adjust the client here to handle the available values?

Comment on lines +10 to +11
export const PRECOMPUTED_BASE_URL = 'https://fs-edge-assignment.eppo.cloud';
export const PRECOMPUTED_FLAGS_ENDPOINT = '/assignments';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bingo - Eric P. and I have a plan for migrating this to https://fscdn.eppo.cloud but will do it after the holiday.

BTW do you think I should version it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessary here, but yes it would be consistent with the UFC endpoint if it is versioned

PRECOMPUTED = 'PRECOMPUTED',
}

export interface PrecomputedFlag {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✔️


/**
* The flag evaluation details
* The flag evaluation details. Null if the flag was precomputed.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it also null if users don't request details?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this implementation it is always null. The edge compute endpoint would need to provide these details in the response for it to be added here, which is out of scope for this milestone

import { Attributes } from './types';

export interface FlagEvaluation {
export interface FlagEvaluationWithoutDetails {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

const precomputedFlag: PrecomputedFlag | null = this.precomputedFlagStore.get(
getMD5Hash(flagKey),
) as PrecomputedFlag;
return precomputedFlag ? decodePrecomputedFlag(precomputedFlag) : null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The server is NOT performing obfuscation in the current implementation - this might have gotten muddled in the design doc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I added support for it in the SDK, but it's not necessary for the server to be obfuscating yet

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll need obfuscation eventually, but it's okay to leave it out of the first milestone

doLog: true,
},
},
}; // TODO: readMockPrecomputedFlagsResponse(MOCK_PRECOMPUTED_FLAGS_RESPONSE_FILE);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fyi

});
});

it('returns null if getStringAssignment was called for the subject before any precomputed flags were loaded', () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice

expect(td.explain(mockLogger.logAssignment).callCount).toEqual(1);
});

it('logs assignment again after the lru cache is full', async () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm glad you are thinking about testing the assignment logging and deduplication - as you mentioned there is some duplication here. Could you consider a way in the future to have the two eppo clients share these?


async getPrecomputedFlags(): Promise<IPrecomputedFlagsResponse | undefined> {
const url = this.apiEndpoints.precomputedFlagsEndpoint();
return await this.rawGet<IPrecomputedFlagsResponse>(url);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Quick thing I just noticed - the endpoint is a POST

Copy link
Contributor Author

@sameerank sameerank Nov 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I bumped the prerelease version (https://www.npmjs.com/package/@eppo/js-client-sdk-common/v/4.3.1-alpha.2) with this change #137 and the requests work now when I run the client in a script. It'll work in the browser after a CORS fix

@sameerank sameerank merged commit 2251bf5 into main Nov 26, 2024
8 checks passed
@sameerank sameerank deleted the sameeran/ff-3566-create-eppoprecomputedclient branch November 26, 2024 18:15
@felipecsl
Copy link
Contributor

@sameerank this PR could really use some fleshing out of the motivation and description. even if after merged, that'd still be helpful and appreciated

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants