editor
editor copied to clipboard
[script-compiler] Mapping sent and received messages and avoiding race conditions
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:
https://github.com/textlint/editor/blob/b32d016d23087d6e7e3ff8de84984a10a90e2815/packages/%40textlint/script-compiler/src/CodeGenerator/worker-codegen.ts#L125-L136
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:
https://github.com/textlint/editor/blob/b32d016d23087d6e7e3ff8de84984a10a90e2815/packages/textchecker-element/index.ts#L41-L63
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