You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/recipes/shared-workers.md
+41-41
Original file line number
Diff line number
Diff line change
@@ -1,10 +1,10 @@
1
1
# Extending AVA using shared workers
2
2
3
-
Shared workers are a new, powerful (and experimental) AVA feature. A program can be loaded in a [worker thread](https://nodejs.org/docs/latest/api/worker_threads.html) in AVA's main process and then communicate with code running in the test workers. This enables your tests to better utilize shared resources during a test run, as well as providing opportunities to set up these resources before tests start (or clean them up after).
3
+
Shared workers are a powerful AVA feature. A program can be loaded in a [worker thread](https://nodejs.org/docs/latest/api/worker_threads.html) in AVA's main process and then communicate with code running in the test workers. This enables your tests to better utilize shared resources during a test run, as well as providing opportunities to set up these resources before tests start (or clean them up after).
4
4
5
5
When you use watch mode, shared workers remain loaded across runs.
6
6
7
-
## Enabling the experiment
7
+
## Enabling the experiment (only needed with AVA 3)
8
8
9
9
Shared workers are available when you use AVA with Node.js 12.17.0 or newer. AVA 3.13.0 or newer is required. It is an experimental feature so you need to enable it in your AVA configuration:
10
10
@@ -31,20 +31,20 @@ Here we'll discuss building low-level plugins.
31
31
32
32
### Registering a shared worker
33
33
34
-
Plugins are registered inside test workers. They'll provide the path for the main program, which AVA will load in a [worker thread](https://nodejs.org/docs/latest/api/worker_threads.html) in its main process. For each unique path one worker thread is started.
34
+
Plugins are registered inside test workers. They'll provide the path for the shared worker, which AVA will load in a [worker thread](https://nodejs.org/docs/latest/api/worker_threads.html) in its main process. For each unique path one worker thread is started.
35
35
36
-
Plugins communicate with their main program using a *protocol*. Protocols are versioned independently from AVA itself. This allows us to make improvements without breaking existing plugins. Protocols are only removed in major AVA releases.
36
+
Plugins communicate with their shared worker using a *protocol*. Protocols are versioned independently from AVA itself. This allows us to make improvements without breaking existing plugins. Protocols are only removed in major AVA releases.
37
37
38
38
Plugins can be compatible with multiple protocols. AVA will select the best protocol it supports. If AVA does not support any of the specified protocols it'll throw an error. The selected protocol is available on the returned worker object.
39
39
40
-
**While shared workers are experimental, there is only an unversioned *experimental* protocol. Breaking changes may occur with any AVA release.**
40
+
**For AVA 3, substitute `'ava4'`with `'experimental'`.**
@@ -55,61 +55,61 @@ You can supply a `teardown()` function which will be called after all tests have
55
55
```js
56
56
constworker=registerSharedWorker({
57
57
filename:path.resolve(__dirname, 'worker.js'),
58
-
supportedProtocols: ['experimental'],
58
+
supportedProtocols: ['ava4'],
59
59
teardown () {
60
60
// Perform any clean-up within the test process itself.
61
61
}
62
62
});
63
63
```
64
64
65
-
You can also provide some data passed to the main program when it is loaded. Of course, it is only loaded once, so this is only useful in limited circumstances:
65
+
You can also provide some data passed to the shared worker when it is loaded. Of course, it is only loaded once, so this is only useful in limited circumstances:
66
66
67
67
```js
68
68
constshared=registerSharedWorker({
69
69
filename:path.resolve(__dirname, 'worker.js'),
70
70
initialData: {hello:'world'},
71
-
supportedProtocols: ['experimental']
71
+
supportedProtocols: ['ava4']
72
72
});
73
73
```
74
74
75
-
On this `shared` object, `protocol` is set to the selected protocol. Since the main program is loaded asynchronously, `available` provides a promise that fulfils when the main program first becomes available. `currentlyAvailable` reflects whether the worker is, well, currently available.
75
+
On this `shared` object, `protocol` is set to the selected protocol. Since the shared worker is loaded asynchronously, `available` provides a promise that fulfils when the shared worker first becomes available. `currentlyAvailable` reflects whether the worker is, well, currently available.
76
76
77
77
There are two more methods available on the `shared` object, which we'll get to soon.
78
78
79
-
#### Initializing the main program
79
+
#### Initializing the shared worker
80
80
81
-
AVA loads the main program (as identified through the `filename` option) in a worker thread. The program must export a factory method. For CJS programs this can be done by assigning `module.exports` or `exports.default`. For ESM programs you must use `export default`. If the `filename` to an ESM program is an absolute path it must be specified using the `file:` protocol.
81
+
AVA loads the shared worker (as identified through the `filename` option) in a worker thread. This must be an ES module file with a default export. The filename must be an absolute path using the `file:` protocol or a `URL` instance.
82
82
83
-
Like when calling `registerSharedWorker()`, the factory method must negotiate a protocol:
83
+
The default export must be a factory method. Like when calling `registerSharedWorker()`, it must negotiate a protocol:
84
84
85
85
```js
86
-
exports.default= ({negotiateProtocol}) => {
87
-
constmain=negotiateProtocol(['experimental']);
88
-
};
86
+
exportdefault ({negotiateProtocol}) => {
87
+
constmain=negotiateProtocol(['ava4']);
88
+
}
89
89
```
90
90
91
91
On this `main` object, `protocol` is set to the selected protocol. `initialData` holds the data provided when the worker was first registered.
92
92
93
-
When you're done initializing the main program you must call `main.ready()`. This makes the worker available in test workers. You can call `main.ready()` asynchronously.
93
+
When you're done initializing the shared worker you must call `main.ready()`. This makes the worker available in test workers. You can call `main.ready()` asynchronously.
94
94
95
95
Any errors thrown by the factory method will crash the worker thread and make the worker unavailable in test workers. The same goes for unhandled rejections. The factory method may return a promise.
96
96
97
-
### Communicating between test workers and the worker thread
97
+
### Communicating between test workers and the shared worker
98
98
99
-
AVA's low-level shared worker infrastructure is primarily about communication. You can send messages from test workers to the shared worker thread, and the other way around. Higher-level logic can be implemented on top of this message passing infrastructure.
99
+
AVA's low-level shared worker infrastructure is primarily about communication. You can send messages from test workers to the shared worker, and the other way around. Higher-level logic can be implemented on top of this message passing infrastructure.
100
100
101
101
Message data is serialized using the [V8 Serialization API](https://nodejs.org/docs/latest-v12.x/api/v8.html#v8_serialization_api). Please read up on some [important limitations](https://nodejs.org/docs/latest-v12.x/api/worker_threads.html#worker_threads_port_postmessage_value_transferlist).
102
102
103
-
In the main program you can subscribe to messages from test workers:
103
+
In the shared worker you can subscribe to messages from test workers:
Like with `reply()`, `broadcast()` returns a published message which can receive replies. Call `replies()` to get an asynchronous iterator for reply messages.
@@ -162,13 +162,13 @@ These test workers have a unique ID (which, like message IDs, is unique for the
162
162
Of course you don't need to wait for a message *from* a test worker to access this object. Use `main.testWorkers()` to get an asynchronous iterator which produces each newly connected test worker:
@@ -255,4 +255,4 @@ Not sure what to build? Previously folks have expressed a desire for mutexes, ma
255
255
256
256
We could also extend the shared worker implementation in AVA itself. Perhaps so you can run code before a new test run, even with watch mode. Or so you can initialize a shared worker based on the AVA configuration, not when a test file runs.
257
257
258
-
Please [comment here](https://github.com/avajs/ava/issues/2605) with ideas, questions and feedback.
258
+
Please [comment here](https://github.com/avajs/ava/discussions/2703) with ideas, questions and feedback.
0 commit comments