Skip to content

Commit

Permalink
updates
Browse files Browse the repository at this point in the history
  • Loading branch information
ajwootto committed Jul 18, 2024
1 parent 904cec4 commit 403cf32
Show file tree
Hide file tree
Showing 14 changed files with 143 additions and 46 deletions.
8 changes: 4 additions & 4 deletions lib/shared/config-manager/src/CDNConfigSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { ResponseError, UserError } from '@devcycle/server-request'
export class CDNConfigSource extends ConfigSource {
constructor(
private cdnURI: string,
private clientMode: boolean,
private logger: DVCLogger,
private requestTimeoutMS: number,
) {
Expand All @@ -15,13 +14,14 @@ export class CDNConfigSource extends ConfigSource {

async getConfig(
sdkKey: string,
kind: 'server' | 'bootstrap',
lastModifiedThreshold?: string,
): Promise<[ConfigBody | null, Record<string, unknown>]> {
let res: Response
try {
res = await getEnvironmentConfig({
logger: this.logger,
url: this.getConfigURL(sdkKey),
url: this.getConfigURL(sdkKey, kind),
requestTimeout: this.requestTimeoutMS,
currentEtag: this.configEtag,
currentLastModified: this.configLastModified,
Expand Down Expand Up @@ -69,8 +69,8 @@ export class CDNConfigSource extends ConfigSource {
return [null, metadata]
}

getConfigURL(sdkKey: string): string {
if (this.clientMode) {
getConfigURL(sdkKey: string, kind: 'server' | 'bootstrap'): string {
if (kind === 'bootstrap') {
return `${this.cdnURI}/config/v1/server/bootstrap/${sdkKey}.json`
}
return `${this.cdnURI}/config/v1/server/${sdkKey}.json`
Expand Down
5 changes: 4 additions & 1 deletion lib/shared/config-manager/src/ConfigSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,21 @@ export abstract class ConfigSource {
* Method to get the config from the source.
* Should return null if the config has not changed, and throw an error if it could not be retrieved.
* @param sdkKey
* @param kind
* @param lastModifiedThreshold
*/
abstract getConfig(
sdkKey: string,
kind: 'server' | 'bootstrap',
lastModifiedThreshold?: string,
): Promise<[ConfigBody | null, Record<string, unknown>]>

/**
* Return the URL (or path or storage key etc.) that will be used to retrieve the config for the given SDK key
* @param sdkKey
* @param kind
*/
abstract getConfigURL(sdkKey: string): string
abstract getConfigURL(sdkKey: string, kind: 'server' | 'bootstrap'): string

protected isLastModifiedHeaderOld(
lastModifiedHeader: string | null,
Expand Down
18 changes: 10 additions & 8 deletions lib/shared/config-manager/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,7 @@ export class EnvironmentConfigManager {

this.configSource =
configSource ??
new CDNConfigSource(
cdnURI,
clientMode,
logger,
this.requestTimeoutMS,
)
new CDNConfigSource(cdnURI, logger, this.requestTimeoutMS)

this.fetchConfigPromise = this._fetchConfig()
.then(() => {
Expand Down Expand Up @@ -212,7 +207,10 @@ export class EnvironmentConfigManager {
}

async _fetchConfig(sseLastModified?: string): Promise<void> {
const url = this.configSource.getConfigURL(this.sdkKey)
const url = this.configSource.getConfigURL(
this.sdkKey,
this.clientMode ? 'bootstrap' : 'server',
)
let projectConfig: ConfigBody | null = null
let retrievalMetadata: Record<string, unknown>
let userError: UserError | null = null
Expand Down Expand Up @@ -253,7 +251,11 @@ export class EnvironmentConfigManager {
`, last-modified: ${this.configSource.configLastModified}`,
)
;[projectConfig, retrievalMetadata] =
await this.configSource.getConfig(this.sdkKey, sseLastModified)
await this.configSource.getConfig(
this.sdkKey,
this.clientMode ? 'bootstrap' : 'server',
sseLastModified,
)
responseTimeMS = Date.now() - startTime
// if no errors occurred, the projectConfig is either new or null (meaning cached version is used)
// either way, trigger the SSE config handler to see if we need to reconnect
Expand Down
1 change: 0 additions & 1 deletion lib/shared/vercel-edge-config/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"name": "@devcycle/vercel-edge-config",
"version": "0.0.1",
"dependencies": {},
"peerDependencies": {
"@devcycle/nodejs-server-sdk": "*",
"@devcycle/types": "*",
Expand Down
19 changes: 15 additions & 4 deletions lib/shared/vercel-edge-config/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@
"assets": ["lib/shared/vercel-edge-config/*.md"]
}
},
"publish": {
"command": "node tools/scripts/publish.mjs shared-vercel-edge-config {args.ver} {args.tag}",
"dependsOn": ["build"]
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
Expand All @@ -41,6 +37,21 @@
"codeCoverage": true
}
}
},
"check-types": {
"executor": "nx:run-commands",
"options": {
"command": "yarn run -T tsc -b --incremental",
"cwd": "lib/shared/vercel-edge-config"
}
},
"npm-publish": {
"executor": "nx:run-commands",
"options": {
"command": "../../../scripts/npm-safe-publish.sh \"@devcycle/vercel-edge-config\"",
"cwd": "dist/lib/shared/vercel-edge-config",
"forwardAllArgs": true
}
}
},
"tags": []
Expand Down
71 changes: 71 additions & 0 deletions lib/shared/vercel-edge-config/src/edge-config.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { EdgeConfigSource } from './edge-config'
import { fromPartial } from '@total-typescript/shoehorn'

describe('EdgeConfigSource', () => {
it('sends a request to edge config with the correct key', async () => {
const get = jest.fn()
const edgeConfigSource = new EdgeConfigSource(
fromPartial({
get,
}),
)

get.mockResolvedValue({
key: 'value',
lastModified: 'some date',
})

const result = await edgeConfigSource.getConfig('sdk-key', 'server')

expect(get).toHaveBeenCalledWith('devcycle-config-v1-server-sdk-key')

expect(result).toEqual([
{ key: 'value', lastModified: 'some date' },
{ resLastModified: 'some date' },
])
})

it('returns null when the existing config date is newer', async () => {
const get = jest.fn()
const edgeConfigSource = new EdgeConfigSource(
fromPartial({
get,
}),
)

get.mockResolvedValueOnce({
key: 'value',
lastModified: '2024-07-18T14:55:32.720Z',
})

get.mockResolvedValueOnce({
key: 'value',
lastModified: '2024-07-18T14:12:32.720Z',
})

const result = await edgeConfigSource.getConfig('sdk-key', 'server')
expect(result[0]).not.toBeNull()
const result2 = await edgeConfigSource.getConfig('sdk-key', 'server')
expect(result2[0]).toBeNull()
})

it('requests the bootstrap config', async () => {
const get = jest.fn()
const edgeConfigSource = new EdgeConfigSource(
fromPartial({
get,
}),
)

get.mockResolvedValue({
key: 'value',
lastModified: 'some date',
})

await edgeConfigSource.getConfig('sdk-key', 'bootstrap')

expect(get).toHaveBeenCalledWith(
'devcycle-config-v1-server-bootstrap-sdk-key',
)
})
})
19 changes: 8 additions & 11 deletions lib/shared/vercel-edge-config/src/edge-config.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
import { ConfigSource } from '@devcycle/nodejs-server-sdk'
import { ConfigSource, UserError } from '@devcycle/nodejs-server-sdk'
import { EdgeConfigClient, EdgeConfigValue } from '@vercel/edge-config'
import { ConfigBody } from '@devcycle/types'
import { UserError } from '@devcycle/server-request'

export class EdgeConfigSource extends ConfigSource {
constructor(
private edgeConfigClient: EdgeConfigClient,
private kind: 'server' | 'bootstrap',
) {
constructor(private edgeConfigClient: EdgeConfigClient) {
super()
}

async getConfig(
sdkKey: string,
kind: 'server' | 'bootstrap',
): Promise<[ConfigBody | null, Record<string, unknown>]> {
const configPath = this.getConfigURL(sdkKey)
const configPath = this.getConfigURL(sdkKey, kind)
const config = await this.edgeConfigClient.get<{
[x: string]: EdgeConfigValue
}>(configPath)
Expand All @@ -36,9 +33,9 @@ export class EdgeConfigSource extends ConfigSource {
]
}

getConfigURL(sdkKey: string): string {
return this.kind == 'server'
? `devcycle-config-v1-server-${sdkKey}`
: `devcycle-config-v1-server-bootstrap-${sdkKey}`
getConfigURL(sdkKey: string, kind: 'server' | 'bootstrap'): string {
return kind == 'bootstrap'
? `devcycle-config-v1-server-bootstrap-${sdkKey}`
: `devcycle-config-v1-server-${sdkKey}`
}
}
9 changes: 0 additions & 9 deletions lib/shared/vercel-edge-config/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"module": "commonjs",
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
},
"files": [],
"include": [],
"references": [
Expand Down
4 changes: 3 additions & 1 deletion lib/shared/vercel-edge-config/tsconfig.lib.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"outDir": "../../../dist/out-tsc",
"module": "node16",
"moduleResolution": "node16",
"declaration": true,
"types": ["node"]
},
Expand Down
1 change: 0 additions & 1 deletion lib/shared/vercel-edge-config/tsconfig.spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"]
},
"include": [
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@
"@testing-library/jest-native": "5.4.3",
"@testing-library/react": "14.0.0",
"@testing-library/react-native": "12.3.2",
"@total-typescript/shoehorn": "^0.1.2",
"@types/async": "^3.2.8",
"@types/eventsource": "^1.1.15",
"@types/hoist-non-react-statics": "^3.3.1",
Expand Down
5 changes: 4 additions & 1 deletion sdk/nodejs/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
} from '@devcycle/js-cloud-server-sdk'
import { DVCPopulatedUserFromDevCycleUser } from './models/populatedUserHelpers'
import { randomUUID } from 'crypto'
import { DevCycleOptionsLocalEnabled } from './index'
import { WASMBucketingExports } from '@devcycle/bucketing-assembly-script'

interface IPlatformData {
Expand Down Expand Up @@ -72,7 +73,7 @@ export class DevCycleClient {
return this._isInitialized
}

constructor(sdkKey: string, options?: DevCycleServerSDKOptions) {
constructor(sdkKey: string, options?: DevCycleOptionsLocalEnabled) {
this.clientUUID = randomUUID()
this.hostname = os.hostname()
this.sdkKey = sdkKey
Expand Down Expand Up @@ -102,6 +103,7 @@ export class DevCycleClient {
clearInterval,
this.trackSDKConfigEvent.bind(this),
options || {},
options?.configSource,
)
if (options?.enableClientBootstrapping) {
this.clientConfigHelper = new EnvironmentConfigManager(
Expand All @@ -117,6 +119,7 @@ export class DevCycleClient {
clearInterval,
this.trackSDKConfigEvent.bind(this),
{ ...options, clientMode: true },
options?.configSource,
)
}

Expand Down
16 changes: 13 additions & 3 deletions sdk/nodejs/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,23 @@ export type DVCEvent = DevCycleEvent
*/
export type DVCOptions = DevCycleServerSDKOptions

export { ConfigSource } from '@devcycle/config-manager'
import { ConfigSource } from '@devcycle/config-manager'

export { ConfigSource }

export { UserError } from '@devcycle/server-request'

type DevCycleOptionsCloudEnabled = DevCycleServerSDKOptions & {
enableCloudBucketing: true
}
type DevCycleOptionsLocalEnabled = DevCycleServerSDKOptions & {

export type DevCycleOptionsLocalEnabled = DevCycleServerSDKOptions & {
enableCloudBucketing?: false

/**
* Override the source to retrieve configuration from. Defaults to the DevCycle CDN
*/
configSource?: ConfigSource
}

export function initializeDevCycle(
Expand Down Expand Up @@ -138,7 +148,7 @@ export function initializeDevCycle(
getNodeJSPlatformDetails(),
)
}
return new DevCycleClient(sdkKey, options)
return new DevCycleClient(sdkKey, options as DevCycleOptionsLocalEnabled)
}

/**
Expand Down
12 changes: 10 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4844,9 +4844,9 @@ __metadata:
"@devcycle/vercel-edge-config@workspace:lib/shared/vercel-edge-config":
version: 0.0.0-use.local
resolution: "@devcycle/vercel-edge-config@workspace:lib/shared/vercel-edge-config"
dependencies:
tslib: ^2.3.0
peerDependencies:
"@devcycle/nodejs-server-sdk": "*"
"@devcycle/types": "*"
"@vercel/edge-config": ^1.2.0
languageName: unknown
linkType: soft
Expand Down Expand Up @@ -9886,6 +9886,13 @@ __metadata:
languageName: node
linkType: hard

"@total-typescript/shoehorn@npm:^0.1.2":
version: 0.1.2
resolution: "@total-typescript/shoehorn@npm:0.1.2"
checksum: eb02c8fae1b8a219d6dceee4f582f478fb280c92fc33c444799a6cb65a73f7f172505a03ffcf19e53a021e27b5ce965af90dd85e561e597bbe021006f38a30ea
languageName: node
linkType: hard

"@trysound/sax@npm:0.2.0":
version: 0.2.0
resolution: "@trysound/sax@npm:0.2.0"
Expand Down Expand Up @@ -15361,6 +15368,7 @@ __metadata:
"@testing-library/jest-native": 5.4.3
"@testing-library/react": 14.0.0
"@testing-library/react-native": 12.3.2
"@total-typescript/shoehorn": ^0.1.2
"@types/async": ^3.2.8
"@types/eventsource": ^1.1.15
"@types/express": ^4.17.17
Expand Down

0 comments on commit 403cf32

Please sign in to comment.