Skip to content

Commit 595e9d0

Browse files
authored
@flags-sdk/launchdarkly: only read edge config once per request (#156)
* @flags-sdk/launchdarkly: only read edge config once per request * fix test
1 parent 0976e8f commit 595e9d0

File tree

3 files changed

+48
-9
lines changed

3 files changed

+48
-9
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@flags-sdk/launchdarkly': patch
3+
---
4+
5+
only read edge config once per request

packages/adapter-launchdarkly/src/index.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { ldAdapter, type LDContext } from '.';
55
const ldClientMock = {
66
waitForInitialization: vi.fn(),
77
variation: vi.fn(),
8+
initialized: vi.fn(() => true),
89
};
910

1011
vi.mock('@launchdarkly/vercel-server-sdk', () => ({

packages/adapter-launchdarkly/src/index.ts

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import type { Adapter } from 'flags';
2-
import { createClient } from '@vercel/edge-config';
2+
import { createClient, type EdgeConfigClient } from '@vercel/edge-config';
33
import {
44
init,
55
LDClient,
66
type LDContext,
77
} from '@launchdarkly/vercel-server-sdk';
8+
import { AsyncLocalStorage } from 'async_hooks';
89

910
export { getProviderData } from './provider';
1011
export type { LDContext };
@@ -45,7 +46,31 @@ export function createLaunchDarklyAdapter({
4546
edgeConfigConnectionString: string;
4647
}): AdapterResponse {
4748
const edgeConfigClient = createClient(edgeConfigConnectionString);
48-
const ldClient = init(clientSideId, edgeConfigClient);
49+
50+
const store = new AsyncLocalStorage<WeakKey>();
51+
const cache = new WeakMap<WeakKey, Promise<unknown>>();
52+
53+
const patchedEdgeConfigClient: EdgeConfigClient = {
54+
...edgeConfigClient,
55+
get: async <T>(key: string) => {
56+
const h = store.getStore();
57+
if (h) {
58+
const cached = cache.get(h);
59+
if (cached) {
60+
return cached as Promise<T>;
61+
}
62+
}
63+
64+
const promise = edgeConfigClient.get<T>(key);
65+
if (h) cache.set(h, promise);
66+
67+
return promise;
68+
},
69+
};
70+
71+
let initPromise: Promise<unknown> | null = null;
72+
73+
const ldClient = init(clientSideId, patchedEdgeConfigClient);
4974

5075
function origin(key: string) {
5176
return `https://app.launchdarkly.com/projects/${projectSlug}/flags/${key}/`;
@@ -56,13 +81,21 @@ export function createLaunchDarklyAdapter({
5681
): Adapter<ValueType, LDContext> {
5782
return {
5883
origin,
59-
async decide({ key, entities }): Promise<ValueType> {
60-
await ldClient.waitForInitialization();
61-
return ldClient.variation(
62-
key,
63-
entities as LDContext,
64-
options.defaultValue,
65-
) as ValueType;
84+
async decide({ key, entities, headers }): Promise<ValueType> {
85+
if (!ldClient.initialized()) {
86+
if (!initPromise) initPromise = ldClient.waitForInitialization();
87+
await initPromise;
88+
}
89+
90+
return store.run(
91+
headers,
92+
() =>
93+
ldClient.variation(
94+
key,
95+
entities as LDContext,
96+
options.defaultValue,
97+
) as ValueType,
98+
);
6699
},
67100
};
68101
}

0 commit comments

Comments
 (0)