editor icon indicating copy to clipboard operation
editor copied to clipboard

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

Open otariidae opened this issue 1 year ago • 14 comments

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

otariidae avatar Jun 15 '23 14:06 otariidae