transcend-io / penumbra

Encrypt/decrypt anything in the browser using streams on background threads.
https://penumbra-example.vercel.app/
Apache License 2.0
145 stars 19 forks source link

setWorkerLocation Refreshing Page with Penumbra Error with Workers #231

Closed jonmchan closed 1 year ago

jonmchan commented 2 years ago

I have successfully got files encrypting and decrypting with Penumbra. However, when I refresh the page many times, I occasionally get the following error:

main.penumbra:2 Uncaught TypeError: Cannot set properties of undefined (setting 'busy')
    at main.penumbra:2:217762
    at Function.g (main.penumbra:2:216560)
    at MessagePort.r (main.penumbra:2:35933)

I isolated the error to happening when I call:

penumbra.setWorkerLocation('/worker.penumbra.js');

If I run it several times, I see the following progression in console:

  1. No message
  2. Penumbra Workers are already active. Reinitializing...
  3. Then the error.

If I don't include the setWorkerLocation, I get a 404 error as it tries to reach out to the code at: http://localhost:3000/files/worker.penumbra.js.

I believe this is an issue with the workers not ready or in some sort of already initialized state. Any hints or ideas how to resolve this?

michaelfarrell76 commented 2 years ago

@eligrey any idea?

eligrey commented 2 years ago

It sounds like this line is throwing during worker job dispatch: https://github.com/transcend-io/penumbra/blob/main/src/workers.ts#L183

I would guess that thev workers were somehow not instantiated in time for this error to happen. We'll be looking into this issue soon.

jonmchan commented 2 years ago

Is there any way to check on the worker status? It seems that the exposed functions are very limited. Is there an event that is fired when the workers are ready or something to query the workers? With the compiled code, can I access the worker.ts code from es6 import?

eligrey commented 2 years ago

Note that we currently require that penumbra.setWorkerLocation(...) is the first API call before using our other APIs. Are you calling this API first?

Is there any way to check on the worker status?

Initialization status cannot currently be queried, and should not matter in most use cases as jobs should still be enqueued automatically as workers become available.

With the compiled code, can I access the worker.ts code from es6 import?

Any ES6 platform with Web Workers should be able to use this library or import from src/worker.penumbra.js directly. This library targets browsers and not node platforms.

jonmchan commented 2 years ago

I'm almost certain turbo (https://github.com/hotwired/turbo-rails) is interfering with this and persisting something that is causing this issue. I'll try disabling it and see if it still happens.

michaelfarrell76 commented 2 years ago

@jonmchan any luck?

jonmchan commented 2 years ago

thanks for following up - hadn't had a chance to work on the project I'm using penumbra on lately. I should be getting back to it this week. Should have updates soon.

bencmbrook commented 1 year ago

@jonmchan we'll close this out in the interim, but let us know if you come back to this and we can re-open it

jonmchan commented 1 year ago

So the problem definitely was with the Ruby on Rails framework and the Turbo library that is used to make the webpages feel more responsive by loading partial content and swapping the dom. What effectively ends up happening is the website becomes a single-page site with javascript from all previous pages still in memory. Navigating from page to page, the penumbra library would remain loaded and would go into an error state because penumbra.setWorkerLocation(...) would effectively be called multiple times.

The solution that I used for this was to simply use a global variable to keep track of whether the library was loaded already. The following code was sufficient to stop the error and make penumbra work even while the turbo library was active.

    if (window.penumbraLoaded === undefined) {
      penumbra.setWorkerLocation('/worker.penumbra.js');
      window.penumbraLoaded = true;
    }

Hope this is helpful if anyone decides to utilize Penumbra with RoR and Turbo/Turbolinks.