2025-07-19 23:46:42 +08:00
|
|
|
use solana_sdk::pubkey::Pubkey;
|
|
|
|
|
|
2025-08-18 01:08:12 +08:00
|
|
|
use crate::common::AnyResult;
|
|
|
|
|
use crate::streaming::common::EventBatchProcessor;
|
|
|
|
|
use crate::streaming::event_parser::common::filter::EventTypeFilter;
|
|
|
|
|
use crate::streaming::event_parser::{Protocol, UnifiedEvent};
|
|
|
|
|
use crate::streaming::shred::{ShredEventProcessor, ShredStreamHandler, TransactionWithSlot};
|
2025-08-11 01:04:16 +08:00
|
|
|
|
2025-08-18 01:08:12 +08:00
|
|
|
use super::ShredStreamGrpc;
|
2025-08-03 05:37:04 +08:00
|
|
|
|
2025-07-19 23:46:42 +08:00
|
|
|
impl ShredStreamGrpc {
|
2025-08-04 21:30:55 +08:00
|
|
|
/// 订阅ShredStream事件(支持批处理和即时处理)
|
2025-07-19 23:46:42 +08:00
|
|
|
pub async fn shredstream_subscribe<F>(
|
|
|
|
|
&self,
|
|
|
|
|
protocols: Vec<Protocol>,
|
|
|
|
|
bot_wallet: Option<Pubkey>,
|
2025-08-18 01:08:12 +08:00
|
|
|
event_type_filter: Option<EventTypeFilter>,
|
2025-07-19 23:46:42 +08:00
|
|
|
callback: F,
|
|
|
|
|
) -> AnyResult<()>
|
|
|
|
|
where
|
|
|
|
|
F: Fn(Box<dyn UnifiedEvent>) + Send + Sync + 'static,
|
|
|
|
|
{
|
2025-08-04 21:30:55 +08:00
|
|
|
// 启动自动性能监控(如果启用)
|
|
|
|
|
if self.config.enable_metrics {
|
2025-08-18 01:08:12 +08:00
|
|
|
self.metrics_manager.start_auto_monitoring().await;
|
2025-08-04 21:30:55 +08:00
|
|
|
}
|
2025-08-11 01:04:16 +08:00
|
|
|
|
2025-08-18 01:08:12 +08:00
|
|
|
// 启动流处理
|
|
|
|
|
let client = (*self.shredstream_client).clone();
|
|
|
|
|
let (_stream_task, rx) = ShredStreamHandler::start_stream_processing(
|
|
|
|
|
client,
|
|
|
|
|
self.config.backpressure.channel_size,
|
|
|
|
|
)
|
|
|
|
|
.await?;
|
2025-08-11 01:04:16 +08:00
|
|
|
|
2025-08-04 21:30:55 +08:00
|
|
|
// 根据配置选择处理模式
|
|
|
|
|
if self.config.batch.enabled {
|
|
|
|
|
// 批处理模式
|
2025-08-18 01:08:12 +08:00
|
|
|
self.process_with_batch(rx, protocols, bot_wallet, event_type_filter, callback).await
|
2025-08-04 21:30:55 +08:00
|
|
|
} else {
|
|
|
|
|
// 即时处理模式
|
2025-08-18 01:08:12 +08:00
|
|
|
self.process_immediate(rx, protocols, bot_wallet, event_type_filter, callback).await
|
2025-08-04 21:30:55 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// 批处理模式
|
|
|
|
|
async fn process_with_batch<F>(
|
|
|
|
|
&self,
|
2025-08-18 01:08:12 +08:00
|
|
|
mut rx: futures::channel::mpsc::Receiver<TransactionWithSlot>,
|
2025-08-04 21:30:55 +08:00
|
|
|
protocols: Vec<Protocol>,
|
|
|
|
|
bot_wallet: Option<Pubkey>,
|
2025-08-18 01:08:12 +08:00
|
|
|
event_type_filter: Option<EventTypeFilter>,
|
2025-08-04 21:30:55 +08:00
|
|
|
callback: F,
|
|
|
|
|
) -> AnyResult<()>
|
|
|
|
|
where
|
|
|
|
|
F: Fn(Box<dyn UnifiedEvent>) + Send + Sync + 'static,
|
|
|
|
|
{
|
2025-08-18 01:08:12 +08:00
|
|
|
use futures::StreamExt;
|
|
|
|
|
|
2025-08-03 05:37:04 +08:00
|
|
|
// 创建批处理器,将单个事件回调转换为批量回调
|
|
|
|
|
let batch_callback = move |events: Vec<Box<dyn UnifiedEvent>>| {
|
|
|
|
|
for event in events {
|
|
|
|
|
callback(event);
|
|
|
|
|
}
|
|
|
|
|
};
|
2025-08-11 01:04:16 +08:00
|
|
|
|
2025-08-18 01:08:12 +08:00
|
|
|
let mut batch_processor = EventBatchProcessor::new(
|
2025-08-11 01:04:16 +08:00
|
|
|
batch_callback,
|
|
|
|
|
self.config.batch.batch_size,
|
|
|
|
|
self.config.batch.batch_timeout_ms,
|
2025-08-04 21:30:55 +08:00
|
|
|
);
|
2025-08-11 01:04:16 +08:00
|
|
|
|
2025-08-18 01:08:12 +08:00
|
|
|
// 创建事件处理器
|
|
|
|
|
let event_processor =
|
|
|
|
|
ShredEventProcessor::new(self.metrics_manager.clone(), self.config.clone());
|
2025-07-19 23:46:42 +08:00
|
|
|
|
|
|
|
|
while let Some(transaction_with_slot) = rx.next().await {
|
2025-08-18 01:08:12 +08:00
|
|
|
if let Err(e) = event_processor
|
2025-08-11 01:04:16 +08:00
|
|
|
.process_transaction_with_batch(
|
|
|
|
|
transaction_with_slot,
|
|
|
|
|
protocols.clone(),
|
|
|
|
|
bot_wallet,
|
|
|
|
|
&mut batch_processor,
|
2025-08-18 01:08:12 +08:00
|
|
|
event_type_filter.clone(),
|
2025-08-11 01:04:16 +08:00
|
|
|
)
|
|
|
|
|
.await
|
2025-07-19 23:46:42 +08:00
|
|
|
{
|
2025-08-18 01:08:12 +08:00
|
|
|
log::error!("Error processing transaction: {e:?}");
|
2025-07-19 23:46:42 +08:00
|
|
|
}
|
|
|
|
|
}
|
2025-08-11 01:04:16 +08:00
|
|
|
|
2025-08-03 05:37:04 +08:00
|
|
|
// 处理剩余的事件
|
|
|
|
|
batch_processor.flush();
|
2025-07-19 23:46:42 +08:00
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-04 21:30:55 +08:00
|
|
|
/// 即时处理模式
|
|
|
|
|
async fn process_immediate<F>(
|
|
|
|
|
&self,
|
2025-08-18 01:08:12 +08:00
|
|
|
mut rx: futures::channel::mpsc::Receiver<TransactionWithSlot>,
|
2025-08-04 21:30:55 +08:00
|
|
|
protocols: Vec<Protocol>,
|
|
|
|
|
bot_wallet: Option<Pubkey>,
|
2025-08-18 01:08:12 +08:00
|
|
|
event_type_filter: Option<EventTypeFilter>,
|
2025-08-04 21:30:55 +08:00
|
|
|
callback: F,
|
|
|
|
|
) -> AnyResult<()>
|
|
|
|
|
where
|
|
|
|
|
F: Fn(Box<dyn UnifiedEvent>) + Send + Sync + 'static,
|
|
|
|
|
{
|
2025-08-18 01:08:12 +08:00
|
|
|
use futures::StreamExt;
|
|
|
|
|
|
|
|
|
|
// 创建事件处理器
|
|
|
|
|
let event_processor =
|
|
|
|
|
ShredEventProcessor::new(self.metrics_manager.clone(), self.config.clone());
|
2025-08-04 21:30:55 +08:00
|
|
|
|
|
|
|
|
while let Some(transaction_with_slot) = rx.next().await {
|
2025-08-18 01:08:12 +08:00
|
|
|
if let Err(e) = event_processor
|
2025-08-11 01:04:16 +08:00
|
|
|
.process_transaction_immediate(
|
|
|
|
|
transaction_with_slot,
|
|
|
|
|
protocols.clone(),
|
|
|
|
|
bot_wallet,
|
2025-08-18 01:08:12 +08:00
|
|
|
event_type_filter.clone(),
|
2025-08-11 01:04:16 +08:00
|
|
|
&callback,
|
|
|
|
|
)
|
|
|
|
|
.await
|
2025-08-04 21:30:55 +08:00
|
|
|
{
|
2025-08-18 01:08:12 +08:00
|
|
|
log::error!("Error processing transaction: {e:?}");
|
2025-08-04 21:30:55 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
2025-08-11 01:04:16 +08:00
|
|
|
}
|