Access a shared worker from a dedicated worker - javascript

Is it possible to access a shared worker created in the main thread in a dedicated worker created by that same main thread? My initial thoughts are no as this could cause a lot of concurrency issues, but I don't have a full understanding of the internals of WebWorkers yet to decide definitively.
My use case would be to have a dedicated worker open up a web socket channel with the server to retrieve a streaming data source. This data would then be sent into a shared worker that will provide functions to manipulate it and return results via transferable objects. I do not want to combine these objects into a single worker since I want to be able to plug in different modules for doing the data manipulation, and do not want to have to duplicate the code to talk with the web socket.

Is it possible to access a shared worker created in the main thread in a dedicated worker created by that same main thread?
Yes. Just create a SharedWorker as a sub-worker (and it will be shared), or create a MessageChannel between the shared and the dedicated worker.
this could cause a lot of concurrency issues
No. Inter-Worker communication is evented and asynchronous.
This data would then be sent into a shared worker that will provide functions to manipulate
That doesn't sound as if you needed a shared worker for that. For "providing functions", a simple library that is loaded into the dedicated worker (which does the websocket communication) will suffice. You might even load libraries dynamically, using some kine of dependency management in the worker. There's no need to duplicate the web socket code.

Related

How to separate caches on different pages / for different service workers?

I have two separate applications under the same origin but on different pages (say origin/a/ and origin/b/). Each page registers a service worker, which operates under its own scope. Whilst service workers are restricted to the pages they are registered on, they share the same caches from the origin. And if I want each service worker to clean up its old caches, it turns out it wipes out also the caches created by another service worker.
I ended up defining a scope const in service workers and manually checking if the cache name starts with it. However, this seems a bit fragile since one could rename this scope, and the cache will get lost. Another approach of using self.registration.scope as a cache name part looks better but also cannot guarantee consistent behaviour for nested pages that could contain yet another service worker.
Is there any consistent way to bind a cache to a service worker that I am missing?

How to share WebAssemly module between UI thread and service worker?

My web app is using a web assembly module for some non trivial operations. It has a service worker set up to handle push notifications. Both the main thread and the push notification handler need access to the web assembly module.
Is there a recommended approach to sharing the wasm module?
My first thought was to put it in the service worker and have the main thread call the worker, but then it might become idled and the worker would need to load and initialize the wasm module again which takes about 800ms. I could also use a shared worker, but I don't believe the service worker can spawn a shared worker, so the solution wouldn't work if the main thread is closed.
Is there a canonical way of doing this?

Working of Web Worker

I was reading about web workers, and I understood that it runs on a separate thread. One doubt I have is, whether the web worker spawns a new thread for every request sent to it. Example, if I have 2 js files wherein I share a webworker between two. Now when I postmessage from both files to web worker, will two threads be created or a single one ?
No, each Worker is a single thread, and they still use the same event loop mechanism as the main execution context; meaning, for example, if your Worker runs into an infinite loop, it will lock up completely and not react to any further messages.

Long-running process inside a Service Worker (or something similar)

I have a client-side JS app that uses IndexedDB to store its state. Works fine. However, it's kind of slow because I am frequently reading from and writing to IndexedDB so that the state does not become inconsistent when multiple tabs are open.
My idea was... put all DB access stuff inside a Service Worker, and then I can cache values there in memory without worrying that another tab might have altered the database.
That seems to work fine, except some parts of my application take a long time to run. I can communicate the status (like "X% done") from the Service Worker to my UI. But both Firefox and Chrome seem to kill the worker if it runs for more than 30 seconds, which is way too short for me.
Is there any way around this limitation? If not, any ideas for achieving something similar? A Shared Worker could do it I think, except browser support is poor and I don't anticipate that improving now with the momentum behind Service Workers.
The Google documentation on service workers tells us that using service workers as a memory cache is impossible:
It's terminated when not in use, and restarted when it's next needed, so you cannot rely on global state within a service worker's onfetch and onmessage handlers. If there is information that you need to persist and reuse across restarts, service workers do have access to the IndexedDB API.
My suggestion is to keep using service workers to persist data to the database, and use localStorage to create a shared cache between pages. The tab that is making the change is then responsible for both updating the cache in localStorage and persisting to IndexedDB through the service worker.
I ended up using a Shared Worker. In browsers that don't support Shared Workers, such as Edge and Safari, I fall back to a Web Worker and some hacky code to only let you open the app in one tab at a time.
Since 90% of my users are on Firefox or Chrome anyway, I figure it's not a huge loss.
I also wrote a library to (amongst other things) normalize the APIs used in Shared Workers and Web Workers, so I have the exact same code running in both scenarios, the only difference is whether the worker is initialized with Worker or SharedWorker.
As you said yourself SharedWorkers seems to be exactly what you need.
I'm not sure why you think the momentum behind implementing ServiceWorkers prevent browsers from supporting SharedWorkers. They seem to be two different kind of beasts.
As far as I understand ServiceWorkers should be used as a proxy for your requests when your application is offline and heavy stuff should be done in WebWorkers and SharedWorkers
https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API
https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker

Node.js HTTP-proxy architecture: downloading big amount of data for client

I need: Write a proxy server which will download music for my client. Suppose each client wants to download 20-200 compositions (400MB-4GB of music) and I must support many users simultaneously.
Problem: I heard very different reasonings on how should I write that server: in the main event loop or open new worker for each user.
My process:
User asks server to download data
Server download data and pass streaming them to the client at once
Question: one thread or many workers for my needs? Why?
Assume that several workers anyway, because it will often need to open tcp connections (blocking main thread) and your callbacks will wait for the main thread queue.
Does your HTTP server has many workers? For my opinion, good decision is to make several workers binding to your HTTP port, and each one is a proxy.
If your app is already clusterized, maby it's justified to use MQ + proxy cluster.

Categories

Resources