Skip to content

Commit

Permalink
fix: Akamai data is fetched for the lifetime of the SDK connection
Browse files Browse the repository at this point in the history
When the SDK retrieves data from the EdgeKV, it does so using a single
sub-request per call to `variation`, `variationDetail`, or
`allFlagsState`. The problem is that Akamai imposes a limit of 4
sub-requests per handler event.

If a customer evaluates more than 4 distinct flags during the handling
of a single event, subsequent flag lookups would fail. To combat this,
we now cache the flag values the first time an evaluation is requested,
and we keep that cache in memory for the full duration of the EdgeWorker
execution.
  • Loading branch information
keelerm84 committed Jan 24, 2025
1 parent 83f9cb1 commit 544565d
Show file tree
Hide file tree
Showing 3 changed files with 2 additions and 21 deletions.
3 changes: 0 additions & 3 deletions packages/shared/akamai-edgeworker-sdk/src/api/LDClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ class LDClient extends LDClientImpl {
defaultValue: LDFlagValue,
callback?: (err: any, res: LDFlagValue) => void,
): Promise<LDFlagValue> {
await this._cacheableStoreProvider.prefetchPayloadFromOriginStore();
return super.variation(key, context, defaultValue, callback);
}

Expand All @@ -56,7 +55,6 @@ class LDClient extends LDClientImpl {
defaultValue: LDFlagValue,
callback?: (err: any, res: LDEvaluationDetail) => void,
): Promise<LDEvaluationDetail> {
await this._cacheableStoreProvider.prefetchPayloadFromOriginStore();
return super.variationDetail(key, context, defaultValue, callback);
}

Expand All @@ -65,7 +63,6 @@ class LDClient extends LDClientImpl {
options?: LDFlagsStateOptions,
callback?: (err: Error | null, res: LDFlagsState) => void,
): Promise<LDFlagsState> {
await this._cacheableStoreProvider.prefetchPayloadFromOriginStore();
return super.allFlagsState(context, options, callback);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@ import { EdgeProvider } from '.';

/**
* Wraps around an edge provider to cache a copy of the sdk payload locally an explicit request is made to refetch data from the origin.
* The wrapper is neccessary to ensure that we dont make redundant sub-requests from Akamai to fetch an entire environment payload.
* The wrapper is necessary to ensure that we dona make redundant sub-requests from Akamai to fetch an entire environment payload.
*/
export default class CacheableStoreProvider implements EdgeProvider {
cache: string | null | undefined;

constructor(

Check failure on line 10 in packages/shared/akamai-edgeworker-sdk/src/featureStore/cacheableStoreProvider.ts

View workflow job for this annotation

GitHub Actions / build-test-akamai-edgeworker-sdk

Replace `⏎····private·readonly·_edgeProvider:·EdgeProvider,⏎··` with `private·readonly·_edgeProvider:·EdgeProvider`
private readonly _edgeProvider: EdgeProvider,
private readonly _rootKey: string,
) {}

/**
Expand All @@ -24,16 +23,4 @@ export default class CacheableStoreProvider implements EdgeProvider {

return this.cache;
}

/**
* Invalidates cache and fetch environment payload data from origin. The result of this data is cached in memory.
* You should only call this function within a feature store to pre-fetch and cache payload data in environments
* where its expensive to make multiple outbound requests to the origin
* @param rootKey
* @returns
*/
async prefetchPayloadFromOriginStore(rootKey?: string): Promise<string | null | undefined> {
this.cache = undefined; // clear the cache so that new data can be fetched from the origin
return this.get(rootKey || this._rootKey);
}
}
5 changes: 1 addition & 4 deletions packages/shared/akamai-edgeworker-sdk/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,7 @@ export const init = (params: BaseSDKParams): LDClient => {

const logger = options.logger ?? BasicLogger.get();

const cachableStoreProvider = new CacheableStoreProvider(
featureStoreProvider,
buildRootKey(sdkKey),
);
const cachableStoreProvider = new CacheableStoreProvider(featureStoreProvider);
const featureStore = new EdgeFeatureStore(cachableStoreProvider, sdkKey, 'Akamai', logger);

const ldOptions: LDOptionsCommon = {
Expand Down

0 comments on commit 544565d

Please sign in to comment.