Skip to content

Add key option to registerSharedWorker() #3006

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/fork.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,9 @@ export default function loadFork(file, options, execArgv = process.execArgv) {
send({type: 'options', options});
break;
case 'shared-worker-connect': {
const {channelId, filename, initialData, port} = message.ava;
const {channelId, key, filename, initialData, port} = message.ava;
emitter.emit('connectSharedWorker', {
key,
filename,
initialData,
port,
Expand Down
12 changes: 6 additions & 6 deletions lib/plugin-support/shared-workers.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ const waitForAvailable = async worker => {
}
};

function launchWorker(filename, initialData) {
if (launchedWorkers.has(filename)) {
return launchedWorkers.get(filename);
function launchWorker(key, filename, initialData) {
if (launchedWorkers.has(key)) {
return launchedWorkers.get(key);
}

const worker = new Worker(LOADER, {
Expand All @@ -40,7 +40,7 @@ function launchWorker(filename, initialData) {
worker,
};

launchedWorkers.set(filename, launched);
launchedWorkers.set(key, launched);
worker.once('exit', () => {
launched.exited = true;
});
Expand All @@ -61,8 +61,8 @@ export async function observeWorkerProcess(fork, runStatus) {
}
});

fork.onConnectSharedWorker(async ({filename, initialData, port, signalError}) => {
const launched = launchWorker(filename, initialData);
fork.onConnectSharedWorker(async ({key, filename, initialData, port, signalError}) => {
const launched = launchWorker(key, filename, initialData);

const handleWorkerMessage = async message => {
if (message.type === 'deregistered-test-worker' && message.id === fork.threadId) {
Expand Down
3 changes: 2 additions & 1 deletion lib/worker/channel.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ function createChannelEmitter(channelId) {
return [emitter, () => channelEmitters.delete(channelId)];
}

function registerSharedWorker(filename, initialData) {
function registerSharedWorker(key, filename, initialData) {
const channelId = `${threadId}/channel/${++channelCounter}`;

const {port1: ourPort, port2: theirPort} = new MessageChannel();
Expand All @@ -191,6 +191,7 @@ function registerSharedWorker(filename, initialData) {
handle.send({
type: 'shared-worker-connect',
channelId,
key,
filename,
initialData,
port: theirPort,
Expand Down
12 changes: 7 additions & 5 deletions lib/worker/plugin.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ require('./guard-environment.cjs'); // eslint-disable-line import/no-unassigned-
const workers = new Map();
const workerTeardownFns = new WeakMap();

function createSharedWorker(filename, initialData, teardown) {
const {channel, forceUnref, ready} = register(filename, initialData, teardown);
function createSharedWorker(key, filename, initialData, teardown) {
const {channel, forceUnref, ready} = register(key, filename, initialData, teardown);
waitForReady.push(ready);
sharedWorkerTeardowns.push(async () => {
try {
Expand Down Expand Up @@ -85,6 +85,7 @@ function createSharedWorker(filename, initialData, teardown) {

function registerSharedWorker({
filename,
key,
initialData,
supportedProtocols,
teardown,
Expand All @@ -100,10 +101,11 @@ function registerSharedWorker({
}

filename = String(filename); // Allow URL instances.
key = key ? key : filename; // Fallback to filename for key

let worker = workers.get(filename);
let worker = workers.get(key);
if (worker === undefined) {
worker = createSharedWorker(filename, initialData, async () => {
worker = createSharedWorker(key, filename, initialData, async () => {
// Run possibly asynchronous teardown functions serially, in reverse
// order. Any error will crash the worker.
const teardownFns = workerTeardownFns.get(worker);
Expand All @@ -113,7 +115,7 @@ function registerSharedWorker({
}
}
});
workers.set(filename, worker);
workers.set(key, worker);
}

if (teardown !== undefined) {
Expand Down
1 change: 1 addition & 0 deletions plugin.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export namespace SharedWorker {
export namespace Plugin {
export type RegistrationOptions<Identifier extends ProtocolIdentifier, Data = unknown> = {
readonly filename: string | URL;
readonly key?: string;
readonly initialData?: Data;
readonly supportedProtocols: readonly Identifier[];
readonly teardown?: () => void;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import * as plugin from 'ava/plugin';

export const getWorker = key => {
const worker = plugin.registerSharedWorker({
key,
filename: new URL('_worker.js', import.meta.url),
supportedProtocols: ['ava-4'],
});

const messages = worker.subscribe();

const random = messages.next().then(({value}) => value).finally(() => messages.return());

return {random};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import crypto from 'node:crypto';

export default async ({negotiateProtocol}) => {
const protocol = negotiateProtocol(['ava-4']).ready();

const random = crypto.randomBytes(16).toString('hex');
for await (const testWorker of protocol.testWorkers()) {
testWorker.publish({random});
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"type": "module",
"ava": {
"files": [
"*"
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import test from 'ava';

import {getWorker} from './_plugin.js';

const {random} = getWorker('test-1');

test('the shared worker produces a random value', async t => {
const {data} = await random;
t.log(data);
t.pass();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import test from 'ava';

import {getWorker} from './_plugin.js';

const {random} = getWorker('test-2');

test('the shared worker produces a random value', async t => {
const {data} = await random;
t.log(data);
t.pass();
});
10 changes: 10 additions & 0 deletions test/shared-workers/keyed-workers-are-not-deduped/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import test from '@ava/test';

import {fixture} from '../../helpers/exec.js';

test('keyed workers are not deduped', async t => {
const result = await fixture();
const logs = result.stats.passed.map(object => result.stats.getLogs(object));
t.is(logs.length, 2);
t.notDeepEqual(logs[0], logs[1]);
});