fix(api): pm2 start script & limit auto restarts (#1040)

* fix(api): limit auto restarts to 10

so persistent errors (e.g. during server boot) don't cause an infinite
loop that's difficult for users to see

* fix(api): invoke js directly from pm2 instead of npm script

npm script wraps it in a child process, so we lose ipc.

* fix(api): update api key service test for ensureDir change

* chore: increase max_restart threshold to 10s per cycle
This commit is contained in:
Pujit Mehrotra
2025-01-14 14:27:00 -05:00
committed by GitHub
parent 1935ba1a7f
commit b53bb3f197
3 changed files with 7 additions and 9 deletions

View File

@@ -2,13 +2,14 @@
"apps": [ "apps": [
{ {
"name": "unraid-api", "name": "unraid-api",
"script": "npm", "script": "./dist/main.js",
"args": "start",
"cwd": "/usr/local/unraid-api", "cwd": "/usr/local/unraid-api",
"log": "/var/log/unraid-api/unraid-api.log", "log": "/var/log/unraid-api/unraid-api.log",
"exec_mode": "fork", "exec_mode": "fork",
"wait_ready": true, "wait_ready": true,
"listen_timeout": 30000, "listen_timeout": 30000,
"max_restarts": 10,
"min_uptime": 10000,
"ignore_watch": [ "ignore_watch": [
"node_modules", "node_modules",
"src", "src",
@@ -17,4 +18,4 @@
] ]
} }
] ]
} }

View File

@@ -91,7 +91,6 @@ describe('ApiKeyService', () => {
vi.mocked(ensureDir).mockResolvedValue(); vi.mocked(ensureDir).mockResolvedValue();
apiKeyService = new ApiKeyService(); apiKeyService = new ApiKeyService();
await apiKeyService.initialize();
vi.spyOn(apiKeyService as any, 'generateApiKey').mockReturnValue('test-api-key'); vi.spyOn(apiKeyService as any, 'generateApiKey').mockReturnValue('test-api-key');
vi.mock('uuid', () => ({ vi.mock('uuid', () => ({
@@ -113,12 +112,8 @@ describe('ApiKeyService', () => {
describe('initialization', () => { describe('initialization', () => {
it('should ensure directory exists', async () => { it('should ensure directory exists', async () => {
vi.mocked(ensureDir).mockResolvedValue();
const service = new ApiKeyService(); const service = new ApiKeyService();
expect(ensureDirSync).toHaveBeenCalledWith(mockBasePath);
await service.initialize();
expect(ensureDir).toHaveBeenCalledWith(mockBasePath);
}); });
it('should return correct paths', async () => { it('should return correct paths', async () => {

View File

@@ -54,6 +54,8 @@ export async function bootstrapNestServer(): Promise<NestFastifyApplication> {
// See https://pm2.keymetrics.io/docs/usage/signals-clean-restart/ // See https://pm2.keymetrics.io/docs/usage/signals-clean-restart/
if (process.send) { if (process.send) {
process.send('ready'); process.send('ready');
} else {
console.log('Warning: process.send is unavailable. This will affect IPC communication with PM2.');
} }
apiLogger.info('Nest Server is now listening'); apiLogger.info('Nest Server is now listening');