microsoft/qdk

Public

mirrored from https://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.21.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

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

96lines · modeblame

c23c2ae4Mine Starks2 years ago1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4import { dirname, join } from "node:path";
5import { fileURLToPath } from "node:url";
6import {
7Worker,
8isMainThread,
9parentPort,
10workerData,
11} from "node:worker_threads";
95956855Bill Ticehurst1 years ago12import * as wasm from "../../lib/nodejs/qsc_wasm.cjs";
c23c2ae4Mine Starks2 years ago13import { log } from "../log.js";
14import {
15IServiceEventMessage,
16IServiceProxy,
17ServiceMethods,
18ServiceProtocol,
19createProxyInternal,
20initService,
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<
30TService extends ServiceMethods<TService>,
31TServiceEventMsg extends IServiceEventMessage,
32>(protocol: ServiceProtocol<TService, TServiceEventMsg>): void {
33if (isMainThread)
34throw "Worker script should be loaded in a Worker thread only";
35
4d6e26abBill Ticehurst1 years ago36const port = parentPort!;
c23c2ae4Mine Starks2 years ago37
38const postMessage = port.postMessage.bind(port);
39
40const invokeService = initService<TService, TServiceEventMsg>(
41postMessage,
42protocol,
021250d6Bill Ticehurst2 years ago43wasm as any, // Need to cast due to difference in web and node wasm types
c23c2ae4Mine Starks2 years ago44workerData && typeof workerData.qscLogLevel === "number"
45? workerData.qscLogLevel
46: undefined,
47);
48
49function messageHandler(data: any) {
50if (!data.type || typeof data.type !== "string") {
51log.error(`Unrecognized msg: %O"`, data);
52return;
53}
54
55invokeService(data);
56}
57
58port.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<
73TService extends ServiceMethods<TService>,
74TServiceEventMsg extends IServiceEventMessage,
75>(
76workerArg: string,
77serviceProtocol: ServiceProtocol<TService, TServiceEventMsg>,
78): TService & IServiceProxy {
79const thisDir = dirname(fileURLToPath(import.meta.url));
80const worker = new Worker(join(thisDir, workerArg), {
81workerData: { qscLogLevel: log.getLogLevel() },
82});
83
84// Create the proxy which will forward method calls to the worker
85const proxy = createProxyInternal<TService, TServiceEventMsg>(
86// If you lose the 'this' binding, some environments have issues.
87worker.postMessage.bind(worker),
88() => worker.terminate(),
89serviceProtocol.methods,
90);
91
92// Let proxy handle response and event messages from the worker
93worker.addListener("message", proxy.onMsgFromWorker);
94
95return proxy;
96}