log_store/kafka/
worker.rs1pub(crate) mod fetch_latest_offset;
16pub(crate) mod flush;
17pub(crate) mod produce;
18
19use std::sync::Arc;
20
21use common_telemetry::debug;
22use dashmap::DashMap;
23use futures::future::try_join_all;
24use rskafka::client::partition::Compression;
25use rskafka::record::Record;
26use snafu::{OptionExt, ResultExt};
27use store_api::logstore::provider::KafkaProvider;
28use tokio::sync::mpsc::Receiver;
29use tokio::sync::oneshot::{self};
30
31use crate::error::{self, NoMaxValueSnafu, Result};
32use crate::kafka::log_store::TopicStat;
33use crate::kafka::producer::ProducerClient;
34
35pub(crate) enum WorkerRequest {
36 Produce(ProduceRequest),
37 FetchLatestOffset,
38}
39
40impl WorkerRequest {
41 pub(crate) fn new_produce_request(batch: Vec<Record>) -> (WorkerRequest, ProduceResultHandle) {
42 let (tx, rx) = oneshot::channel();
43
44 (
45 WorkerRequest::Produce(ProduceRequest { batch, sender: tx }),
46 ProduceResultHandle { receiver: rx },
47 )
48 }
49}
50
51pub(crate) struct ProduceRequest {
52 batch: Vec<Record>,
53 sender: oneshot::Sender<ProduceResultReceiver>,
54}
55
56pub(crate) struct ProduceResultHandle {
59 receiver: oneshot::Receiver<ProduceResultReceiver>,
60}
61
62impl ProduceResultHandle {
63 pub(crate) async fn wait(self) -> Result<u64> {
66 self.receiver
67 .await
68 .context(error::WaitProduceResultReceiverSnafu)?
69 .wait()
70 .await
71 }
72}
73
74#[derive(Default)]
75pub(crate) struct ProduceResultReceiver {
76 receivers: Vec<oneshot::Receiver<Result<Vec<i64>>>>,
77}
78
79impl ProduceResultReceiver {
80 fn add_receiver(&mut self, receiver: oneshot::Receiver<Result<Vec<i64>>>) {
81 self.receivers.push(receiver)
82 }
83
84 async fn wait(self) -> Result<u64> {
85 Ok(try_join_all(self.receivers)
86 .await
87 .into_iter()
88 .flatten()
89 .collect::<Result<Vec<_>>>()?
90 .into_iter()
91 .flatten()
92 .max()
93 .context(NoMaxValueSnafu)? as u64)
94 }
95}
96
97pub(crate) struct PendingRequest {
98 batch: Vec<Record>,
99 size: usize,
100 sender: oneshot::Sender<Result<Vec<i64>>>,
101}
102
103pub(crate) struct BackgroundProducerWorker {
104 pub(crate) provider: Arc<KafkaProvider>,
105 pub(crate) client: Arc<dyn ProducerClient>,
107 pub(crate) compression: Compression,
109 pub(crate) receiver: Receiver<WorkerRequest>,
111 pub(crate) request_batch_size: usize,
113 pub(crate) max_batch_bytes: usize,
115 pub(crate) topic_stats: Arc<DashMap<Arc<KafkaProvider>, TopicStat>>,
117}
118
119impl BackgroundProducerWorker {
120 pub(crate) async fn run(&mut self) {
121 let mut buffer = Vec::with_capacity(self.request_batch_size);
122 loop {
123 match self.receiver.recv().await {
124 Some(req) => {
125 buffer.clear();
126 buffer.push(req);
127 for _ in 1..self.request_batch_size {
128 match self.receiver.try_recv() {
129 Ok(req) => buffer.push(req),
130 Err(_) => break,
131 }
132 }
133 self.handle_requests(&mut buffer).await;
134 }
135 None => {
136 debug!("The sender is dropped, BackgroundProducerWorker exited");
137 break;
139 }
140 }
141 }
142 }
143
144 async fn handle_requests(&mut self, buffer: &mut Vec<WorkerRequest>) {
145 let mut produce_requests = Vec::with_capacity(buffer.len());
146 for req in buffer.drain(..) {
147 match req {
148 WorkerRequest::Produce(req) => produce_requests.push(req),
149 WorkerRequest::FetchLatestOffset => {
150 self.fetch_latest_offset().await;
151 }
152 }
153 }
154
155 let pending_requests = self.aggregate_records(&mut produce_requests, self.max_batch_bytes);
156 self.try_flush_pending_requests(pending_requests).await;
157 }
158}