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

Conversation

codetheweb
Copy link
Contributor

Motivation

We'd like to use TypeScript for shared workers.

We're currently using esbuild-register for JIT transpilation for all TS files loaded by Ava, but this doesn't work when loading shared workers. We made a small worker wrapper that allows us to load TS files as workers:
get-typescript-worker.mjs:

import "esbuild-register"
import { createRequire } from "node:module"

const require = createRequire(import.meta.url)

/**
 * This is meant to be loaded as a shared Ava worker, and allows TypeScript files to be loaded as shared workers.
 * The `initialData` payload is expected to contain a full path to the target TypeScript file as `target_worker_path`.
 */
const loadTypeScriptWorker = async ({ negotiateProtocol }) => {
  const protocol = await negotiateProtocol(["ava-4"]).ready()

  const {
    initialData: { target_worker_path },
  } = protocol

  await require(target_worker_path).default(protocol)
}

export default loadTypeScriptWorker

Problem

However, this approach means that the wrapper file is the only file ever registered with registerSharedWorker(). Since workers are currently de-duped based on the source filename, we can only load 1 TS worker in this manner.

Solution

An optional, user-specified key parameter is added to registerSharedWorker() that overrides the implicit filename key for de-duping.

After building this out, I realized that there's a second solution: when calling registerSharedWorker(), you can add a unique hash to the filename that acts as a key:
register-typescript-worker.ts:

const registerTypeScriptWorker = (worker_name: string) => {
  return registerSharedWorker<any>({
    filename: new URL(
      `file:${path.join(
        __dirname,
        "../",
        "workers",
        "get-typescript-worker.mjs"
      )}#${encodeURIComponent(worker_name)}`
    ),
    supportedProtocols: ["ava-4"],
    initialData: {
      target_worker_path: path.join(__dirname, "../", "workers", worker_name),
    },
  })
}

But this feels kinda weird and it would be nice to have an officially supported key parameter.

@novemberborn
Copy link
Member

I chose the filename as the cache key since it's somewhat analogous to module loading: you also get the same module that was loaded previously. Within that context I think adding a hash or search parameter is a fairly decent solution that matches ES modules.

@codetheweb
Copy link
Contributor Author

Makes sense. In that case, can I make a PR to update https://github.com/avajs/ava/blob/ae0042c95d2dbe72b4910931232ea15f6071e04e/docs/recipes/shared-workers.md with an example?

@novemberborn
Copy link
Member

Makes sense. In that case, can I make a PR to update ae0042c/docs/recipes/shared-workers.md with an example?

Yea that'd be great!

codetheweb added a commit to codetheweb/ava that referenced this pull request Apr 11, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants