Skip to content
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
5 changes: 5 additions & 0 deletions .changeset/quiet-adapter-probe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"evlog": patch
---

Avoid unnecessary Nitro runtime-config probes when drain adapter overrides or env vars already satisfy the env-backed config fields.
18 changes: 17 additions & 1 deletion packages/evlog/src/adapters/_config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ export async function resolveAdapterConfig<T>(
fields: ConfigField<T>[],
overrides?: Partial<T>,
): Promise<Partial<T>> {
const runtimeConfig = await getRuntimeConfig()
const runtimeConfig = shouldProbeRuntimeConfig(fields, overrides)
? await getRuntimeConfig()
: undefined
const evlogNs = runtimeConfig?.evlog?.[namespace]
const rootNs = runtimeConfig?.[namespace]

Expand All @@ -38,6 +40,20 @@ export async function resolveAdapterConfig<T>(
return config as Partial<T>
}

function shouldProbeRuntimeConfig<T>(
fields: ConfigField<T>[],
overrides?: Partial<T>,
): boolean {
// Optional tuning fields (e.g. timeout/retries) should not trigger Nitro
// virtual-module imports when env/overrides already resolve the env-backed
// adapter fields in non-Nitro runtimes.
return fields.some(({ key, env }) => {
if (overrides?.[key] !== undefined) return false
if (!env) return false
return resolveEnv(env) === undefined
})
}

function resolveEnv(envKeys?: string[]): string | undefined {
if (!envKeys) return undefined
for (const key of envKeys) {
Expand Down
151 changes: 151 additions & 0 deletions packages/evlog/test/adapters/config.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import { afterEach, describe, expect, it, vi } from 'vitest'

vi.mock('../../src/shared/nitroConfigBridge', () => ({
getNitroRuntimeConfigRecord: vi.fn(),
}))

// eslint-disable-next-line import/first -- Must import after vi.mock
import { resolveAdapterConfig } from '../../src/adapters/_config'
// eslint-disable-next-line import/first -- Must import after vi.mock
import { getNitroRuntimeConfigRecord } from '../../src/shared/nitroConfigBridge'

interface TestAdapterConfig {
apiKey?: string
endpoint?: string
site?: string
timeout?: number
}

describe('resolveAdapterConfig', () => {
afterEach(() => {
vi.clearAllMocks()
vi.unstubAllEnvs()
})

it('skips the Nitro runtime probe when overrides and env already satisfy env-backed fields', async () => {
const runtimeProbe = vi.mocked(getNitroRuntimeConfigRecord)
runtimeProbe.mockResolvedValue({
evlog: {
test: {
timeout: 30_000,
},
},
})

const config = await resolveAdapterConfig<TestAdapterConfig>(
'test',
[
{ key: 'apiKey', env: ['TEST_API_KEY'] },
{ key: 'endpoint', env: ['TEST_ENDPOINT'] },
{ key: 'timeout' },
],
{
apiKey: 'override-key',
endpoint: 'https://override.example.com',
},
)

expect(runtimeProbe).not.toHaveBeenCalled()
expect(config).toEqual({
apiKey: 'override-key',
endpoint: 'https://override.example.com',
timeout: undefined,
})
})

it('skips the Nitro runtime probe when env alone satisfies the remaining env-backed fields', async () => {
vi.stubEnv('TEST_API_KEY', 'env-key')
vi.stubEnv('TEST_ENDPOINT', 'https://env.example.com')

const runtimeProbe = vi.mocked(getNitroRuntimeConfigRecord)

const config = await resolveAdapterConfig<TestAdapterConfig>(
'test',
[
{ key: 'apiKey', env: ['TEST_API_KEY'] },
{ key: 'endpoint', env: ['TEST_ENDPOINT'] },
{ key: 'timeout' },
],
)

expect(runtimeProbe).not.toHaveBeenCalled()
expect(config).toEqual({
apiKey: 'env-key',
endpoint: 'https://env.example.com',
timeout: undefined,
})
})

it('probes Nitro runtime config when an env-backed field is still unresolved', async () => {
const runtimeProbe = vi.mocked(getNitroRuntimeConfigRecord)
runtimeProbe.mockResolvedValue({
evlog: {
test: {
apiKey: 'runtime-key',
endpoint: 'https://runtime.example.com',
},
},
test: {
endpoint: 'https://root.example.com',
timeout: 15_000,
},
})

const config = await resolveAdapterConfig<TestAdapterConfig>(
'test',
[
{ key: 'apiKey', env: ['TEST_API_KEY'] },
{ key: 'endpoint', env: ['TEST_ENDPOINT'] },
{ key: 'timeout' },
],
)

expect(runtimeProbe).toHaveBeenCalledTimes(1)
expect(config).toEqual({
apiKey: 'runtime-key',
endpoint: 'https://runtime.example.com',
timeout: 15_000,
})
})

it('preserves override then runtime then env precedence when the probe is required', async () => {
vi.stubEnv('TEST_API_KEY', 'env-key')
vi.stubEnv('TEST_ENDPOINT', 'https://env.example.com')

const runtimeProbe = vi.mocked(getNitroRuntimeConfigRecord)
runtimeProbe.mockResolvedValue({
evlog: {
test: {
apiKey: 'runtime-key',
endpoint: 'https://runtime.example.com',
site: 'runtime-site',
},
},
test: {
endpoint: 'https://root.example.com',
timeout: 5_000,
},
})

const config = await resolveAdapterConfig<TestAdapterConfig>(
'test',
[
{ key: 'apiKey', env: ['TEST_API_KEY'] },
{ key: 'endpoint', env: ['TEST_ENDPOINT'] },
{ key: 'site', env: ['TEST_SITE'] },
{ key: 'timeout' },
],
{
apiKey: 'override-key',
},
)

expect(runtimeProbe).toHaveBeenCalledTimes(1)
expect(config).toEqual({
apiKey: 'override-key',
endpoint: 'https://runtime.example.com',
site: 'runtime-site',
timeout: 5_000,
})
})
})
Loading