CEC-4854 Trunk-based deploy pipeline (#412)
* CEC-4855: fix manifest deselect (#410) * fix manifest deselect * adjusted blackduck pipeline to run the latest detect version * added blackduck_rapid pipeline to run synopsys detect rapid scans * adjusted deploy pipeline to trun-based model, adjusted test pipeline to use main branch * test image builds * clean up * CEC-4563: add cancel and include results in promise (#411) * splited build and deploy order according to each environment, test builds * clean up * clean up * CEC-4635: prevent false 0 calculation (#413) * prevent false 0 calculation * refactor switch statement --------- Co-authored-by: Tristan Timblin <ttimblin@fiskerinc.com>
This commit is contained in:
@@ -8,7 +8,7 @@ export default class TaskRunner {
|
||||
|
||||
if (total) {
|
||||
this._total = total;
|
||||
this._responses = new Array(total);
|
||||
this._responses = new Array(total).fill(undefined);
|
||||
}
|
||||
|
||||
this._onComplete = new Promise((resolve, reject) => {
|
||||
@@ -18,7 +18,8 @@ export default class TaskRunner {
|
||||
}
|
||||
|
||||
execute() {
|
||||
if (this._running >= this._concurrencyLimit || this._queue.length === 0) {
|
||||
const isBusy = this._running >= this._concurrencyLimit || this._queue.length === 0;
|
||||
if (isBusy || this._paused) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -38,10 +39,16 @@ export default class TaskRunner {
|
||||
}
|
||||
resolve(response);
|
||||
} catch (error) {
|
||||
if (this._responses) {
|
||||
this._responses[index] = new Error(`Task was rejected: ${error}`);
|
||||
}
|
||||
reject(error);
|
||||
} finally {
|
||||
this._running -= 1;
|
||||
this.#progress();
|
||||
this._complete += 1;
|
||||
if (this._complete === this._total) {
|
||||
this._onCompleteResolve(this._responses);
|
||||
}
|
||||
this.execute();
|
||||
}
|
||||
}
|
||||
@@ -51,17 +58,15 @@ export default class TaskRunner {
|
||||
});
|
||||
}
|
||||
|
||||
#progress() {
|
||||
this._complete += 1;
|
||||
if (this._complete === this._total) {
|
||||
this._onCompleteResolve(this._responses);
|
||||
}
|
||||
}
|
||||
|
||||
async onComplete() {
|
||||
if (!this._total) {
|
||||
this._onCompleteReject(new Error("Total is required to determine onComplete."));
|
||||
}
|
||||
return this._onComplete;
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this._concurrencyLimit = 0;
|
||||
this._onCompleteReject(this._responses);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,9 @@ const mockPromise = async (id, ms) => {
|
||||
await new Promise(resolve => setTimeout(resolve, ms));
|
||||
return id;
|
||||
}
|
||||
const mockPromiseReject = async (id, ms) => {
|
||||
return new Promise((_, reject) => setTimeout(reject(id), ms));
|
||||
}
|
||||
const mockPromiseError = async (id, ms) => {
|
||||
await new Promise(resolve => setTimeout(resolve, ms));
|
||||
return new Error(`Task ${id} had an error`);
|
||||
@@ -44,19 +47,10 @@ describe("TaskRunner", () => {
|
||||
it("runs tasks in order", async () => {
|
||||
const actual = [];
|
||||
const taskRunner = new TaskRunner(2);
|
||||
taskRunner.push(asyncFn1)
|
||||
.then((id) => {
|
||||
actual.push(id);
|
||||
});
|
||||
taskRunner.push(asyncFn2)
|
||||
.then((id) => {
|
||||
actual.push(id);
|
||||
});
|
||||
taskRunner.push(asyncFn3)
|
||||
.then((id) => {
|
||||
actual.push(id);
|
||||
});
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
taskRunner.push(asyncFn1).then(id => actual.push(id));
|
||||
taskRunner.push(asyncFn2).then(id => actual.push(id));
|
||||
taskRunner.push(asyncFn3).then(id => actual.push(id));
|
||||
await new Promise(resolve => setTimeout(resolve, 200));
|
||||
expect(actual).toEqual([2, 3, 1]);
|
||||
});
|
||||
|
||||
@@ -72,6 +66,20 @@ describe("TaskRunner", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("resolves a promise when all tasks are complete, even if some are rejected", async () => {
|
||||
const error = new Error(`Task was rejected: 3`);
|
||||
const taskRunner = new TaskRunner(2, 5);
|
||||
taskRunner.push(() => mockPromise(1, 600));
|
||||
taskRunner.push(() => mockPromise(2, 300));
|
||||
taskRunner.push(() => mockPromiseReject(3, 200)).catch(payload => expect(payload).toBe(3));
|
||||
taskRunner.push(() => mockPromise(4, 600));
|
||||
taskRunner.push(() => mockPromise(5, 100));
|
||||
|
||||
await taskRunner.onComplete().then((response) => {
|
||||
expect(response).toStrictEqual([1, 2, error, 4, 5]);
|
||||
});
|
||||
});
|
||||
|
||||
it("resolves a promise when all tasks are complete, even if some fail", async () => {
|
||||
const error = new Error(`Task 3 had an error`);
|
||||
const taskRunner = new TaskRunner(2, 5);
|
||||
@@ -85,7 +93,7 @@ describe("TaskRunner", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("rejects a promise when the total number of tasks is unknown", async () => {
|
||||
it("immediately rejects onComplete when the total number of tasks is unknown", async () => {
|
||||
const taskRunner = new TaskRunner(2);
|
||||
taskRunner.push(() => mockPromise(1, 600));
|
||||
taskRunner.push(() => mockPromise(2, 300));
|
||||
@@ -96,4 +104,21 @@ describe("TaskRunner", () => {
|
||||
expect(error.message).toBe("Total is required to determine onComplete.");
|
||||
});
|
||||
});
|
||||
|
||||
it("cancels a task runner and returns progress", async () => {
|
||||
const taskRunner = new TaskRunner(2, 5);
|
||||
taskRunner.push(() => mockPromise(1, 600));
|
||||
taskRunner.push(() => mockPromise(2, 300));
|
||||
taskRunner.push(() => mockPromise(3, 200));
|
||||
taskRunner.push(() => mockPromise(4, 600));
|
||||
taskRunner.push(() => mockPromise(5, 100));
|
||||
|
||||
setTimeout(() => {
|
||||
taskRunner.cancel();
|
||||
}, 550);
|
||||
|
||||
await taskRunner.onComplete().catch((response) => {
|
||||
expect(response).toStrictEqual([undefined, 2, 3, undefined, undefined]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user