-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
327 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,325 @@ | ||
|
||
# require-worker API docs | ||
|
||
Read README.md before jumping into this documentation. | ||
|
||
The require-worker module creates a seperate nodejs process via `fork`, which that process then uses the native `require` method on the given path. | ||
|
||
Each process can either be dedicated to a single module, or be a shared host to multiple modules. Process & module sharing can be manually specified for what module is shared in the same process as another module. | ||
|
||
There are 2 main interfaces. The require-worker *client* which interacts with the forked process, and the require-worker *host* which interacts with the natively required module within the forked process. | ||
|
||
# Set up | ||
|
||
### Install via npm | ||
|
||
``` | ||
npm install require-worker@pre-v1 --save | ||
``` | ||
|
||
### Require within your nodejs project | ||
|
||
|
||
```js | ||
const requireWorker = require('require-worker'); | ||
``` | ||
|
||
# requireWorker methods | ||
|
||
## requireWorker.require() | ||
Usage: `requireWorker.require(path,[options])` | ||
|
||
Creates a require-worker client. | ||
|
||
```js | ||
const aModule = requireWorker.require("path/to/module"); | ||
``` | ||
|
||
The return value of this method is a [JavaScript Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) which is configured to interact with properties on the module's exports object. See the client proxy interface API docs below. | ||
|
||
### paramater: `path` | ||
|
||
The path to the module that will be required within the forked process. | ||
|
||
`require.resolve()` is automatically called on the path. If the path is relative to the current script which is calling `requireWorker.require()`, then the `parentModule` property should be specified as an option, with the value set to the [module variable](https://nodejs.org/api/modules.html#modules_module) which is global, but unique to each script. This can be skipped by calling `require.resolve(path)` before passing it as the paramater. | ||
|
||
### paramater: `options` | ||
|
||
The optional `options` paramater specifies client specific behavior. | ||
|
||
| Property | Description (when `true` or specified) | Default Value | | ||
|-|-|-| | ||
| `ownProcess` | Dedicate a single process for this module. | `false` | | ||
| `shareProcess` | Provide a require-worker client (or client proxy) to share this module within it's host process. | `null` | | ||
| `forkOptions` | The fork options passed directly to `childProcess.fork`. | automatic | | ||
| `parentModule` | The `module` variable for the current script, which the `path` can be relative to the script's directory. | `null` | | ||
| `returnClient` | Have this require method return the client interface. | `false` | | ||
| `returnClientPromise` | Have this require method return the `client.readyPromise` promise, which when resolved, the value is the client interface. | `false` | | ||
| `preConfigureProxy` | Pre configure the proxy interface | `null` | | ||
|
||
When neither `ownProcess` or `shareProcess` is specified, the module will be required within a shared process by other clients which did not specify those options. | ||
|
||
## requireWorker.preConfiguredProxy() | ||
|
||
Usage: `requireWorker.preConfiguredProxy(target,options)` | ||
|
||
An alias for `client.preConfiguredProxy()` (see below), except the `target` paramater can be a client object, a client proxy, or even a proxy call promise. | ||
|
||
## requireWorker() | ||
|
||
Usage: `requireWorker(object)` | ||
|
||
A function that lets you find a require-worker client or host interface. | ||
|
||
The `object` paramater can be a client object, a host object, a host module's `exports` variable, or a resolved module path. | ||
|
||
This method is mainly used within the required module to get the host interface. For example: `const requireWorkerHost = requireWorker(module.exports);` | ||
|
||
# requireWorker client methods | ||
|
||
The require-worker client interface for a module that has been required within a forked process. | ||
|
||
## client.isClientProxy() | ||
|
||
Usage: `client.isClientProxy(object)` | ||
|
||
Check if the given object is a configured proxy for this require-worker client | ||
|
||
## client.setChildReferenced() | ||
|
||
Usage: `client.setChildReferenced(boolean)` | ||
|
||
Specify true or false to set the forked child process as referenced or not. If it's not referenced, it will not keep the NodeJS process open when there is nothing else referenced. | ||
|
||
Each forked child process is referenced by default. | ||
|
||
## client.destroy() | ||
|
||
Usage: `client.destroy()` | ||
|
||
Completly destroy the require-worker client. The client can not be used again without calling the `client.restart()` method. | ||
|
||
The host will also be destroyed. | ||
|
||
## client.restart() | ||
|
||
Usage: `client.restart([options])` | ||
|
||
Attempt to re-construct the client using the existing options passed to the constructor. | ||
|
||
If the `options` paramater is provided, then the given properties will be replaced with the new values. | ||
|
||
The return value will be the `client`, Use `client.readyPromise` to access the client ready promise. Use client.proxy to get the new proxy. | ||
|
||
## client.preConfiguredProxy() | ||
|
||
Usage: `client.preConfiguredProxy(options)` | ||
|
||
Creates a proxy interface where all proxy calls are pre-configured with the given options. | ||
|
||
# requireWorker client properties | ||
|
||
## client.client | ||
|
||
The client object (referencing itself). Handy for object destructuring. | ||
|
||
## client.proxy | ||
|
||
The client proxy object. | ||
|
||
## client.events | ||
|
||
The client event emitter. | ||
|
||
| Event Name | Description | | ||
|-|-| | ||
| `requireSuccess` | Emitted when the module was successfully required. If the event has already been emitted, then all new `requireSuccess` listeners attached to this event will be emitted immediately. | | ||
| `error` | Emitted when a critical error has occurred. | | ||
| `destroy` | Emitted **before** client destruction. | | ||
| `destroyed` | Emitted **after** client destruction. | | ||
| `workerClose` | Emitted when the child process emits the `close` event. | | ||
| `workerDisconnect` | Emitted when the child process emits the `disconnect` event. | | ||
| `workerError` | Emitted when the child process emits the `error` event. | | ||
| `workerExit` | Emitted when the child process emits the `exit` event. | | ||
|
||
After an `error` event is emitted, the client & host will both be destroyed. | ||
|
||
## client.readyPromise | ||
|
||
A promise which resolves when the client has successfully been created and the module has been required. Internally, this is resolved when the `requireSuccess` event is emitted, and rejected when the `error` event is emitted. | ||
|
||
The resolved value is the client object. | ||
|
||
The promise rejects on failure with the error as the value. | ||
|
||
A no-op reject handler is attached when the `returnClientPromise` option is **not** specified. | ||
|
||
# requireWorker host methods | ||
|
||
The require-worker host interface in a forked child process for the module that was required. | ||
|
||
## host.destroy() | ||
|
||
Usage: `host.destroy()` | ||
|
||
Completly destroy the require-worker host. The forked child process that the host resides within, may be forcefully exited if there are no other hosts that are shared within the same process. If other hosts are shared, then the process can remain open, and the required module can still operate, but can no longer communicate to the require-worker client in the other process. | ||
|
||
The client will also be destroyed. | ||
|
||
# requireWorker host properties | ||
|
||
## host.events | ||
|
||
The host event emitter. | ||
|
||
| Event Name | Description | | ||
|-|-| | ||
| `destroy` | Emitted **before** host destruction. | | ||
| `destroyed` | Emitted **after** host destruction. | | ||
|
||
# requireWorker client proxy interface | ||
|
||
A client proxy interface is a [JavaScript Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) which is configured to interact with properties on the module's exports object. | ||
|
||
Every method returns a promise, which either resolves or rejects based on if the method was successfully called, or if the property was successfully `get`, `set` or had other operations done to it. If the property was not found, failed an operation, or errored during a method call, the promise will be rejected. | ||
|
||
## Creating a proxy call | ||
|
||
Usage: `clientProxy.proxyCall(...args)` where `proxyCall` can be any property that may or may not exist on the module's exports object. | ||
|
||
Alternative Usage: `clientProxy['some-method (or property) name'](...args)` | ||
|
||
Proxy calls can be called during and after client initialisation, so you don't need to wait for the `requireSuccess` event or for the `readyPromise` promise to resolve to queue up proxy calls. | ||
|
||
There can be any number of paramaters of almost any type. Each argument is transformed in some way so it can be transferred between the require-worker client & host, then be applied to the module method, or have operations done on the module property. | ||
|
||
The return value for a proxy call, is a promise. | ||
|
||
Make sure to have promise rejection handling, as unhandled promise rejections can cause the process to exit. | ||
|
||
The require-worker client can be accessed via `clientProxy.constructor.client` and `preConfiguredProxy` can also be accessed via `clientProxy.constructor.preConfiguredProxy` | ||
|
||
## Proxy call configurations | ||
|
||
Every proxy call returns a promise, with a `.configure(options)` method available. If the proxy call needs to be configured, the method should be called directly after creating the promise, before anything else is done with the promise. If the configure method is called too late, an error will be thrown. | ||
|
||
The promise resolves with an object containing the results of the proxy call. The `value` property is the result value. The recommended inline way to get this value is via [object destructuring](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment): `clientProxy.proxyCall().then(({ value })=>{ ... })`. This can be overridden via the `returnKey` option. | ||
|
||
When the promise rejects, it is also an object containing the results of the proxy call. | ||
|
||
### paramater: `options` | ||
|
||
The `options` paramater specifies how the proxy call will behave. See below for examples on how these options effect the proxy call's behavior. | ||
|
||
| Property | Description (when `true` or specified) | Default Value | | ||
|-|-|-| | ||
| `deleteProperty` | The `delete` keyword will be called on the property. | - | | ||
| `setProperty` | The property will be set to the given value. If multiple arguments are listed, the property's value will be an array of the given values. | - | | ||
| `hasProperty` | Resolves `true` or `false` if the property exists via the `in` keyword. | - | | ||
| `hasOwnProperty` | Resolves `true` or `false` if the property exists via the `hasOwnProperty` method. | - | | ||
| `resolveError` | The proxy call will never reject. The resolved result will contain an `error` property instead of rejection. | - | | ||
| `returnKey` | Resolve/reject with the specified result property instead of the result object. | - | | ||
| `promiseResult` | Resolve/reject with the target promise value instead of the result object. Same as having `returnKey` as 'promise'. | - | | ||
| `newOperator` | The `new` keyword will be called on the property. If the property is not a method, this will act as the `setProperty` option. This option can also be triggered if the `new` keyword is used on the proxy call. | - | | ||
| `timeout` | The proxy call will reject if the timeout value is reached. | Infinity | | ||
| `promisify` | If `promisify` exists on the `util` module, and if the method has a `promisify` alternative, then that will be called instead of the method. | - | | ||
| `followPromise` | If the method returns a promise, then the proxy call will not resolve until that target promise does. Same with rejection. | - | | ||
| `forceProxy` | *TODO: Work In Progress. Not Yet Implemented.* | Automatic | | ||
| `objectPath` | *TODO: Work In Progress. Not Yet Implemented.* | - | | ||
| `eventEmitter` | *TODO: Work In Progress. Not Yet Implemented.* | - | | ||
| `property` | If the proxy call was initiated via proxy(), then this option can be used to specify what the proxy call `name` / property is. | - | | ||
| `args` | Specifies the arguments when the `property` option is used. | - | | ||
|
||
### Proxy call configure example: | ||
|
||
The following will have the proxy call promise resolve with the value, instead of the result object, due to the `returnKey` configure option being applied on the proxy call. | ||
|
||
```js | ||
clientProxy.proxyCall().configure({ returnKey:'value' }).then((value)=>{ ... }) | ||
``` | ||
|
||
### The `new` keyword: | ||
|
||
The `new` keyword triggers the `newOperator` configure option. This lets you set property values or construct new function objects or classes within the required module. | ||
|
||
### `proxy()`: | ||
|
||
The proxy object itself can be used as a proxy call function. Use the `property` and `args` configure options to specify the property and arguments. The arguments can also be used normally via `proxy(...args)`. | ||
|
||
The following code snippet: | ||
|
||
```js | ||
clientProxy().configure({ property:'greetings', args:['friend'] }).then(({ value })=>{ ... }) | ||
``` | ||
|
||
Is the same as calling: | ||
|
||
```js | ||
clientProxy('friend').configure({ property:'greetings' }).then(({ value })=>{ ... }) | ||
``` | ||
|
||
Which is also the same as calling: | ||
|
||
```js | ||
clientProxy.greetings('friend').then(({ value })=>{ ... }) | ||
``` | ||
|
||
## Working with module properties | ||
|
||
*TODO - Coming Soon.* | ||
|
||
## Working with module methods | ||
|
||
*TODO - Coming Soon.* | ||
|
||
## Working with data types | ||
|
||
*TODO - Coming Soon.* | ||
|
||
# Async-Await | ||
|
||
Since most of the API is promise based, [async await](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) can improve the usability of the API. | ||
|
||
The below example creates the client, then waits for a proxy call. The proxy call internally waits for the client to finish initialising. | ||
|
||
```js | ||
(async ()=>{ | ||
const myModule = require('require-worker').require('myModule'); | ||
var name = (await myModule.getModuleName()).value; | ||
// ... | ||
})(); | ||
``` | ||
|
||
If you only want the proxy call result value, then you can use the proxy call configure option `returnKey` as `'value'`. | ||
|
||
```js | ||
(async ()=>{ | ||
const requireWorker = require('require-worker'); | ||
const myModule = requireWorker.require('myModule'); | ||
var name = await myModule.getModuleName().configure({ returnKey:'value' }); | ||
// ... | ||
})(); | ||
``` | ||
|
||
Or use a preconfigured proxy via `client.preConfiguredProxy()`. | ||
|
||
```js | ||
(async ()=>{ | ||
const requireWorker = require('require-worker'); | ||
const client = requireWorker.require('myModule',{ returnClient:true }); | ||
const myModule = client.preConfiguredProxy({ returnKey:'value' }); | ||
var name = await myModule.getModuleName(); | ||
// ... | ||
})(); | ||
``` | ||
|
||
Or use a preconfigured proxy with the `preConfigureProxy` client option. | ||
|
||
```js | ||
(async ()=>{ | ||
const requireWorker = require('require-worker'); | ||
const myModule = requireWorker.require('myModule',{ preConfigureProxy:{ returnKey:'value' } }); | ||
var name = await myModule.getModuleName(); | ||
// ... | ||
})(); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters