The RelayPool I'm working on is a stripped down pool whose only job is to keep a group of WebSocket connections alive. It does not facilitate messaging. This is the correct abstraction, because you can then pass RelayPool instances into other functions who add the messaging layers on top, allowing you to keep one pool without duplicate connections.
The RelayPool is an EventTarget with "add", "remove", and "reconnect" events, so you can build anything on top of it.
Abstractions, abstractions, abstractions, abstractions!