Kitura/Kitura-WebSocket

Receiving messages out of order / concurrently

Closed this issue · 4 comments

In the code I see that each incoming message received on a socket is dispatched asynchronously to a global, concurrent queue. I believe this will lead to bugs where messages received from the same connection will be processed out of order.

In my application it is important to process messages from a single given client in the order that they were sent on the client. This is hard to gurantee when all callbacks are called on a concurrent queue.

I propose that each websocket connection has a private serial queue in which all delegate callbacks are called on. Then the delegate can be sure it has finished processing a "connected" callback before a "received" callback starts for the same connection.

As the API stands the most straightforward way to make my code correct would be to dispatch all callbacks to a single global serial queue. This would be less efficient than the per-connection queue.

The problem with using a private serial queue is that there is limited number of threads on macOS (64 I believe) and as such there is a limit to the number of serial queues that can be created.

Thus using serial queues for serialization here, will limit the scaleability of Kitura-WebSocket.

I'm about to work on a different solution.

The docs say,

You can create as many serial queues as you need.

I don't think each queue is 1:1 related to a thread. The system just makes sure that a serial queue's tasks are never run on more than one thread at the same time.

The semantics of a serial queue are exactly what is needed here, so I'm afraid that re-implementing those same semantics another way will be less optimized than a serial queue or might not be correct. For example, if we just used a lock then we could have task A executing and then B and C waiting on the lock. Once released it would be random whether B or C executes next. That means we should have a array structure for enqueuing blocks and then protect that array with a lock. At that point we've almost reinvented serial dispatch queues.

This was fixed by #8.