Skip to content

Commit

Permalink
fix: improve compatibility with node>=8.10 <12.11 (#35)
Browse files Browse the repository at this point in the history
  • Loading branch information
JounQin committed Jul 13, 2021
1 parent ebfb59d commit 578db5b
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 18 deletions.
5 changes: 5 additions & 0 deletions .changeset/fifty-pets-taste.md
@@ -0,0 +1,5 @@
---
"synckit": patch
---

fix: improve compatibility with node >=8.10 <12.11
9 changes: 7 additions & 2 deletions README.md
Expand Up @@ -23,7 +23,8 @@ Perform async work synchronously in Node.js using `worker_threads`, or `child_pr
- [Usage](#usage)
- [Install](#install)
- [API](#api)
- [Env variables](#env-variables)
- [`Node` compatibility](#node-compatibility)
- [Envs](#envs)
- [TypeScript](#typescript)
- [Benchmark](#benchmark)
- [Changelog](#changelog)
Expand Down Expand Up @@ -71,7 +72,11 @@ You must make sure:
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)
2. if `child_process` is used, the `result` is serialized by `JSON.stringify`

### Env variables
### `Node` compatibility

`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.

### Envs

1. `SYNCKIT_WORKER_THREADS`: whether or not enable `worker_threads`, it's enabled by default, set as `0` to disable
2. `SYNCKIT_BUFFER_SIZE`: `bufferSize` to create `SharedArrayBuffer` for `worker_threads` (default as `1024`), or `maxBuffer` for `child_process` (no default)
Expand Down
4 changes: 2 additions & 2 deletions package.json
Expand Up @@ -6,7 +6,7 @@
"author": "JounQin <admin@1stg.me>",
"license": "MIT",
"engines": {
"node": ">=12"
"node": ">=8.10"
},
"main": "lib",
"module": "lib/es2015",
Expand Down Expand Up @@ -82,7 +82,7 @@
]
},
"typeCoverage": {
"atLeast": 99.21,
"atLeast": 99.2,
"cache": true,
"detail": true,
"ignoreAsAssertion": true,
Expand Down
36 changes: 22 additions & 14 deletions src/index.ts
Expand Up @@ -2,13 +2,6 @@ import { execSync } from 'child_process'
import { tmpdir as _tmpdir } from 'os'
import path from 'path'
import fs from 'fs'
import {
MessageChannel,
parentPort,
receiveMessageOnPort,
Worker,
workerData,
} from 'worker_threads'

import { v4 as uuid } from 'uuid'

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

let workerThreads: typeof import('worker_threads') | undefined

try {
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-unsafe-assignment
workerThreads = require('worker_threads')
} catch {
/* istanbul ignore next */
console.warn(
'`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',
)
}

const { SYNCKIT_WORKER_THREADS, SYNCKIT_BUFFER_SIZE, SYNCKIT_TIMEOUT } =
process.env

export const useWorkerThreads =
!SYNCKIT_WORKER_THREADS || !['0', 'false'].includes(SYNCKIT_WORKER_THREADS)
!!workerThreads &&
(!SYNCKIT_WORKER_THREADS || !['0', 'false'].includes(SYNCKIT_WORKER_THREADS))

export const DEFAULT_BUFFER_SIZE = SYNCKIT_BUFFER_SIZE
? +SYNCKIT_BUFFER_SIZE
Expand Down Expand Up @@ -118,11 +124,12 @@ function startWorkerThread<R, T extends AnyAsyncFn<R>>(
bufferSize = DEFAULT_WORKER_BUFFER_SIZE,
timeout?: number,
) {
const { port1: mainPort, port2: workerPort } = new MessageChannel()
const { port1: mainPort, port2: workerPort } =
new workerThreads!.MessageChannel()

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

const worker = new Worker(
const worker = new workerThreads!.Worker(
isTs
? `require('ts-node/register');require(require('worker_threads').workerData.workerPath)`
: workerPath,
Expand Down Expand Up @@ -156,7 +163,8 @@ function startWorkerThread<R, T extends AnyAsyncFn<R>>(
id: id2,
result,
error,
} = receiveMessageOnPort(mainPort)!.message as WorkerToMainMessage<R>
} = workerThreads!.receiveMessageOnPort(mainPort)!
.message as WorkerToMainMessage<R>

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

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

/* istanbul ignore next */
const { workerPort } = workerData as WorkerData
const { workerPort } = workerThreads.workerData as WorkerData
/* istanbul ignore next */
parentPort!.on(
workerThreads.parentPort!.on(
'message',
({ sharedBuffer, id, args }: MainToWorkerMessage<Parameters<T>>) => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
Expand Down

0 comments on commit 578db5b

Please sign in to comment.