Skip to content

[script-compiler] Mapping sent and received messages and avoiding race conditions #72

Description

@otariidae

I'd like to have a one-to-one correspondence between the text I send to the Textlint worker and the lint result I receive from the Textlint worker.
However, the order I received results from the Textlint worker can differ from the one I posted texts to the worker probably because kernel.lintText is async. Ref:

return kernel.lintText(data.text, {
rules: rules,
filterRules: config.filterRules,
plugins: config.plugins,
filePath: "/path/to/README" + data.ext,
ext: data.ext,
}).then(result => {
return self.postMessage({
command: "lint:result",
result
});
});

So relying on message reception order can cause a race condition. Pseudocode:

worker.addEventListener("message", (event) => {
  // lint result of text#2 comes first
  // lint result of text#1 comes next
})
worker.postMessage({
  command: "lint",
  text: "text#1 very long text that takes a long time to lint",
  ext: ".txt"
})
worker.postMessage({
  command: "lint",
  text: "text#2 short text; lint finishes quickly",
  ext: ".txt"
})

More higher-level example:

const lintText: LintEngineAPI["lintText"] = async ({ text }: { text: string }): Promise<TextlintResult[]> => {
updateStatus("linting...");
return new Promise((resolve, _reject) => {
worker.addEventListener(
"message",
function (event) {
const data: TextlintWorkerCommandResponse = event.data;
if (data.command === "lint:result") {
resolve([data.result]);
}
updateStatus("linted");
},
{
once: true
}
);
return worker.postMessage({
command: "lint",
text,
ext: ext
} as TextlintWorkerCommandLint);
});
};

const texts = ["text#1 very long text that takes a long time to lint", "text#2 short text; lint finishes quickly"]
const results = await Promise.all(texts => lintText({ text }))
// [<lint result of text#2>, <lint result of text#2>]
// lint result of text#1 goes away

Some Web Worker libraries use IDs in messages. I think it can be one of the ideas to solve this problem.
For example, comlink:

https://github.com/GoogleChromeLabs/comlink/blob/dffe9050f63b1b39f30213adeb1dd4b9ed7d2594/src/comlink.ts#L596-L615

For another example, minlink:

https://github.com/mizchi/minlink/blob/98f0eed1b1fc00a51709e07c6fe3e18232cdfaad/src/shared.ts#L52-L61

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions