Fixes #5
This commit is contained in:
Connor Peet 2021-01-21 23:04:02 -08:00
Родитель f351c7f968
Коммит c7d50c8e29
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: CF8FD2EA0DBC61BD
8 изменённых файлов: 69 добавлений и 17 удалений

22
.vscode/launch.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,22 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "pwa-node",
"request": "launch",
"name": "Launch Program",
"skipFiles": [
"<node_internals>/**"
],
"program": "${workspaceFolder}\\src\\index.ts",
"args": ["src/**/*.ts"],
"preLaunchTask": "tsc: build - tsconfig.json",
"outFiles": [
"${workspaceFolder}/dist/**/*.js"
]
}
]
}

Просмотреть файл

@ -8,7 +8,9 @@ import * as cluster from 'cluster';
import * as commander from 'commander';
import { cpus } from 'os';
import * as prettier from 'prettier';
import { version } from '../package.json';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { version } = require('../package.json');
function startMaster() {
const program = commander

Просмотреть файл

@ -39,7 +39,7 @@ export function spawnWorkers(options: IOptions) {
() => {
progress.complete();
if (progress.reformatted && options.check) {
if ((progress.reformatted && options.check) || progress.failed) {
process.exit(1);
} else {
process.exit(0);

Просмотреть файл

@ -12,6 +12,7 @@ import { IFormatResults } from './protocol';
export class ProgressReporter {
public total = 0;
public reformatted = 0;
public failed = 0;
private spinner?: ora.Ora;
constructor(quiet: boolean, private readonly check: boolean) {
@ -26,6 +27,7 @@ export class ProgressReporter {
public update(results: IFormatResults) {
this.total += results.files;
this.reformatted += results.formatted.length;
this.failed += results.failed.length;
if (results.formatted.length) {
if (this.spinner) {

Просмотреть файл

@ -46,6 +46,7 @@ export type MasterMessage = IInitializationMessage | IFilesMessage;
*/
export interface IFormatResults {
files: number;
failed: IDiscoveredFile[];
formatted: IDiscoveredFile[];
}

Просмотреть файл

@ -3,8 +3,8 @@
*--------------------------------------------------------*/
import * as cluster from 'cluster';
import { fromEvent, Observable } from 'rxjs';
import { filter, map, take, tap } from 'rxjs/operators';
import { BehaviorSubject, fromEvent, Observable } from 'rxjs';
import { filter, map, switchMap, take, tap } from 'rxjs/operators';
import {
IFormatResults,
IInitializationMessage,
@ -14,11 +14,17 @@ import {
WorkerMode,
} from './protocol';
export class WorkerExitedError extends Error {
constructor(codeOrSignal: number | string) {
super(`Worker exited with unexpected ${codeOrSignal} code`);
}
}
/**
* Pool of workers.
*/
export class WorkerPool {
private readonly workers: Array<{ worker: cluster.Worker; active: number }> = [];
private readonly workers: Array<{ worker: Observable<cluster.Worker>; active: number }> = [];
private workIdCounter = 0;
/**
@ -41,10 +47,13 @@ export class WorkerPool {
const target = this.workers[0];
const id = this.workIdCounter++;
target.active++;
target.worker.send({ type: MessageType.WorkerFiles, files, id });
this.sortWorkers();
return fromEvent<[WorkerMessage]>(target.worker, 'message').pipe(
return target.worker.pipe(
switchMap((worker) => {
worker.send({ type: MessageType.WorkerFiles, files, id });
return fromEvent<[WorkerMessage]>(worker, 'message');
}),
map(([m]) => m),
filter((m) => m.id === id),
take(1),
@ -60,9 +69,14 @@ export class WorkerPool {
}
private spawnWorker() {
const worker = { worker: cluster.fork(), active: 0 };
this.workers.unshift(worker);
worker.worker.send({
const worker = cluster.fork();
const subject = new BehaviorSubject(worker);
this.workers.unshift({ worker: subject, active: 0 });
worker.on('exit', (code, signal) => subject.error(new WorkerExitedError(code ?? signal)));
worker.on('error', (err) => subject.error(err));
worker.send({
mode: this.options.check
? WorkerMode.Assert
: this.options.write

Просмотреть файл

@ -6,7 +6,7 @@ import { readFile, writeFile } from 'fs';
import * as prettier from 'prettier';
import { combineLatest, Observable, of, Subject } from 'rxjs';
import { last, mergeMap } from 'rxjs/operators';
import { promisify } from 'util';
import { inspect, promisify } from 'util';
import {
IFilesMessage,
IFormattedMessage,
@ -32,6 +32,7 @@ function runFormatting(
const output: IFormattedMessage = {
files: files.files.length,
formatted: [],
failed: [],
id: files.id,
type: MessageType.Formatted,
};
@ -39,10 +40,17 @@ function runFormatting(
return of(...files.files).pipe(
mergeMap(async (file) => {
const contents = await readFileAsync(file.path, 'utf-8');
const formatted = prettier.format(contents, {
...(await prettier.resolveConfig(file.path)),
filepath: file.path,
});
let formatted: string;
try {
formatted = prettier.format(contents, {
...(await prettier.resolveConfig(file.path)),
filepath: file.path,
});
} catch (e) {
process.stderr.write('\r\n' + inspect(e) + '\r\n');
output.failed.push(file);
return output;
}
if (formatted === contents) {
return output;
@ -76,7 +84,7 @@ export function startWorker() {
}
});
combineLatest(settings, files)
combineLatest([settings, files])
.pipe(mergeMap(([s, f]) => runFormatting(s, f)))
.subscribe(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion

Просмотреть файл

@ -14,5 +14,8 @@
"lib": ["es6", "es7"],
"outDir": "dist",
"types": ["node"]
}
},
"include": [
"src"
]
}