A WebSocket subscriber is only notified if it subscribed through the same hostname that the write came through. When one pod is reachable under two names, such as localhost and a LAN address, a write through one name doesn't notify tabs on the other, even though they're watching the same file.
This looks deliberate rather than a bug, because the hostname is part of a resource's identity and subdomain pods rely on it. This issue records the behaviour and asks whether JSS should change it.
What happens
getRequestPaths in src/handlers/resource.js builds the change URL from the request hostname:
notifySubscribers in src/notifications/websocket.js then looks up that exact string in subscribers. checkSubscriptionAccess also requires the subscribed URL's origin to match the socket's origin, so a client can't subscribe across names.
Test
Version 0.0.225, started with --host 0.0.0.0. One subscriber on each address, then the same file was uploaded once through each with PUT:
Upload through
localhost subscriber
192.168.0.167 subscriber
localhost
Notified
Silent
192.168.0.167
Silent
Notified
We found this when a script uploaded through localhost while browser tabs, including one on another LAN machine, had the map open through the LAN address. The tabs only updated after a refresh.
Behind a proxy this normally doesn't show, because the writer and readers all use the public name. A local writer behind a proxy would hit the same thing.
Other servers
From reading the code, not running it:
Server
Matches on
Write on one name, subscriber on another
Trade-off
JSS
Full URL
Not notified
Writer and readers must share one name
NSS (solid-ws)
Path only (defaultToChannel)
Notified
With subdomain pods, the same path on two pods looks like it would share a channel
CSS
Full URL, one configured base URL
Other hosts get a 500 (E0001), unless fixedBaseUrl is set
One canonical name by configuration
Options
Keep it and document it. Writer and readers use the same address. This needs no code, and it's what we're doing for now.
Match on the storage path. Key subscribers on what getEffectiveUrlPath returns, and send each socket the URL it subscribed with:
Request
Storage path
localhost/public/x
/public/x
192.168.0.167/public/x
/public/x (same file, both notified)
alice.example.com/foo
/alice/foo
bob.example.com/foo
/bob/foo (different file, kept apart)
This hasn't been built or tested. The ancestor-container walk in broadcast and the ACL check on subscribe would need checking against it.
Either way, it would help to mention this in the notifications section of docs/configuration.md, since going from localhost to --host 0.0.0.0 is an easy way to run into it.
Activity