gatsby-worker
Advanced tools
Comparing version 0.1.0-next.0 to 0.1.0-next.1
@@ -6,2 +6,8 @@ # Change Log | ||
# [0.1.0-next.1](https://github.com/gatsbyjs/gatsby/compare/gatsby-worker@0.1.0-next.0...gatsby-worker@0.1.0-next.1) (2021-07-02) | ||
### Features | ||
- **gatsby-worker:** add messaging api ([#32159](https://github.com/gatsbyjs/gatsby/issues/32159)) ([5a93e74](https://github.com/gatsbyjs/gatsby/commit/5a93e7485b2718b44a59e595c5b1e896fe9802cb)) | ||
# 0.1.0-next.0 (2021-07-01) | ||
@@ -8,0 +14,0 @@ |
@@ -0,1 +1,6 @@ | ||
export interface IGatsbyWorkerMessenger<MessagesFromParent = unknown, MessagesFromChild = MessagesFromParent> { | ||
onMessage: (listener: (msg: MessagesFromParent) => void) => void; | ||
sendMessage: (msg: MessagesFromChild) => void; | ||
messagingVersion: 1; | ||
} | ||
/** | ||
@@ -5,2 +10,3 @@ * Used to check wether current context is executed in worker process | ||
declare let isWorker: boolean; | ||
export { isWorker }; | ||
declare let getMessenger: <MessagesFromParent = unknown, MessagesFromChild = MessagesFromParent>() => IGatsbyWorkerMessenger<MessagesFromParent, MessagesFromChild> | undefined; | ||
export { isWorker, getMessenger }; |
"use strict"; | ||
exports.__esModule = true; | ||
exports.isWorker = void 0; | ||
exports.getMessenger = exports.isWorker = void 0; | ||
@@ -16,4 +16,11 @@ var _types = require("./types"); | ||
let getMessenger = function () { | ||
return undefined; | ||
}; | ||
exports.getMessenger = getMessenger; | ||
if (process.send && process.env.GATSBY_WORKER_MODULE_PATH) { | ||
exports.isWorker = isWorker = true; | ||
const listeners = []; | ||
const ensuredSendToMain = process.send.bind(process); | ||
@@ -35,2 +42,19 @@ | ||
const MESSAGING_VERSION = 1; | ||
exports.getMessenger = getMessenger = function () { | ||
return { | ||
onMessage(listener) { | ||
listeners.push(listener); | ||
}, | ||
sendMessage(msg) { | ||
const poolMsg = [_types.CUSTOM_MESSAGE, msg]; | ||
ensuredSendToMain(poolMsg); | ||
}, | ||
messagingVersion: MESSAGING_VERSION | ||
}; | ||
}; | ||
const child = require(process.env.GATSBY_WORKER_MODULE_PATH); | ||
@@ -56,2 +80,6 @@ | ||
process.off(`message`, messageHandler); | ||
} else if (msg[0] === _types.CUSTOM_MESSAGE) { | ||
for (const listener of listeners) { | ||
listener(msg[1]); | ||
} | ||
} | ||
@@ -58,0 +86,0 @@ } |
@@ -23,3 +23,3 @@ interface IWorkerOptions { | ||
*/ | ||
export declare class WorkerPool<WorkerModuleExports = Record<string, unknown>> { | ||
export declare class WorkerPool<WorkerModuleExports = Record<string, unknown>, MessagesFromParent = unknown, MessagesFromChild = MessagesFromParent> { | ||
/** | ||
@@ -40,2 +40,3 @@ * Schedule task execution on all workers. Useful for setting up workers | ||
private idleWorkers; | ||
private listeners; | ||
constructor(workerPath: string, options?: IWorkerOptions); | ||
@@ -52,3 +53,5 @@ /** | ||
private scheduleWorkAll; | ||
onMessage(listener: (msg: MessagesFromChild, workerId: number) => void): void; | ||
sendMessage(msg: MessagesFromParent, workerId: number): void; | ||
} | ||
export * from "./child"; |
@@ -59,2 +59,3 @@ "use strict"; | ||
this.idleWorkers = new Set(); | ||
this.listeners = []; | ||
const single = {}; | ||
@@ -153,2 +154,6 @@ const all = {}; | ||
task.reject(error); | ||
} else if (msg[0] === _types.CUSTOM_MESSAGE) { | ||
for (const listener of this.listeners) { | ||
listener(msg[1], workerId); | ||
} | ||
} | ||
@@ -247,4 +252,19 @@ }); | ||
onMessage(listener) { | ||
this.listeners.push(listener); | ||
} | ||
sendMessage(msg, workerId) { | ||
const worker = this.workers[workerId - 1]; | ||
if (!worker) { | ||
throw new Error(`There is no worker with "${workerId}" id.`); | ||
} | ||
const poolMsg = [_types.CUSTOM_MESSAGE, msg]; | ||
worker.worker.send(poolMsg); | ||
} | ||
} | ||
exports.WorkerPool = WorkerPool; |
@@ -5,2 +5,4 @@ export declare const EXECUTE = 1; | ||
export declare const END = 0; | ||
export declare const CUSTOM_MESSAGE = 4; | ||
declare type CustomMessage = [typeof CUSTOM_MESSAGE, unknown]; | ||
declare type FunctionName = string | number | symbol; | ||
@@ -10,3 +12,3 @@ declare type FunctionArgs = Array<any>; | ||
declare type EndMessage = [typeof END]; | ||
export declare type ParentMessageUnion = ExecuteMessage | EndMessage; | ||
export declare type ParentMessageUnion = ExecuteMessage | EndMessage | CustomMessage; | ||
declare type ErrorType = string; | ||
@@ -24,3 +26,3 @@ declare type ErrorMessage = string; | ||
declare type TaskResult = [typeof RESULT, ResultType]; | ||
export declare type ChildMessageUnion = TaskError | TaskResult; | ||
export declare type ChildMessageUnion = TaskError | TaskResult | CustomMessage; | ||
export {}; |
"use strict"; | ||
exports.__esModule = true; | ||
exports.END = exports.RESULT = exports.ERROR = exports.EXECUTE = void 0; | ||
exports.CUSTOM_MESSAGE = exports.END = exports.RESULT = exports.ERROR = exports.EXECUTE = void 0; | ||
const EXECUTE = 0b01; | ||
@@ -12,2 +12,4 @@ exports.EXECUTE = EXECUTE; | ||
const END = 0b00; | ||
exports.END = END; | ||
exports.END = END; | ||
const CUSTOM_MESSAGE = 0b100; | ||
exports.CUSTOM_MESSAGE = CUSTOM_MESSAGE; |
{ | ||
"name": "gatsby-worker", | ||
"description": "Utility to create worker pools", | ||
"version": "0.1.0-next.0", | ||
"version": "0.1.0-next.1", | ||
"author": "Michal Piechowiak<misiek.piechowiak@gmail.com>", | ||
@@ -41,3 +41,3 @@ "bugs": { | ||
}, | ||
"gitHead": "db030ef900abd051151bbcd6c9ee4c9e41f58fd3" | ||
"gitHead": "8a68d8f27ab7c500ee01eb9cd2d0b8f672b6cef0" | ||
} |
128
README.md
@@ -20,3 +20,3 @@ # gatsby-worker | ||
File `parent.ts` | ||
File `parent.ts`: | ||
@@ -103,2 +103,128 @@ ```ts | ||
### Messaging | ||
`gatsby-worker` allows sending messages from worker to main and from main to worker at any time. | ||
#### Sending messages from worker | ||
File `message-types.ts`: | ||
```ts | ||
// `gatsby-worker` supports message types. Creating common module that centralize possible messages | ||
// that is shared by worker and parent will ensure messages type safety. | ||
interface IPingMessage { | ||
type: `PING` | ||
} | ||
interface IAnotherMessageFromChild { | ||
type: `OTHER_MESSAGE_FROM_CHILD` | ||
payload: { | ||
foo: string | ||
} | ||
} | ||
export type MessagesFromChild = IPingMessage | IAnotherMessageFromChild | ||
interface IPongMessage { | ||
type: `PONG` | ||
} | ||
interface IAnotherMessageFromParent { | ||
type: `OTHER_MESSAGE_FROM_PARENT` | ||
payload: { | ||
foo: string | ||
} | ||
} | ||
export type MessagesFromParent = IPongMessage | IAnotherMessageFromParent | ||
``` | ||
File `worker.ts`: | ||
```ts | ||
import { getMessenger } from "gatsby-worker" | ||
import { MessagesFromParent, MessagesFromChild } from "./message-types" | ||
const messenger = getMessenger<MessagesFromParent, MessagesFromChild>() | ||
// messenger might be `undefined` if `getMessenger` | ||
// is called NOT in worker context | ||
if (messenger) { | ||
// send a message to a parent | ||
messenger.send({ type: `PING` }) | ||
messenger.send({ | ||
type: `OTHER_MESSAGE_FROM_CHILD`, | ||
payload: { | ||
foo: `bar`, | ||
}, | ||
}) | ||
// following would cause type error as message like that is | ||
// not part of MessagesFromChild type union | ||
// messenger.send({ type: `NOT_PART_OF_TYPES` }) | ||
// start listening to messages from parent | ||
messenger.onMessage(msg => { | ||
switch (msg.type) { | ||
case `PONG`: { | ||
// handle PONG message | ||
break | ||
} | ||
case `OTHER_MESSAGE_FROM_PARENT`: { | ||
// msg.payload.foo will be typed as `string` here | ||
// handle | ||
break | ||
} | ||
// following would cause type error as there is no msg with | ||
// given type as part of MessagesFromParent type union | ||
// case `NOT_PART_OF_TYPES`: {} | ||
} | ||
}) | ||
} | ||
``` | ||
File `parent.ts`: | ||
```ts | ||
import { getMessenger } from "gatsby-worker" | ||
import { MessagesFromParent, MessagesFromChild } from "./message-types" | ||
const workerPool = new WorkerPool< | ||
typeof import("./worker"), | ||
MessagesFromParent, | ||
MessagesFromChild | ||
>( | ||
workerPath: require.resolve(`./worker`) | ||
) | ||
// `sendMessage` on WorkerPool instance requires second parameter | ||
// `workerId` to specify to which worker to send message to | ||
// (`workerId` starts at 1 for first worker). | ||
workerPool.sendMessage( | ||
{ | ||
type: `OTHER_MESSAGE_FROM_PARENT`, | ||
payload: { | ||
foo: `baz` | ||
} | ||
}, | ||
1 | ||
) | ||
// start listening to messages from child | ||
// `onMessage` callback will be called with message sent from worker | ||
// and `workerId` (to identify which worker send this message) | ||
workerPool.onMessage((msg: MessagesFromChild, workerId: number): void => { | ||
switch(msg.type) { | ||
case: `PING`: { | ||
// send message back making sure we send it back to same worker | ||
// that sent `PING` message | ||
workerPool.sendMessage({ type: `PONG` }, workerId) | ||
break | ||
} | ||
} | ||
}) | ||
``` | ||
## Usage with unit tests | ||
@@ -105,0 +231,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
27478
473
252
1