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
12 changes: 8 additions & 4 deletions src/utils/parseEnvConfigs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,14 @@ export function parseSystemConfigEnvValue(key: keyof typeof SYSTEM_CONFIG_ENV_MA
case 'delay_after':
return Number(raw);

// An empty value, or one of the words an operator is likely to reach for,
// means no limit. Without this the only way to express "uncapped" through the
// environment would be to unset the variable, which a deployment template
// cannot easily do.
// One of the words an operator is likely to reach for means no limit. Without
// this the only way to express "uncapped" through the environment would be to
// unset the variable, which a deployment template cannot easily do.
//
// A truly empty value never gets here: bootstrapSystemConfig skips empty env
// values, so they count as unset (an existing cap is kept, otherwise the
// default applies). The empty check below only catches a whitespace-only
// value, which is empty once trimmed.
case 'max_concurrent_sessions': {
const value = raw.trim().toLowerCase();

Expand Down
78 changes: 78 additions & 0 deletions tests/unit/config/bootstrapMaxConcurrentSessions.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { vi } from 'vitest';

vi.mock('../../../src/models/systemConfig', () => ({
SystemConfig: {
findByPk: vi.fn(),
create: vi.fn(),
},
}));

vi.mock('../../../src/config/systemConfig.envMap', () => ({
SYSTEM_CONFIG_ENV_MAP: {
max_concurrent_sessions: 'MAX_CONCURRENT_SESSIONS',
},
}));

vi.mock('../../../src/schemas/systemConfig.schema', () => ({
SystemConfigSchema: {
safeParse: vi.fn(),
},
}));

import { beforeEach, describe, expect, it } from 'vitest';

// The real parser and defaults are used here. Bootstrap skips an empty env value
// before parsing, so MAX_CONCURRENT_SESSIONS='' behaves as unset rather than as
// "no limit". Only a whitespace-only value reaches the parser's empty check.
describe('bootstrapSystemConfig with MAX_CONCURRENT_SESSIONS', () => {
beforeEach(() => {
vi.resetModules();
vi.clearAllMocks();
delete process.env.MAX_CONCURRENT_SESSIONS;
});

async function load() {
const { SystemConfig } = await import('../../../src/models/systemConfig');
const { SystemConfigSchema } = await import('../../../src/schemas/systemConfig.schema');
(SystemConfigSchema.safeParse as any).mockReturnValue({ success: true, data: {} });
const { bootstrapSystemConfig } = await import('../../../src/config/bootstrapSystemConfig');
return { SystemConfig, SystemConfigSchema, bootstrapSystemConfig };
}

it('keeps an existing cap when the value is empty', async () => {
const { SystemConfig, SystemConfigSchema, bootstrapSystemConfig } = await load();
const row = { value: 3, updatedBy: null, update: vi.fn(), destroy: vi.fn() };
(SystemConfig.findByPk as any).mockResolvedValue(row);
process.env.MAX_CONCURRENT_SESSIONS = '';

await bootstrapSystemConfig();

expect(row.update).not.toHaveBeenCalled();
expect(row.destroy).not.toHaveBeenCalled();
expect(SystemConfigSchema.safeParse).toHaveBeenCalledWith({ max_concurrent_sessions: 3 });
});

it('uses the default when the value is empty and no row exists', async () => {
const { SystemConfig, SystemConfigSchema, bootstrapSystemConfig } = await load();
(SystemConfig.findByPk as any).mockResolvedValue(null);
process.env.MAX_CONCURRENT_SESSIONS = '';

await bootstrapSystemConfig();

expect(SystemConfig.create).not.toHaveBeenCalled();
expect(SystemConfigSchema.safeParse).toHaveBeenCalledWith({ max_concurrent_sessions: null });
});

it('clears an existing cap when the value is whitespace only', async () => {
const { SystemConfig, SystemConfigSchema, bootstrapSystemConfig } = await load();
const row = { value: 3, updatedBy: null, update: vi.fn(), destroy: vi.fn() };
(SystemConfig.findByPk as any).mockResolvedValue(row);
process.env.MAX_CONCURRENT_SESSIONS = ' ';

await bootstrapSystemConfig();

expect(row.destroy).toHaveBeenCalled();
expect(row.update).not.toHaveBeenCalled();
expect(SystemConfigSchema.safeParse).toHaveBeenCalledWith({ max_concurrent_sessions: null });
});
});
Loading