microsoft/qdk

Public

mirrored fromhttps://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
iadavis/pipeline-issue-debugging

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

source/npm/qsharp/src/workers/node.ts

96lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4import { dirname, join } from "node:path";
5import { fileURLToPath } from "node:url";
6import {
7 Worker,
8 isMainThread,
9 parentPort,
10 workerData,
11} from "node:worker_threads";
12import * as wasm from "../../lib/nodejs/qsc_wasm.cjs";
13import { log } from "../log.js";
14import {
15 IServiceEventMessage,
16 IServiceProxy,
17 ServiceMethods,
18 ServiceProtocol,
19 createProxyInternal,
20 initService,
21} from "./common.js";
22
23/**
24 * Creates an initializes a service, setting it up to receive requests.
25 * This function to be is used in the worker.
26 *
27 * @param serviceProtocol An object that describes the service: its constructor, methods and events
28 */
29export function createWorker<
30 TService extends ServiceMethods<TService>,
31 TServiceEventMsg extends IServiceEventMessage,
32>(protocol: ServiceProtocol<TService, TServiceEventMsg>): void {
33 if (isMainThread)
34 throw "Worker script should be loaded in a Worker thread only";
35
36 const port = parentPort!;
37
38 const postMessage = port.postMessage.bind(port);
39
40 const invokeService = initService<TService, TServiceEventMsg>(
41 postMessage,
42 protocol,
43 wasm as any, // Need to cast due to difference in web and node wasm types
44 workerData && typeof workerData.qscLogLevel === "number"
45 ? workerData.qscLogLevel
46 : undefined,
47 );
48
49 function messageHandler(data: any) {
50 if (!data.type || typeof data.type !== "string") {
51 log.error(`Unrecognized msg: %O"`, data);
52 return;
53 }
54
55 invokeService(data);
56 }
57
58 port.addListener("message", messageHandler);
59}
60
61/**
62 * Creates and initializes a service in a worker thread, and returns a proxy for the service
63 * to be used from the main thread.
64 *
65 * @param workerArg The the URL of the service web worker script.
66 * @param wasmModule The wasm module to initialize the service with
67 * @param serviceProtocol An object that describes the service: its constructor, methods and events
68 * @returns A proxy object that implements the service interface.
69 * This interface can now be used as if calling into the real service,
70 * and the calls will be proxied to the web worker.
71 */
72export function createProxy<
73 TService extends ServiceMethods<TService>,
74 TServiceEventMsg extends IServiceEventMessage,
75>(
76 workerArg: string,
77 serviceProtocol: ServiceProtocol<TService, TServiceEventMsg>,
78): TService & IServiceProxy {
79 const thisDir = dirname(fileURLToPath(import.meta.url));
80 const worker = new Worker(join(thisDir, workerArg), {
81 workerData: { qscLogLevel: log.getLogLevel() },
82 });
83
84 // Create the proxy which will forward method calls to the worker
85 const proxy = createProxyInternal<TService, TServiceEventMsg>(
86 // If you lose the 'this' binding, some environments have issues.
87 worker.postMessage.bind(worker),
88 () => worker.terminate(),
89 serviceProtocol.methods,
90 );
91
92 // Let proxy handle response and event messages from the worker
93 worker.addListener("message", proxy.onMsgFromWorker);
94
95 return proxy;
96}
97