Skip to content
Closed
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: 3 additions & 2 deletions packages/egg/src/lib/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,16 +193,17 @@ export class Application extends EggApplicationCore {
}

/**
* save routers to `run/router.json`
* save routers to `${rundir}/router.json`
* @private
*/
dumpConfig(): void {
super.dumpConfig();

// dump routers to router.json
const rundir = this.config.rundir;
const rundir = this.getRuntimeRundir();
const FULLPATH = this.loader.FileLoader.FULLPATH;
try {
fs.mkdirSync(rundir, { recursive: true });
const dumpRouterFile = path.join(rundir, 'router.json');
const routers = [];
for (const layer of this.router.stack) {
Expand Down
41 changes: 28 additions & 13 deletions packages/egg/src/lib/egg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ import { convertObject, createTransparentProxy } from './core/utils.ts';
import type { EggApplicationLoader } from './loader/index.ts';
import type { EggAppConfig } from './types.ts';

const DEFAULT_WORKER_START_TIMEOUT = 10 * 60 * 1000;

export interface EggApplicationCoreOptions extends Omit<EggCoreOptions, 'baseDir'> {
mode?: 'cluster' | 'single';
clusterPort?: number;
Expand Down Expand Up @@ -561,15 +563,13 @@ export class EggApplicationCore extends EggCore {
}

/**
* save app.config to `run/${type}_config.json`
* save app.config to `${rundir}/${type}_config.json`
* @private
*/
dumpConfig(): void {
const rundir = this.config.rundir;
const rundir = this.getRuntimeRundir();
try {
if (!fs.existsSync(rundir)) {
fs.mkdirSync(rundir);
}
fs.mkdirSync(rundir, { recursive: true });

// get dumped object
const { config, meta } = this.dumpConfigToObject();
Expand All @@ -589,7 +589,8 @@ export class EggApplicationCore extends EggCore {
dumpTiming(): void {
try {
const items = this.timing.toJSON();
const rundir = this.config.rundir;
const rundir = this.getRuntimeRundir();
fs.mkdirSync(rundir, { recursive: true });
const dumpFile = path.join(rundir, `${this.type}_timing_${process.pid}.json`);
fs.writeFileSync(dumpFile, CircularJSON.stringify(items, null, 2));
this.coreLogger.info(this.timing.toString());
Expand Down Expand Up @@ -641,27 +642,41 @@ export class EggApplicationCore extends EggCore {
}

#setupTimeoutTimer(): void {
const workerStartTimeout = this.getWorkerStartTimeout();
const startTimeoutTimer = setTimeout(() => {
this.coreLogger.error(this.timing.toString());
this.coreLogger.error(`${this.type} still doesn't ready after ${this.config.workerStartTimeout} ms.`);
this.coreLogger.error(`${this.type} still doesn't ready after ${workerStartTimeout} ms.`);
Comment thread
killagu marked this conversation as resolved.
// log unfinished
const items = this.timing.toJSON();
for (const item of items) {
if (item.end) continue;
this.coreLogger.error(`unfinished timing item: ${CircularJSON.stringify(item)}`);
}
this.coreLogger.error(
'[egg][setupTimeoutTimer] check run/%s_timing_%s.json for more details.',
this.type,
process.pid,
);
const dumpTimingFile = path.join(this.getRuntimeRundir(), `${this.type}_timing_${process.pid}.json`);
this.coreLogger.error('[egg][setupTimeoutTimer] check %s for more details.', dumpTimingFile);
this.emit('startTimeout');
this.dumpConfig();
this.dumpTiming();
}, this.config.workerStartTimeout);
}, workerStartTimeout);
this.ready(() => clearTimeout(startTimeoutTimer));
}

protected getRuntimeRundir(): string {
const rundir = this.config.rundir;
if (typeof rundir === 'string' && rundir.length > 0) {
return rundir;
}
return path.join(this.baseDir, 'run');
}
Comment thread
killagu marked this conversation as resolved.

private getWorkerStartTimeout(): number {
const workerStartTimeout = this.config.workerStartTimeout;
if (typeof workerStartTimeout === 'number' && Number.isFinite(workerStartTimeout) && workerStartTimeout > 0) {
return workerStartTimeout;
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
return DEFAULT_WORKER_START_TIMEOUT;
}

get config() {
return super.config as EggAppConfig;
}
Expand Down
47 changes: 47 additions & 0 deletions packages/egg/test/egg.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,53 @@ describe.sequential('test/egg.test.ts', () => {
});
});

describe('runtime diagnostics fallback config', () => {
const baseDir = getFilepath('apps/dumpconfig');
const runDir = path.join(baseDir, 'run');
let app: MockApplication;

beforeAll(async () => {
app = createApp('apps/dumpconfig');
await app.ready();
});

afterAll(() => app.close());

it('should dump config and timing to baseDir/run when rundir is missing', () => {
fs.rmSync(runDir, { recursive: true, force: true });
const originalRundir = app.config.rundir;
Reflect.set(app.config, 'rundir', undefined);
try {
app.dumpConfig();
app.dumpTiming();
} finally {
Reflect.set(app.config, 'rundir', originalRundir);
}

assertFile(path.join(runDir, 'application_config.json'));
assertFile(path.join(runDir, `application_timing_${process.pid}.json`));
assertFile(path.join(runDir, 'router.json'));
});

it('should use the default worker start timeout when config is missing or invalid', () => {
const originalWorkerStartTimeout = app.config.workerStartTimeout;
try {
Reflect.set(app.config, 'workerStartTimeout', undefined);
assert.equal((app as any).getWorkerStartTimeout(), 10 * 60 * 1000);
Reflect.set(app.config, 'workerStartTimeout', 0);
assert.equal((app as any).getWorkerStartTimeout(), 10 * 60 * 1000);
Reflect.set(app.config, 'workerStartTimeout', -1);
assert.equal((app as any).getWorkerStartTimeout(), 10 * 60 * 1000);
Reflect.set(app.config, 'workerStartTimeout', Number.POSITIVE_INFINITY);
assert.equal((app as any).getWorkerStartTimeout(), 10 * 60 * 1000);
Reflect.set(app.config, 'workerStartTimeout', 1);
assert.equal((app as any).getWorkerStartTimeout(), 1);
} finally {
Reflect.set(app.config, 'workerStartTimeout', originalWorkerStartTimeout);
}
});
});

describe('custom config from env', () => {
let app: MockApplication;
let baseDir: string;
Expand Down
Loading