Socket.IO is commonly used for real-time, bidirectional and event-based communication. This library played a key role in OpenSooq’s successful Chat service providing tons of leads to our users. In OpenSooq, we have a lot of services managed internally and upgrading outdated technologies can improve business efficiency and help us gain a competitive edge. However, Missing updates can also mean missing out on bug fixes and functionality upgrades. In time, our service might have more compatibility issues due to age. Regular updates will keep all of our services working at its best.
Socket.IO team announced version 2.X that is not backward-compatible, due to:
- a breaking change related to utf-8 encoding in engine.io-parser (socketio/engine.io-parser#81)
- an update to make the socket id on the client match the id on the server-side (socketio/socket.io-client#1058)
In this article we will discuss how OpenSooq managed to maintain various clients with various languages and versions by building repeater. This repeater serves the purpose of passing messages between two different version of Socket IO (1.X and 2.X). Any message received from one of them is automatically passed to all others.
Our Clients for Socket.io v1.x
In the Socket.io v1.x era and before the release of v2.0, this were very easy, just pick the latest version for each platform.
- Web Client: socket.io-client v1.x
- Android app: socket.io-client-java ≤ 0.9
- iOS app: socket.io-client-swift < v10.0.0
The first think one might notice is that socket.io server and its client SDKs do not share same versions and developers should take care of compatibility matrix between the client and server.
Introducing Socket.io v2.x
With the release of socket.io v2.x, breaking changes in the encoding and namespaces were introduced which breaks old unmodified clients from using upgraded servers properly. This might work for those who can upgrade both clients and servers at the same time like when the clients are all web applications (like EtherPad) but it does not work for us and all those who have millions of clients running old apps and they might slow adoption rate for updates.
Split-brain and Useless Workarounds
Although servers are not designed to talk to both old and new clients, some socket.io client libraries claim to support connecting to both old and new servers, which is a very strange and rare scenario that does not even worth supporting.
We have developers, infra team, and load-balancers, and we control DNS, configuration engine and discovery service. We can point old apps to old servers and new apps to new servers. But for a chat message coming from an old app to reach its destination in the hands of a user connected to new server, those servers should be some how connected to each other.
One suggestion was to modify old apps to disable “polling transport” having the encoding problem which is useless workaround because
- If we can modify old apps, then we had better upgrade the io client library (the problem to solve is unmodified old apps)
- This would degrade the reliability (long pulling is not cosmetic)
The Real Solution
An unmodified old client resolves the server domain leading to a socket.io v1.x service, but that service is just a “bridge” interfacing with old v1.x clients from one side passing those events to the real socket.io v2.x upstream
git clone ... cd socketio_repeater npm install SERVER_BASEURL='http://io-v2.internal:3000' LISTEN_PORT=1300 node index.js