Andrey Antukh 58178d2383 ♻️ Index websocket connections by profile
The connection registry was a flat map from connection id to
connection data, so finding the connections of one profile meant
walking every connection. `on-connect` and `on-disconnect` also
`swap!`ed a whole-map `assoc`/`dissoc`, which is O(n) per connection
churn.

The registry now holds `:connections` and `:by-profile` in the same
atom, so one `swap!` keeps both consistent and a profile lookup is a
single map access. Both maps are updated together by
`register-connection` / `unregister-connection`; a profile whose last
connection leaves is dropped from the index instead of lingering with
an empty set.

Also extracts `close-file-subscription` out of the
`:unsubscribe-file` handler so a revocation can tear a subscription
down through exactly the same path the client uses: announce
`:leave-file`, close the relay channel, purge the bus. Closing the
channel is what stops the `:subscribe-file` go-loop, since `take!` on
a closed channel returns nil.

Adds `connections-for-profile` and `repl-get-connections-for-profile`
so an operator can inspect a profile's connections from the REPL the
same way as for a file or a team.

The new helpers take no `!` suffix: per `mem:clojure/design-rules` the
default is no `!`, and these are neither `app.db` API nor transient
helpers. Existing `!` names such as `mbus/pub!` are legacy and stay
until their own refactor.

The registry stays local to one backend instance. That is documented
on the var: reaching connections owned by another instance has to go
through the message bus, which is what the revocation watcher will do.

Closes #12155

AI-assisted-by: space-bunny-free
2026-10-08 13:08:50 +02:00
..
2026-10-08 13:08:50 +02:00
2026-10-08 13:08:50 +02:00
2026-09-29 09:07:34 +02:00
2026-10-06 15:12:15 +02:00
2026-10-06 15:12:15 +02:00
2024-05-29 19:05:04 +02:00