Skip to content

Commit

Permalink
Allow async methods on worker proxy (#7088)
Browse files Browse the repository at this point in the history
Co-authored-by: Mathieu Marchand <matmarchand@users.noreply.github.com>
Co-authored-by: Paul Connelly <22944042+pmconne@users.noreply.github.com>
  • Loading branch information
3 people authored Aug 15, 2024
1 parent f7fffa2 commit ece72d6
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@itwin/core-frontend",
"comment": "",
"type": "none"
}
],
"packageName": "@itwin/core-frontend"
}
25 changes: 25 additions & 0 deletions core/frontend/src/test/worker/WorkerProxy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,29 @@ describe("WorkerProxy", () => {

worker.terminate();
});

it("returns results out of sequence if caller does not await each operation", async () => {
const worker = createWorker();

const [slowest, slow, fast] = await Promise.all([
worker.someVeryLongRunningAsyncOperation(),
worker.someLongRunningAsyncOperation(),
worker.someFastSynchronousOperation(),
]);

expect(fast).to.be.lessThan(slow);
expect(slow).to.be.lessThan(slowest);
worker.terminate();
});

it("returns results in sequence if caller awaits each operation", async () => {
const worker = createWorker();

const first = await worker.someVeryLongRunningAsyncOperation();
const second = await worker.someLongRunningAsyncOperation();
const third = await worker.someFastSynchronousOperation();

expect(first).to.be.lessThan(second);
expect(second).to.be.lessThan(third);
});
});
24 changes: 24 additions & 0 deletions core/frontend/src/test/worker/test-worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ export interface TestWorker {
throwString(): never;
setTransfer(wantTransfer: boolean): undefined;
createGraphic(context: WorkerGraphicDescriptionContextProps): WorkerGraphic;
someVeryLongRunningAsyncOperation(): Promise<number>;
someLongRunningAsyncOperation(): Promise<number>;
someFastSynchronousOperation(): number;
}

let doTransfer = false;
Expand All @@ -35,6 +38,15 @@ function maybeTransfer<T>(result: T): T | { result: T, transfer: Transferable[]
return { result, transfer: [] };
}

let globalTickCounter = 0;

async function waitNTicks(nTicks: number): Promise<void> {
let counter = 0;
while (++counter < nTicks) {
await new Promise<void>((resolve: any) => setTimeout(resolve, 1));
}
}

registerWorker<TestWorker>({
zero: () => maybeTransfer("zero"),
one: (arg: string) => maybeTransfer(arg),
Expand Down Expand Up @@ -85,4 +97,16 @@ registerWorker<TestWorker>({
transfer: Array.from(transferables),
};
},

someVeryLongRunningAsyncOperation: async () => {
await waitNTicks(10);
return ++globalTickCounter;
},
someLongRunningAsyncOperation: async () => {
await waitNTicks(5);
return ++globalTickCounter;
},
someFastSynchronousOperation: () => {
return ++globalTickCounter;
},
});
7 changes: 5 additions & 2 deletions core/frontend/src/workers/RegisterWorker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,17 @@ interface WorkerRequest {
* @beta
*/
export function registerWorker<T>(impl: WorkerImplementation<T>): void {
onmessage = (e: MessageEvent) => {
onmessage = async (e: MessageEvent) => {
const req = e.data as WorkerRequest;
const msgId = req.msgId;
try {
assert(typeof req === "object" && "operation" in req && "payload" in req && "msgId" in req);
const func = (impl as any)[req.operation];
assert(typeof func === "function");
const ret = func(req.payload);
let ret = func(req.payload);
if (ret instanceof Promise) {
ret = await ret;
}
if (typeof ret === "object" && "transfer" in ret)
postMessage({ result: ret.result, msgId }, { transfer: ret.transfer });
else
Expand Down

0 comments on commit ece72d6

Please sign in to comment.