use tracing::trace;
use tracing::error;
use tracing::debug;
use tracing::warn;
use fluvio_socket::FlvSocketError;
use fluvio_socket::FlvStream;
use fluvio_socket::FlvSocket;
use fluvio_service::api_loop;
use fluvio_types::SpuId;
use crate::core::DefaultSharedGlobalContext;
use super::LeaderReplicaControllerCommand;
use super::FollowerOffsetUpdate;
use super::LeaderPeerApiEnum;
use super::LeaderPeerRequest;
use super::UpdateOffsetRequest;
use super::ReplicaOffsetRequest;
pub struct LeaderConnection {
ctx: DefaultSharedGlobalContext,
follower_id: SpuId,
}
impl LeaderConnection {
pub async fn handle(
ctx: DefaultSharedGlobalContext,
follower_id: SpuId,
socket: FlvSocket,
) -> Result<(), FlvSocketError> {
let (sink, stream) = socket.split();
ctx.follower_sinks().insert_sink(follower_id, sink);
let connection = Self {
ctx: ctx.clone(),
follower_id,
};
connection.main_loop(stream).await?;
ctx.follower_sinks().clear_sink(&follower_id);
Ok(())
}
async fn main_loop(&self, mut stream: FlvStream) -> Result<(), FlvSocketError> {
trace!(
"starting connection handling from follower: {} for leader: {}",
self.follower_id,
self.ctx.local_spu_id()
);
let mut api_stream = stream.api_stream::<LeaderPeerRequest, LeaderPeerApiEnum>();
api_loop!(
api_stream,
LeaderPeerRequest::UpdateOffsets(request) => {
self.route_offset_request(request.request).await
}
);
Ok(())
}
async fn route_offset_request(&self, request: UpdateOffsetRequest) {
debug!("receive offset request from follower: {}", self.follower_id);
for replica in request.replicas {
route_replica_offset(self.ctx.clone(), self.follower_id, replica).await
}
}
}
async fn route_replica_offset(
ctx: DefaultSharedGlobalContext,
follower_id: SpuId,
replica: ReplicaOffsetRequest,
) {
let replica_key = replica.replica;
let follower_update = FollowerOffsetUpdate {
follower_id,
leo: replica.leo,
hw: replica.hw,
};
match ctx
.leaders_state()
.send_message(
&replica_key,
LeaderReplicaControllerCommand::FollowerOffsetUpdate(follower_update),
)
.await
{
Ok(success_stat) => {
if success_stat {
trace!("send offset data to: replica leader: {}", replica_key);
} else {
warn!("replica leader: {} was not found", replica_key); }
}
Err(err) => error!(
"Error writing message to replica {}, err: {}",
replica_key, err
),
}
}