The cold standby client is overly complicated and potentially buggy when segments are loaded from the primary.
- when the StandbyClientHandler is removed from the pipeline, its EventExecutorGroup is passed to the SegmentLoaderHandler to signal a surrogate of the "channel close" event. It would be more sensible for SegmentLoaderHandler to listen to the proper "channel close" event instead.
- after the SegmentLoaderHandler is added to the pipeline, the "channel active" callback method is called directly using the ChannelHandlerContext of the StandbyClientHandler. It would be better for SegmentLoaderHandler to use a proper initialisation point like, in example, the "handler added" callback method. The SegmentLoaderHandler should also use its own ChannelHandlerContext, instead of owning one from another handler.
- SegmentLoaderHandler saves and uses the ChannelHandlerContext of the StandbyClientHandler. The only purpose for it is to use the EventExecutorGroup of the StandbyClientHandler to issue "write messages" events. The SegmentLoaderHandler should use Netty's event loop to issue I/O operations, and instead use a different thread for business logic - in this case, the synchronization process between primary and standby instances.
- The StandbyClientHandler is registered with its own EventExecutorGroup with four threads. This is overkill, since the synchronization process should run anyway in a separate thread (see below). The StandbyClientHandler should use the default event loop.
- The SegmentLoaderHandler is registered with its own EventExecutorGroup with four threads. This is overkill, since request/response cycle between the standby and the primary instances is synchronous. The SegmentLoaderHandler should instead use the default event loop for I/O events and run another (single) thread to execute the synchronization process.