Persist api-server logs and refresh recharge balance
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
import { execFileSync, spawn } from 'node:child_process';
|
||||
import { existsSync, readFileSync } from 'node:fs';
|
||||
import { resolve } from 'node:path';
|
||||
import {
|
||||
createWriteStream,
|
||||
existsSync,
|
||||
mkdirSync,
|
||||
readFileSync,
|
||||
} from 'node:fs';
|
||||
import { dirname, isAbsolute, resolve } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const repoRoot = process.cwd();
|
||||
@@ -67,7 +72,69 @@ export function mergeApiServerEnv(repoRootPath, baseEnv = process.env) {
|
||||
return mergedEnv;
|
||||
}
|
||||
|
||||
function stopExistingWindowsApiServer() {
|
||||
export function formatApiServerLogTimestamp(date = new Date()) {
|
||||
const pad = (value) => String(value).padStart(2, '0');
|
||||
|
||||
return [
|
||||
date.getFullYear(),
|
||||
pad(date.getMonth() + 1),
|
||||
pad(date.getDate()),
|
||||
'-',
|
||||
pad(date.getHours()),
|
||||
pad(date.getMinutes()),
|
||||
pad(date.getSeconds()),
|
||||
].join('');
|
||||
}
|
||||
|
||||
export function resolveApiServerLogFile(
|
||||
repoRootPath,
|
||||
env = process.env,
|
||||
now = new Date(),
|
||||
) {
|
||||
const explicitLogFile = String(
|
||||
env.GENARRATIVE_API_SERVER_LOG_FILE ?? '',
|
||||
).trim();
|
||||
|
||||
if (explicitLogFile) {
|
||||
return isAbsolute(explicitLogFile)
|
||||
? explicitLogFile
|
||||
: resolve(repoRootPath, explicitLogFile);
|
||||
}
|
||||
|
||||
const logDir =
|
||||
String(env.GENARRATIVE_API_SERVER_LOG_DIR ?? '').trim() ||
|
||||
'logs/api-server';
|
||||
const resolvedLogDir = isAbsolute(logDir)
|
||||
? logDir
|
||||
: resolve(repoRootPath, logDir);
|
||||
|
||||
return resolve(
|
||||
resolvedLogDir,
|
||||
`api-server-${formatApiServerLogTimestamp(now)}.log`,
|
||||
);
|
||||
}
|
||||
|
||||
function createApiServerLogStream(logFilePath) {
|
||||
mkdirSync(dirname(logFilePath), { recursive: true });
|
||||
const logStream = createWriteStream(logFilePath, {
|
||||
flags: 'a',
|
||||
encoding: 'utf8',
|
||||
});
|
||||
logStream.on('error', (error) => {
|
||||
console.error(`[api-server] 写入日志失败: ${error.message}`);
|
||||
});
|
||||
return logStream;
|
||||
}
|
||||
|
||||
function writeLauncherLog(logStream, message, stream = process.stdout) {
|
||||
const line = `${message}\n`;
|
||||
stream.write(line);
|
||||
if (!logStream.destroyed) {
|
||||
logStream.write(line);
|
||||
}
|
||||
}
|
||||
|
||||
function stopExistingWindowsApiServer(logStream) {
|
||||
if (process.platform !== 'win32') {
|
||||
return;
|
||||
}
|
||||
@@ -104,7 +171,7 @@ function stopExistingWindowsApiServer() {
|
||||
).trim();
|
||||
|
||||
if (output) {
|
||||
console.log(`[api-server] 已停止旧 api-server 进程: ${output}`);
|
||||
writeLauncherLog(logStream, `[api-server] 已停止旧 api-server 进程: ${output}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,19 +188,55 @@ function main() {
|
||||
mergedEnv.GENARRATIVE_SPACETIME_TOKEN =
|
||||
mergedEnv.GENARRATIVE_SPACETIME_TOKEN || '';
|
||||
|
||||
const logFilePath = resolveApiServerLogFile(repoRoot, mergedEnv);
|
||||
const logStream = createApiServerLogStream(logFilePath);
|
||||
mergedEnv.GENARRATIVE_API_SERVER_LOG_FILE = logFilePath;
|
||||
|
||||
let didExit = false;
|
||||
const exitAfterLogFlush = (code) => {
|
||||
const finish = () => {
|
||||
if (didExit) {
|
||||
return;
|
||||
}
|
||||
didExit = true;
|
||||
process.exit(code);
|
||||
};
|
||||
|
||||
if (logStream.destroyed) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
logStream.end(finish);
|
||||
setTimeout(finish, 1000).unref();
|
||||
};
|
||||
|
||||
writeLauncherLog(logStream, `[api-server] 日志: ${logFilePath}`);
|
||||
|
||||
if (!mergedEnv.GENARRATIVE_SPACETIME_DATABASE) {
|
||||
console.error('[api-server] 缺少 GENARRATIVE_SPACETIME_DATABASE。');
|
||||
process.exit(1);
|
||||
writeLauncherLog(
|
||||
logStream,
|
||||
'[api-server] 缺少 GENARRATIVE_SPACETIME_DATABASE。',
|
||||
process.stderr,
|
||||
);
|
||||
exitAfterLogFlush(1);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
stopExistingWindowsApiServer();
|
||||
stopExistingWindowsApiServer(logStream);
|
||||
} catch (error) {
|
||||
console.error(`[api-server] 清理旧 api-server 进程失败: ${error.message}`);
|
||||
process.exit(1);
|
||||
writeLauncherLog(
|
||||
logStream,
|
||||
`[api-server] 清理旧 api-server 进程失败: ${error.message}`,
|
||||
process.stderr,
|
||||
);
|
||||
exitAfterLogFlush(1);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(
|
||||
writeLauncherLog(
|
||||
logStream,
|
||||
`[api-server] SpacetimeDB ${mergedEnv.GENARRATIVE_SPACETIME_DATABASE} @ ${mergedEnv.GENARRATIVE_SPACETIME_SERVER_URL}`,
|
||||
);
|
||||
|
||||
@@ -143,22 +246,41 @@ function main() {
|
||||
{
|
||||
cwd: repoRoot,
|
||||
env: mergedEnv,
|
||||
stdio: 'inherit',
|
||||
stdio: ['inherit', 'pipe', 'pipe'],
|
||||
},
|
||||
);
|
||||
|
||||
child.on('error', (error) => {
|
||||
console.error(`[api-server] 启动 cargo 失败: ${error.message}`);
|
||||
process.exit(1);
|
||||
child.stdout?.on('data', (chunk) => {
|
||||
process.stdout.write(chunk);
|
||||
logStream.write(chunk);
|
||||
});
|
||||
|
||||
child.on('exit', (code, signal) => {
|
||||
child.stderr?.on('data', (chunk) => {
|
||||
process.stderr.write(chunk);
|
||||
logStream.write(chunk);
|
||||
});
|
||||
|
||||
child.on('error', (error) => {
|
||||
writeLauncherLog(
|
||||
logStream,
|
||||
`[api-server] 启动 cargo 失败: ${error.message}`,
|
||||
process.stderr,
|
||||
);
|
||||
exitAfterLogFlush(1);
|
||||
});
|
||||
|
||||
child.on('close', (code, signal) => {
|
||||
if (signal) {
|
||||
console.error(`[api-server] api-server 被信号终止: ${signal}`);
|
||||
process.exit(1);
|
||||
writeLauncherLog(
|
||||
logStream,
|
||||
`[api-server] api-server 被信号终止: ${signal}`,
|
||||
process.stderr,
|
||||
);
|
||||
exitAfterLogFlush(1);
|
||||
return;
|
||||
}
|
||||
|
||||
process.exit(code ?? 0);
|
||||
exitAfterLogFlush(code ?? 0);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user