Skip to content

Commit

Permalink
feat: implement isAlive check
Browse files Browse the repository at this point in the history
- Implemented isAlive check for start and status commands
- Added separated option for commands
- Created helper function to obtain socket
  • Loading branch information
L2jLiga authored and mantoni committed Sep 29, 2024
1 parent fbe0137 commit a4b5570
Show file tree
Hide file tree
Showing 10 changed files with 267 additions and 86 deletions.
16 changes: 11 additions & 5 deletions bin/eslint_d.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#!/usr/bin/env node

import { loadConfig } from '../lib/config.js';
import { loadConfig, removeConfig } from '../lib/config.js';
import { createResolver } from '../lib/resolver.js';
import { forwardToDaemon } from '../lib/forwarder.js';
import { forwardToDaemon, isAlive } from '../lib/forwarder.js';
import { launchDaemon, stopDaemon } from '../lib/launcher.js';
import { filesHash } from '../lib/hash.js';

Expand Down Expand Up @@ -31,11 +31,17 @@ const command = process.argv[2];
]);
switch (command) {
case 'start':
if (config) {
if (await isAlive(config)) {
console.log('eslint_d: Already running');
} else {
await launchDaemon(resolver, hash);
return;
}

if (config) {
await removeConfig(resolver);
}

await launchDaemon(resolver, hash);

return;
case 'stop':
if (config) {
Expand Down
3 changes: 3 additions & 0 deletions lib/commands.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const PING_COMMAND = 'ESLINT_D_PING';
export const SHUTDOWN_COMMAND = 'ESLINT_D_SHUTDOWN';
export const LINT_COMMAND = 'ESLINT_D_LINT';
76 changes: 66 additions & 10 deletions lib/forwarder.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,45 @@
import net from 'node:net';
import supportsColor from 'supports-color';
import { removeConfig } from '../lib/config.js';
import { LINT_COMMAND, PING_COMMAND } from './commands.js';

/**
* @import { Config} from '../lib/config.js'
* @import { Resolver} from '../lib/resolver.js'
* @import { Config } from './config.js'
* @import { Resolver } from './resolver.js'
*/

const EXIT_TOKEN_REGEXP = new RegExp(/EXIT([0-9]{3})/);
const EXIT_TOKEN_LENGTH = 7;

/**
* @param {Config | null} config
* @returns {Promise<boolean>}
*/
export function isAlive(config) {
return forwardCommandToDaemon(config, PING_COMMAND)
.then(() => true)
.catch(() => false);
}

/**
* @param {Config | null} config
* @param {string} command
* @returns {Promise<void>}
*/
export async function forwardCommandToDaemon(config, command) {
if (!config) {
return Promise.reject(new Error('config not found'));
}

const socket = await connectToDaemon(config);
socket.write(JSON.stringify([config.token, command]));
socket.end();

return new Promise((resolve, reject) => {
socket.on('end', () => resolve()).on('error', (err) => reject(err));
});
}

/**
* @param {Resolver} resolver
* @param {Config} config
Expand Down Expand Up @@ -38,9 +68,24 @@ export async function forwardToDaemon(resolver, config) {
);
}

const socket = net.connect(config.port, '127.0.0.1');
let socket;
try {
socket = await connectToDaemon(config);
} catch (/** @type {any} */ err) {
if (err['code'] === 'ECONNREFUSED') {
console.error(`eslint_d: ${err} - removing config`);
await removeConfig(resolver);
} else {
console.error(`eslint_d: ${err}`);
}
// eslint-disable-next-line require-atomic-updates
process.exitCode = 1;
return;
}

const args = [
config.token,
LINT_COMMAND,
stdout ? stdout.level : 0,
process.cwd(),
eslint_args
Expand Down Expand Up @@ -90,13 +135,8 @@ export async function forwardToDaemon(resolver, config) {
process.exitCode = 1;
}
})
.on('error', async (err) => {
if (err['code'] === 'ECONNREFUSED') {
console.error(`eslint_d: ${err} - removing config`);
await removeConfig(resolver);
} else {
console.error(`eslint_d: ${err}`);
}
.on('error', (err) => {
console.error(`eslint_d: ${err}`);
process.exitCode = 1;
});

Expand All @@ -113,6 +153,22 @@ export async function forwardToDaemon(resolver, config) {
}
}

/**
* @param {Config} config
* @returns {Promise<net.Socket>}
*/
function connectToDaemon(config) {
return new Promise((resolve, reject) => {
const socket = net.connect(config.port, '127.0.0.1');
socket
.on('connect', () => resolve(socket))
.on('connectionAttemptFailed', (err) => {
reject(err);
socket.end();
});
});
}

function readStdin() {
return new Promise((resolve, reject) => {
let content = '';
Expand Down
Loading

0 comments on commit a4b5570

Please sign in to comment.