Skip to content

Commit 578db5b

Browse files
authored
fix: improve compatibility with node>=8.10 <12.11 (#35)
1 parent ebfb59d commit 578db5b

4 files changed

Lines changed: 36 additions & 18 deletions

File tree

.changeset/fifty-pets-taste.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"synckit": patch
3+
---
4+
5+
fix: improve compatibility with node >=8.10 <12.11

README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ Perform async work synchronously in Node.js using `worker_threads`, or `child_pr
2323
- [Usage](#usage)
2424
- [Install](#install)
2525
- [API](#api)
26-
- [Env variables](#env-variables)
26+
- [`Node` compatibility](#node-compatibility)
27+
- [Envs](#envs)
2728
- [TypeScript](#typescript)
2829
- [Benchmark](#benchmark)
2930
- [Changelog](#changelog)
@@ -71,7 +72,11 @@ You must make sure:
7172
1. if `worker_threads` is enabled (by default), the `result` is serialized by [`Structured Clone Algorithm`](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm)
7273
2. if `child_process` is used, the `result` is serialized by `JSON.stringify`
7374

74-
### Env variables
75+
### `Node` compatibility
76+
77+
`worker_threads` is available from `Node 8.10` with flag `--experimental-worker` and only enabled by default from `Node 12.11`, so you may want to enable it by using `node --experimental-worker` or setting env `NODE_OPTIONS="--experimental-worker"` for better performance.
78+
79+
### Envs
7580

7681
1. `SYNCKIT_WORKER_THREADS`: whether or not enable `worker_threads`, it's enabled by default, set as `0` to disable
7782
2. `SYNCKIT_BUFFER_SIZE`: `bufferSize` to create `SharedArrayBuffer` for `worker_threads` (default as `1024`), or `maxBuffer` for `child_process` (no default)

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"author": "JounQin <admin@1stg.me>",
77
"license": "MIT",
88
"engines": {
9-
"node": ">=12"
9+
"node": ">=8.10"
1010
},
1111
"main": "lib",
1212
"module": "lib/es2015",
@@ -82,7 +82,7 @@
8282
]
8383
},
8484
"typeCoverage": {
85-
"atLeast": 99.21,
85+
"atLeast": 99.2,
8686
"cache": true,
8787
"detail": true,
8888
"ignoreAsAssertion": true,

src/index.ts

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,6 @@ import { execSync } from 'child_process'
22
import { tmpdir as _tmpdir } from 'os'
33
import path from 'path'
44
import fs from 'fs'
5-
import {
6-
MessageChannel,
7-
parentPort,
8-
receiveMessageOnPort,
9-
Worker,
10-
workerData,
11-
} from 'worker_threads'
125

136
import { v4 as uuid } from 'uuid'
147

@@ -29,11 +22,24 @@ export * from './types'
2922
*/
3023
export const tmpdir = fs.realpathSync(_tmpdir())
3124

25+
let workerThreads: typeof import('worker_threads') | undefined
26+
27+
try {
28+
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-unsafe-assignment
29+
workerThreads = require('worker_threads')
30+
} catch {
31+
/* istanbul ignore next */
32+
console.warn(
33+
'`worker_threads` is not available in current environment,\nyou may want to enable it by using `node --experimental-worker` or setting env `NODE_OPTIONS="--experimental-worker"` for better performance',
34+
)
35+
}
36+
3237
const { SYNCKIT_WORKER_THREADS, SYNCKIT_BUFFER_SIZE, SYNCKIT_TIMEOUT } =
3338
process.env
3439

3540
export const useWorkerThreads =
36-
!SYNCKIT_WORKER_THREADS || !['0', 'false'].includes(SYNCKIT_WORKER_THREADS)
41+
!!workerThreads &&
42+
(!SYNCKIT_WORKER_THREADS || !['0', 'false'].includes(SYNCKIT_WORKER_THREADS))
3743

3844
export const DEFAULT_BUFFER_SIZE = SYNCKIT_BUFFER_SIZE
3945
? +SYNCKIT_BUFFER_SIZE
@@ -118,11 +124,12 @@ function startWorkerThread<R, T extends AnyAsyncFn<R>>(
118124
bufferSize = DEFAULT_WORKER_BUFFER_SIZE,
119125
timeout?: number,
120126
) {
121-
const { port1: mainPort, port2: workerPort } = new MessageChannel()
127+
const { port1: mainPort, port2: workerPort } =
128+
new workerThreads!.MessageChannel()
122129

123130
const isTs = workerPath.endsWith('.ts')
124131

125-
const worker = new Worker(
132+
const worker = new workerThreads!.Worker(
126133
isTs
127134
? `require('ts-node/register');require(require('worker_threads').workerData.workerPath)`
128135
: workerPath,
@@ -156,7 +163,8 @@ function startWorkerThread<R, T extends AnyAsyncFn<R>>(
156163
id: id2,
157164
result,
158165
error,
159-
} = receiveMessageOnPort(mainPort)!.message as WorkerToMainMessage<R>
166+
} = workerThreads!.receiveMessageOnPort(mainPort)!
167+
.message as WorkerToMainMessage<R>
160168

161169
/* istanbul ignore if */
162170
if (id !== id2) {
@@ -177,7 +185,7 @@ function startWorkerThread<R, T extends AnyAsyncFn<R>>(
177185

178186
export async function runAsWorker<T extends AnyAsyncFn>(fn: T): Promise<void>
179187
export async function runAsWorker<R, T extends AnyAsyncFn<R>>(fn: T) {
180-
if (!workerData) {
188+
if (!workerThreads?.workerData) {
181189
const filename = process.argv[2]
182190
const content = fs.readFileSync(filename, 'utf8')
183191
const args = JSON.parse(content) as Parameters<T>
@@ -197,9 +205,9 @@ export async function runAsWorker<R, T extends AnyAsyncFn<R>>(fn: T) {
197205
}
198206

199207
/* istanbul ignore next */
200-
const { workerPort } = workerData as WorkerData
208+
const { workerPort } = workerThreads.workerData as WorkerData
201209
/* istanbul ignore next */
202-
parentPort!.on(
210+
workerThreads.parentPort!.on(
203211
'message',
204212
({ sharedBuffer, id, args }: MainToWorkerMessage<Parameters<T>>) => {
205213
// eslint-disable-next-line @typescript-eslint/no-floating-promises

0 commit comments

Comments
 (0)