nodeca / tabex

Cross-tab message bus for browsers.
http://nodeca.github.io/tabex/
MIT License
219 stars 19 forks source link

How to determine current tab is only tab on startup? #12

Closed damonmaria closed 7 years ago

damonmaria commented 7 years ago

Apologies for the question in 'issues'.

How do I determine that the current tab is the only tab for this origin? I know I could ping and pong messages as per the example site but how long should I wait for a pong message to return as I expect this timeout will change depending on the underlying mechanism used. Alternatively is there some internal mechanism I could rely on that is fired once everything is 'setup' as I presume this must be being figured out internally, and that an internal list of other tabs is kept.

My use case is that I'm saving pending updates to sync to the server in localforage (backed by IndexedDB). Once they're synced I remove them. So when a page loads (it's a single page application) I want to send any pending updates because the previous session couldn't send them. But, if multiple tabs are open then I only want one tab to do this, rather than all tabs read the same entries and duplicate everything (like when the browser restores and multiple tabs all open at once).

puzrin commented 7 years ago

There are no corrects ways to count outer clients with guarantees. That conflicts with general approach.

I think your problem should be solved via locks. Acquire lock, check that you still have data to sync, sync data and release lock. Tabex has locks support, not very good, but should be enougth for your case.

damonmaria commented 7 years ago

Thanks for the suggestion. But a lock means one tab is the only one performing an action whereas I want this 'locked' for the lifetime of the tab so a new tab opened won't also start syncing, which I don't think the lock mechanism is designed for.

Is there a known time interval I can rely on for messages to be sent to other tabs?

Just looking through the code, another way to possibly achieve the same thing (and some useful functionality in other situations) would be if an event was emitted when the current tab became the master. Then I could perform updates only in the master tab (or as per the note in the README is the concept of master only for certain routers?).

puzrin commented 7 years ago

Another router type (shared worker), can be without master at all. You should not rely on this feature of LS router if you wish to have good design.

Is there a known time interval I can rely on for messages to be sent to other tabs?

There are no known guarantees. On practice even 3s propagation delay between LS sync was registered in IE. I'd recomment to read https://github.com/bemson/subetha-bridge/issues/1, it has a lot of interesting info.

I think 10-30s will be safe assumption for worst case, but keep in mind that on mobile tab can freeze in background.

I want this 'locked' for the lifetime of the tab so a new tab opened won't also start syncing, which I don't think the lock mechanism is designed for.

It's better to design tabs with symmetry in mind. Keep timestamp of last sync in shared storage. Set timer to (sync interval + small random). Then acquire lock in all tabs, only one can win. That will not depend on tab opening.

damonmaria commented 7 years ago

Thanks. That's great advice.

puzrin commented 7 years ago

Also, relax your requirements if possible. I think, nothing bad happens if 2 tabs will sync in parallel in very rare case (when sync with server done properly). Instead of "collision resolution" think about "collision avoidance" and "merge without conflicts".

https://github.com/gritzko/swarm - this may be an interesting reading if you have time.