Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: parallelize config fetch #1008

Merged
merged 2 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 17 additions & 10 deletions sdk/nextjs/src/server/bucketing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,21 +88,14 @@ class CDNConfigSource extends ConfigSource {
}
}

/**
* Retrieve the config from CDN for the current request's SDK Key. This data will often be cached
* Compute the bucketed config for the current request's user using that data, with local bucketing library
* Cache the bucketed config for this request so that repeated calls to this function are memoized
*/
export const getBucketedConfig = async (
export const getConfigFromSource = async (
sdkKey: string,
clientSDKKey: string,
user: DevCycleUser,
options: DevCycleNextOptions,
userAgent?: string,
): Promise<BucketedConfigWithAdditionalFields> => {
): Promise<{ config: ConfigBody; lastModified: string | null }> => {
const cdnConfigSource = new CDNConfigSource(clientSDKKey)

const configSource = options.configSource ?? cdnConfigSource

const { config, lastModified } = await configSource.getConfig(
sdkKey,
'bootstrap',
Expand All @@ -111,6 +104,20 @@ export const getBucketedConfig = async (
true,
)

return { config, lastModified }
}

/**
* Compute the bucketed config for the current request's user using raw config data, with local bucketing library
* Cache the bucketed config for this request so that repeated calls to this function are memoized
*/
export const getBucketedConfig = async (
config: ConfigBody,
lastModified: string | null,
user: DevCycleUser,
options: DevCycleNextOptions,
userAgent?: string,
): Promise<BucketedConfigWithAdditionalFields> => {
const { bucketedConfig } = await generateBucketedConfigCached(
!!options.enableObfuscation,
user,
Expand Down
15 changes: 8 additions & 7 deletions sdk/nextjs/src/server/initialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { getClient, setClient } from './requestContext'
import { getUserAgent } from './userAgent'
import { DevCycleNextOptions, DevCycleServerData } from '../common/types'
import { cache } from 'react'
import { getBucketedConfig } from './bucketing'
import { getBucketedConfig, getConfigFromSource } from './bucketing'

const jsClientOptions = {
// pass next object to enable "next" mode in JS SDK
Expand All @@ -29,11 +29,12 @@ export const initialize = async (
userGetter: () => DevCycleUser | Promise<DevCycleUser>,
options: DevCycleNextOptions = {},
): Promise<DevCycleServerData> => {
// TODO moving this call to inside `getBucketedConfig` appears to cause static build issues from reading headers
// Might be a bug in Next, if moving this make sure to verify you can `yarn next build` the e2e app router app
const userAgent = await getUserAgent(options)
const [userAgent, user, configData] = await Promise.all([
getUserAgent(options),
cachedUserGetter(userGetter),
getConfigFromSource(sdkKey, clientSDKKey, options),
])

const user = await cachedUserGetter(userGetter)
if (!user || typeof user.user_id !== 'string') {
throw new Error('DevCycle user getter must return a user')
}
Expand All @@ -53,8 +54,8 @@ export const initialize = async (
let config = null
try {
config = await getBucketedConfig(
sdkKey,
clientSDKKey,
configData.config,
configData.lastModified,
user,
options,
userAgent,
Expand Down
Loading