Skip to content

Commit

Permalink
fix: disable last modified check on vercel edge config and fix type d…
Browse files Browse the repository at this point in the history
…efinitions (#930)
  • Loading branch information
ajwootto authored Aug 14, 2024
1 parent a5cc1c1 commit b49eadf
Show file tree
Hide file tree
Showing 8 changed files with 47 additions and 13 deletions.
15 changes: 10 additions & 5 deletions lib/shared/vercel-edge-config/src/edge-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ export class EdgeConfigSource extends ConfigSource {
super()
}

async getConfig(
async getConfig<T extends boolean>(
sdkKey: string,
kind: 'server' | 'bootstrap',
obfuscated: boolean,
lastModifiedThreshold?: string,
skipLastModified?: T,
): Promise<{
config: ConfigBody | null
config: T extends true ? ConfigBody : ConfigBody | null
metaData: Record<string, unknown>
lastModified: string | null
}> {
Expand All @@ -22,14 +24,17 @@ export class EdgeConfigSource extends ConfigSource {
}>(configPath)

if (!config) {
throw new UserError(`Invalid SDK key provided: ${sdkKey}`)
throw new UserError(
`Invalid SDK key provided, or edge config integration is not setup: ${sdkKey}`,
)
}

const lastModified = config['lastModified'] as string

if (this.isLastModifiedHeaderOld(lastModified)) {
if (!skipLastModified && this.isLastModifiedHeaderOld(lastModified)) {
return {
config: null,
// type hackery to make it accept the return type when skipLastModified is false
config: null as T extends true ? never : ConfigBody | null,
metaData: {
resLastModified: lastModified,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import { DevCycleClient, initializeDevCycle } from '@devcycle/js-client-sdk'
import { invalidateConfig } from '../../common/invalidateConfig'
import { DevCycleNextOptions, DevCycleServerData } from '../../common/types'
import { DevCycleProviderContext } from './context'
import { useRouter } from 'next/navigation'

export type DevCycleClientContext = {
serverDataPromise: Promise<DevCycleServerData>
serverData?: DevCycleServerData
clientSDKKey: string
options: DevCycleNextOptions
enableStreaming: boolean
realtimeDelay?: number
userAgent?: string
}

Expand Down Expand Up @@ -59,12 +61,28 @@ export const InternalDevCycleClientsideProvider = ({
promiseResolved,
}: DevCycleClientsideProviderProps): React.ReactElement => {
const clientRef = useRef<DevCycleClient>()
const router = useRouter()

const { serverDataPromise, serverData, clientSDKKey, enableStreaming } =
context

const revalidateConfig = (lastModified?: number) => {
void invalidateConfig(clientSDKKey)
const revalidateConfig = async (lastModified?: number) => {
if (context.realtimeDelay) {
// wait configured delay before checking for new config
await new Promise((resolve) =>
setTimeout(resolve, context.realtimeDelay),
)
}
try {
await invalidateConfig(clientSDKKey)
} catch {
// do nothing on failure, this is best effort
}
if (context.realtimeDelay) {
// if delay is configured, assume that the server action invalidation won't update any content and just
// call for a full in-place refresh
router.refresh()
}
}

let resolvedServerData = serverData
Expand Down
9 changes: 7 additions & 2 deletions sdk/nextjs/src/common/ConfigSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,16 @@ export abstract class ConfigSource {
* @param kind
* @param obfuscated
* @param lastModifiedThreshold
* @param skipLastModified
*/
abstract getConfig(
abstract getConfig<T extends boolean>(
sdkKey: string,
kind: 'server' | 'bootstrap',
obfuscated: boolean,
lastModifiedThreshold?: string,
): Promise<{ config: ConfigBody; lastModified: string | null }>
skipLastModified?: T,
): Promise<{
config: T extends true ? ConfigBody : ConfigBody | null
lastModified: string | null
}>
}
1 change: 0 additions & 1 deletion sdk/nextjs/src/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ export type BucketedConfigWithAdditionalFields = BucketedUserConfig & {
}

export type DevCycleServerData = {
options: DevCycleNextOptions
user: DevCycleUser
// this is null if the config failed to be fetched
config: BucketedConfigWithAdditionalFields | null
Expand Down
3 changes: 2 additions & 1 deletion sdk/nextjs/src/pages/bucketing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ class CDNConfigSource extends ConfigSource {
sdkKey: string,
kind: 'server' | 'bootstrap',
obfuscated: boolean,
lastModifiedThreshold?: string,
): Promise<{
config: ConfigBody
lastModified: string | null
Expand Down Expand Up @@ -49,6 +48,8 @@ export const getBucketedConfig = async (
sdkKey,
'bootstrap',
obfuscated,
'',
true,
)
const populatedUser = new DVCPopulatedUser(
user,
Expand Down
4 changes: 3 additions & 1 deletion sdk/nextjs/src/server/bucketing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class CDNConfigSource extends ConfigSource {
throw new Error('Could not fetch config: ' + responseText)
}
return {
config: await cdnConfig.json(),
config: (await cdnConfig.json()) as ConfigBody,
lastModified: cdnConfig.headers.get('last-modified'),
}
}
Expand All @@ -82,6 +82,8 @@ export const getBucketedConfig = async (
sdkKey,
'bootstrap',
!!options.enableObfuscation,
'',
true,
)

const { bucketedConfig } = await generateBucketedConfigCached(
Expand Down
2 changes: 1 addition & 1 deletion sdk/nextjs/src/server/initialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export const initialize = async (
client.synchronizeBootstrapData(config, user, getUserAgent(options))
}

return { config, user, options }
return { config, user }
}

export const validateSDKKey = (
Expand Down
4 changes: 4 additions & 0 deletions sdk/nextjs/src/server/setupDevCycle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ export const setupDevCycle = ({
options: clientOptions,
clientSDKKey: clientSDKKey,
enableStreaming: options?.enableStreaming ?? false,
// if a custom config source is set, add an artificial delay for realtime updates as a clumsy way to
// allow for propagation time of the custom source, since we don't have a first-class way to ensure its
// up to date
realtimeDelay: options?.configSource ? 10000 : undefined,
userAgent: getUserAgent(options),
}
}
Expand Down

0 comments on commit b49eadf

Please sign in to comment.