private LifecycleMessageHandler<ReceivedInstantClusterIdAwareMessage<?>> createMessageHandlerChain( CoreServerModule coreServerModule ) { RaftMessageApplier messageApplier = new RaftMessageApplier( localDatabase, logProvider, consensusModule.raftMachine(), coreServerModule.downloadService(), coreServerModule.commandApplicationProcess(), catchupAddressProvider ); ComposableMessageHandler monitoringHandler = RaftMessageMonitoringHandler.composable( platformModule.clock, platformModule.monitors ); int queueSize = platformModule.config.get( CausalClusteringSettings.raft_in_queue_size ); int maxBatch = platformModule.config.get( CausalClusteringSettings.raft_in_queue_max_batch ); Function<Runnable, ContinuousJob> jobFactory = runnable -> new ContinuousJob( platformModule.jobScheduler.threadFactory( new JobScheduler.Group( "raft-batch-handler" ) ), runnable, logProvider ); ComposableMessageHandler batchingMessageHandler = BatchingMessageHandler.composable( queueSize, maxBatch, jobFactory, logProvider ); ComposableMessageHandler leaderAvailabilityHandler = LeaderAvailabilityHandler.composable( consensusModule.getLeaderAvailabilityTimers(), consensusModule.raftMachine()::term ); ComposableMessageHandler clusterBindingHandler = ClusterBindingHandler.composable( logProvider ); return clusterBindingHandler .compose( leaderAvailabilityHandler ) .compose( batchingMessageHandler ) .compose( monitoringHandler ) .apply( messageApplier ); } }