Skip to content

Commit

Permalink
feat: introduce --num-workers option / -j flag (#4)
Browse files Browse the repository at this point in the history
This patch introduces a CLI option to limit the number of workers processes used by `igniter`. This only affects `ExecTask` tasks.
  • Loading branch information
Benjozork authored Jul 17, 2021
1 parent fcf70cd commit a28cf56
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 3 deletions.
20 changes: 18 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"reflect-metadata": "^0.1.13",
"rollup": "^2.39.0",
"rollup-plugin-add-shebang": "^0.3.1",
"task-pool": "^0.1.1",
"ts-jest": "^26.5.1",
"tslib": "^2.1.0",
"tsyringe": "^4.4.0",
Expand Down
3 changes: 3 additions & 0 deletions src/Binary.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Command } from 'commander';
import { Pool } from 'task-pool';
import { findConfigPath, loadConfigTask } from './Helpers';
import { Context } from './Library/Contracts/Context';
import { version } from '../package.json';
Expand All @@ -7,6 +8,7 @@ import Cache from './Cache';

const binary = (new Command()).version(version)
.option('-c, --config <filename>', 'set the configuration file name', 'igniter.config.mjs')
.option('-j, --num-workers <number>', 'set the maximum number of workers to use', `${Number.MAX_SAFE_INTEGER}`)
.option('-r, --regex <regex>', 'regular expression used to filter tasks')
.option('-i, --invert', 'if true, regex will be used to reject tasks')
.option('--no-cache', 'do not skip tasks, even if hash matches cache')
Expand All @@ -24,6 +26,7 @@ const context: Context = {
dryRun: options.dryRun,
filterRegex: options.regex ? RegExp(options.regex) : undefined,
invertRegex: options.invert,
taskPool: new Pool({ limit: options.numWorkers }),
};

// Create and register a cache if needed.
Expand Down
2 changes: 2 additions & 0 deletions src/Library/Contracts/Context.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Pool } from 'task-pool';
import { Cache } from './Cache';

export interface Context {
Expand All @@ -7,4 +8,5 @@ export interface Context {
filterRegex: RegExp|undefined,
invertRegex: boolean,
cache?: Cache,
taskPool: Pool,
}
14 changes: 13 additions & 1 deletion src/Library/Tasks/ExecTask.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { exec } from 'child_process';
import { promisify } from 'util';
import GenericTask from './GenericTask';
import { TaskStatus } from '../Contracts/Task';

export default class ExecTask extends GenericTask {
constructor(
Expand All @@ -10,7 +11,18 @@ export default class ExecTask extends GenericTask {
) {
const commands = typeof command === 'string' ? [command] : command;
super(key, async () => {
for await (const cmd of commands) await promisify(exec)(cmd);
for await (const cmd of commands) {
const poolExec = this.context.taskPool.promise.wrap(promisify(exec));

const task = poolExec(cmd);

this.status = TaskStatus.Queued;
task.on('run', () => {
this.status = TaskStatus.Running;
});

await task;
}
}, hashFolders);
}
}
51 changes: 51 additions & 0 deletions src/task-pool.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
declare module "task-pool" {
export type PoolStyle = 'callback' | 'promise'

export interface PoolInit {
timeout: number,
style: PoolStyle,
limit: number,
}

export interface PoolTaskOptions {
timeout: number,
style: PoolStyle,
}

export type PoolTaskFunction<TArgs> = (...args: TArgs[]) => any

export interface PoolTask<TFnArgs> {
fn: PoolTaskFunction<TFnArgs>,
timeout: number,
style: PoolStyle,
args: any[],
on: (event: string, fn: (event: any) => void) => void,
}

export type PoolTaskFactory<TPoolStyle extends PoolStyle> = <TArgs>(...args: TArgs[]) =>
(TPoolStyle extends 'callback' ? PoolTask<TArgs> : Promise<any> & PoolTask<any>)

export class Pool<TPoolStyle extends PoolStyle = 'callback'> {
constructor(init: Partial<PoolInit>)

timeout: Pick<PoolInit, 'timeout'>

style: TPoolStyle

limit: Pick<PoolInit, 'limit'>

running: number

queue: PoolTask<any>[]

wrap(Function, options?: Partial<PoolTaskOptions>): PoolTaskFactory<TPoolStyle>

next()

start(): boolean

add(task: PoolTask<any>)

get promise(): Pool<'promise'>
}
}

0 comments on commit a28cf56

Please sign in to comment.