2025-08-26 17:57:39 +08:00
|
|
|
use crate::common::AnyResult;
|
2025-10-12 17:20:50 +08:00
|
|
|
use crate::streaming::common::MetricsEventType;
|
2025-08-26 17:57:39 +08:00
|
|
|
use crate::streaming::event_parser::common::filter::EventTypeFilter;
|
|
|
|
|
use crate::streaming::event_parser::core::account_event_parser::AccountEventParser;
|
|
|
|
|
use crate::streaming::event_parser::core::common_event_parser::CommonEventParser;
|
2025-09-14 01:13:11 +08:00
|
|
|
use crate::streaming::event_parser::core::event_parser::EventParser;
|
2025-10-12 22:00:15 +08:00
|
|
|
use crate::streaming::event_parser::{core::traits::DexEvent, Protocol};
|
2025-10-10 18:19:44 +08:00
|
|
|
use crate::streaming::grpc::{EventPretty, MetricsManager};
|
2025-08-26 17:57:39 +08:00
|
|
|
use crate::streaming::shred::TransactionWithSlot;
|
2025-10-12 17:20:50 +08:00
|
|
|
use solana_sdk::pubkey::Pubkey;
|
|
|
|
|
use std::sync::Arc;
|
2025-09-19 23:17:50 +08:00
|
|
|
|
2025-10-12 17:20:50 +08:00
|
|
|
/// 创建带 metrics 统计的 callback 包装器
|
|
|
|
|
///
|
|
|
|
|
/// 用于 Transaction 事件处理,在调用原始 callback 的同时更新 metrics
|
|
|
|
|
#[inline]
|
|
|
|
|
fn create_metrics_callback(
|
2025-10-12 22:00:15 +08:00
|
|
|
callback: Arc<dyn Fn(DexEvent) + Send + Sync>,
|
|
|
|
|
) -> Arc<dyn Fn(DexEvent) + Send + Sync> {
|
|
|
|
|
Arc::new(move |event: DexEvent| {
|
2025-11-10 23:03:54 +08:00
|
|
|
let metadata = event.metadata();
|
|
|
|
|
let processing_time_us = metadata.handle_us as f64;
|
|
|
|
|
let recv_us = metadata.recv_us;
|
|
|
|
|
let block_time_ms = metadata.block_time_ms;
|
|
|
|
|
|
2025-10-12 17:20:50 +08:00
|
|
|
callback(event);
|
2025-11-10 23:03:54 +08:00
|
|
|
|
|
|
|
|
update_metrics_with_latency(
|
2025-10-12 17:20:50 +08:00
|
|
|
MetricsEventType::Transaction,
|
|
|
|
|
1,
|
|
|
|
|
processing_time_us,
|
2025-11-10 23:03:54 +08:00
|
|
|
recv_us,
|
|
|
|
|
block_time_ms,
|
2025-10-12 17:20:50 +08:00
|
|
|
);
|
|
|
|
|
})
|
2025-08-26 17:57:39 +08:00
|
|
|
}
|
|
|
|
|
|
2025-10-12 17:20:50 +08:00
|
|
|
/// Process GRPC transaction events
|
|
|
|
|
pub async fn process_grpc_transaction(
|
|
|
|
|
event_pretty: EventPretty,
|
|
|
|
|
protocols: &[Protocol],
|
|
|
|
|
event_type_filter: Option<&EventTypeFilter>,
|
2025-10-12 22:00:15 +08:00
|
|
|
callback: Arc<dyn Fn(DexEvent) + Send + Sync>,
|
2025-10-12 17:20:50 +08:00
|
|
|
bot_wallet: Option<Pubkey>,
|
|
|
|
|
) -> AnyResult<()> {
|
|
|
|
|
match event_pretty {
|
|
|
|
|
EventPretty::Account(account_pretty) => {
|
|
|
|
|
MetricsManager::global().add_account_process_count();
|
|
|
|
|
|
|
|
|
|
let account_event = AccountEventParser::parse_account_event(
|
|
|
|
|
protocols,
|
|
|
|
|
account_pretty,
|
|
|
|
|
event_type_filter,
|
|
|
|
|
);
|
2025-08-26 17:57:39 +08:00
|
|
|
|
2025-10-12 17:20:50 +08:00
|
|
|
if let Some(event) = account_event {
|
|
|
|
|
let processing_time_us = event.metadata().handle_us as f64;
|
|
|
|
|
callback(event);
|
|
|
|
|
update_metrics(MetricsEventType::Account, 1, processing_time_us);
|
2025-08-26 17:57:39 +08:00
|
|
|
}
|
|
|
|
|
}
|
2025-10-12 17:20:50 +08:00
|
|
|
EventPretty::Transaction(transaction_pretty) => {
|
|
|
|
|
MetricsManager::global().add_tx_process_count();
|
|
|
|
|
|
|
|
|
|
let slot = transaction_pretty.slot;
|
|
|
|
|
let signature = transaction_pretty.signature;
|
|
|
|
|
let block_time = transaction_pretty.block_time;
|
|
|
|
|
let recv_us = transaction_pretty.recv_us;
|
2026-03-07 12:35:57 +08:00
|
|
|
let tx_index = transaction_pretty.tx_index;
|
2025-10-12 17:20:50 +08:00
|
|
|
let grpc_tx = transaction_pretty.grpc_tx;
|
|
|
|
|
|
|
|
|
|
let adapter_callback = create_metrics_callback(callback.clone());
|
|
|
|
|
|
2025-11-04 22:49:40 +08:00
|
|
|
EventParser::parse_grpc_transaction(
|
2025-10-12 17:20:50 +08:00
|
|
|
protocols,
|
|
|
|
|
event_type_filter,
|
|
|
|
|
grpc_tx,
|
2025-08-26 17:57:39 +08:00
|
|
|
signature,
|
|
|
|
|
Some(slot),
|
2025-10-12 17:20:50 +08:00
|
|
|
block_time,
|
2025-09-03 15:49:50 +08:00
|
|
|
recv_us,
|
2025-08-26 17:57:39 +08:00
|
|
|
bot_wallet,
|
2026-03-07 12:35:57 +08:00
|
|
|
tx_index,
|
2025-08-29 14:59:16 +08:00
|
|
|
adapter_callback,
|
2025-08-26 17:57:39 +08:00
|
|
|
)
|
2025-08-29 14:59:16 +08:00
|
|
|
.await?;
|
2025-10-12 17:20:50 +08:00
|
|
|
}
|
|
|
|
|
EventPretty::BlockMeta(block_meta_pretty) => {
|
|
|
|
|
MetricsManager::global().add_block_meta_process_count();
|
|
|
|
|
|
|
|
|
|
let block_time_ms = block_meta_pretty
|
|
|
|
|
.block_time
|
|
|
|
|
.map(|ts| ts.seconds * 1000 + ts.nanos as i64 / 1_000_000)
|
2026-03-07 06:44:42 +00:00
|
|
|
.unwrap_or_else(|| {
|
|
|
|
|
std::time::SystemTime::now()
|
|
|
|
|
.duration_since(std::time::UNIX_EPOCH)
|
|
|
|
|
.unwrap()
|
|
|
|
|
.as_millis() as i64
|
|
|
|
|
});
|
2025-10-12 17:20:50 +08:00
|
|
|
|
|
|
|
|
let block_meta_event = CommonEventParser::generate_block_meta_event(
|
|
|
|
|
block_meta_pretty.slot,
|
|
|
|
|
block_meta_pretty.block_hash,
|
|
|
|
|
block_time_ms,
|
|
|
|
|
block_meta_pretty.recv_us,
|
|
|
|
|
);
|
2025-08-26 17:57:39 +08:00
|
|
|
|
2025-10-12 17:20:50 +08:00
|
|
|
let processing_time_us = block_meta_event.metadata().handle_us as f64;
|
|
|
|
|
callback(block_meta_event);
|
|
|
|
|
update_metrics(MetricsEventType::BlockMeta, 1, processing_time_us);
|
|
|
|
|
}
|
2025-08-26 17:57:39 +08:00
|
|
|
}
|
2025-08-27 21:31:31 +08:00
|
|
|
|
2025-10-12 17:20:50 +08:00
|
|
|
Ok(())
|
2025-08-26 17:57:39 +08:00
|
|
|
}
|
|
|
|
|
|
2025-10-12 17:20:50 +08:00
|
|
|
/// Process Shred transaction events
|
|
|
|
|
pub async fn process_shred_transaction(
|
|
|
|
|
transaction_with_slot: TransactionWithSlot,
|
|
|
|
|
protocols: &[Protocol],
|
|
|
|
|
event_type_filter: Option<&EventTypeFilter>,
|
2025-10-12 22:00:15 +08:00
|
|
|
callback: Arc<dyn Fn(DexEvent) + Send + Sync>,
|
2025-10-12 17:20:50 +08:00
|
|
|
bot_wallet: Option<Pubkey>,
|
|
|
|
|
) -> AnyResult<()> {
|
|
|
|
|
MetricsManager::global().add_tx_process_count();
|
|
|
|
|
|
|
|
|
|
let tx = transaction_with_slot.transaction;
|
|
|
|
|
let slot = transaction_with_slot.slot;
|
2026-03-07 12:35:57 +08:00
|
|
|
let tx_index = transaction_with_slot.tx_index;
|
2025-10-12 17:20:50 +08:00
|
|
|
|
|
|
|
|
if tx.signatures.is_empty() {
|
|
|
|
|
return Ok(());
|
2025-08-26 17:57:39 +08:00
|
|
|
}
|
2025-10-12 17:20:50 +08:00
|
|
|
|
|
|
|
|
let signature = tx.signatures[0];
|
|
|
|
|
let recv_us = transaction_with_slot.recv_us;
|
|
|
|
|
|
|
|
|
|
let adapter_callback = create_metrics_callback(callback);
|
2026-03-07 12:35:57 +08:00
|
|
|
// Shred 路径仅能拿到 static_account_keys,且无 inner_instructions,解析限制见 docs/SHREDSTREAM_LIMITATIONS.md
|
|
|
|
|
// 若交易使用 ALT,账户可能为 default/错误;无 CPI 合并,timestamp/reserves 等多为 0。
|
2025-11-04 22:49:40 +08:00
|
|
|
let accounts = tx.message.static_account_keys();
|
2025-10-12 17:20:50 +08:00
|
|
|
|
2025-11-04 22:49:40 +08:00
|
|
|
EventParser::parse_instruction_events_from_versioned_transaction(
|
2025-10-12 17:20:50 +08:00
|
|
|
protocols,
|
|
|
|
|
event_type_filter,
|
2025-11-04 22:49:40 +08:00
|
|
|
&tx,
|
2025-10-12 17:20:50 +08:00
|
|
|
signature,
|
|
|
|
|
Some(slot),
|
2026-03-07 12:35:57 +08:00
|
|
|
None, // shred 无 block_time
|
2025-10-12 17:20:50 +08:00
|
|
|
recv_us,
|
2025-11-04 22:49:40 +08:00
|
|
|
accounts,
|
|
|
|
|
&[],
|
2025-10-12 17:20:50 +08:00
|
|
|
bot_wallet,
|
2026-03-07 12:35:57 +08:00
|
|
|
tx_index,
|
2025-10-12 17:20:50 +08:00
|
|
|
adapter_callback,
|
|
|
|
|
)
|
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-10 23:03:54 +08:00
|
|
|
/// Update metrics for event processing (with optional latency check)
|
2025-10-12 17:20:50 +08:00
|
|
|
#[inline]
|
|
|
|
|
fn update_metrics(ty: MetricsEventType, count: u64, time_us: f64) {
|
|
|
|
|
MetricsManager::global().update_metrics(ty, count, time_us);
|
2025-08-26 17:57:39 +08:00
|
|
|
}
|
2025-11-10 23:03:54 +08:00
|
|
|
|
|
|
|
|
/// Update metrics with latency check
|
|
|
|
|
#[inline]
|
|
|
|
|
fn update_metrics_with_latency(
|
|
|
|
|
ty: MetricsEventType,
|
|
|
|
|
count: u64,
|
|
|
|
|
time_us: f64,
|
|
|
|
|
recv_us: i64,
|
|
|
|
|
block_time_ms: i64,
|
|
|
|
|
) {
|
|
|
|
|
MetricsManager::global().update_metrics_with_latency(ty, count, time_us, recv_us, block_time_ms);
|
|
|
|
|
}
|