Skip to content

Commit

Permalink
fix: clean cancel on SIGINT
Browse files Browse the repository at this point in the history
  • Loading branch information
loopingz committed Jan 16, 2024
1 parent a8610f3 commit 90c8627
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 1 deletion.
21 changes: 21 additions & 0 deletions packages/core/src/core.spec.ts
Expand Up @@ -7,6 +7,7 @@ import { Core, OriginFilter, WebsiteOriginFilter } from "./core";
import {
Authentication,
Bean,
CancelablePromise,
ConsoleLoggerService,
ContextProvider,
CoreModel,
Expand Down Expand Up @@ -664,6 +665,26 @@ class CoreTest extends WebdaTest {
core.createServices();
}

@test
async sigintPromises() {
let stub = sinon.stub(process, "exit").callsFake(<any>(() => {}));
try {
let found = false;
let p = new CancelablePromise(
() => {},
async () => {
found = true;
}
);
process.emit("SIGINT");
// It should be cancelled
await assert.rejects(p, /Cancelled/);
assert.strictEqual(found, true);
} finally {
stub.restore();
}
}

@test
async cov() {
//assert.deepStrictEqual(this.webda.getDeployers(), {});
Expand Down
33 changes: 33 additions & 0 deletions packages/core/src/core.ts
Expand Up @@ -428,6 +428,10 @@ export class Core<E extends CoreEvents = CoreEvents> extends events.EventEmitter
* System context
*/
protected globalContext: GlobalContext;
/**
*
*/
interuptables: { cancel: () => Promise<void> }[] = [];

/**
* @params {Object} config - The configuration Object, if undefined will load the configuration file
Expand All @@ -438,6 +442,16 @@ export class Core<E extends CoreEvents = CoreEvents> extends events.EventEmitter
// Store WebdaCore in process to avoid conflict with import
// @ts-ignore
Core.singleton = process.webda = this;
/**
* SIGINT handler
*/
process.on("SIGINT", async () => {
if (Core.get().interuptables.length > 0) {
console.log("Received SIGINT. Cancelling all interuptables.");
await Promise.all(Core.get().interuptables.map(i => i.cancel()));
}
process.exit(0);
});
this.workerOutput = application.getWorkerOutput();
this.logger = new Logger(this.workerOutput, "@webda/core/lib/core.js");
this.application = application || new UnpackedApplication(".");
Expand Down Expand Up @@ -473,6 +487,25 @@ export class Core<E extends CoreEvents = CoreEvents> extends events.EventEmitter
this.setGlobalContext(new GlobalContext(this));
}

/**
* Register a cancelable process
* @param interuptable
*/
public static registerInteruptableProcess(interuptable: { cancel: () => Promise<void> }) {
Core.get().interuptables.push(interuptable);
}

/**
* Unregister a cancelable process
* @param interuptable
*/
public static unregisterInteruptableProcess(interuptable: { cancel: () => Promise<void> }) {
const id = Core.get().interuptables.findIndex(i => i === interuptable);
if (id >= 0) {
Core.get().interuptables.splice(id, 1);
}
}

/**
* Get the current script location
* @returns
Expand Down
6 changes: 5 additions & 1 deletion packages/core/src/utils/waiter.ts
@@ -1,5 +1,5 @@
import { v4 as uuidv4 } from "uuid";
import { Logger } from "../index";
import { Core, Logger } from "../index";

/**
* Function that define the amount of time between calls
Expand Down Expand Up @@ -150,10 +150,12 @@ export class CancelablePromise<T = void> extends Promise<T> {
await onCancel();
}
reject("Cancelled");
Core.unregisterInteruptableProcess(this);
};
callback(resolve, reject);
});
this.cancel = localReject;
Core.registerInteruptableProcess(this);
}
}

Expand All @@ -171,6 +173,7 @@ export class CancelableLoopPromise extends Promise<void> {
await onCancel();
}
shouldRun = false;
Core.unregisterInteruptableProcess(this);
};
let loop = () => {
if (shouldRun) {
Expand All @@ -180,6 +183,7 @@ export class CancelableLoopPromise extends Promise<void> {
resolve(callback(localReject).then(loop));
});
this.cancel = localReject;
Core.registerInteruptableProcess(this);
}

static get [Symbol.species]() {
Expand Down

0 comments on commit 90c8627

Please sign in to comment.