2024-01-19 00:04:03 -08:00
|
|
|
use log::info;
|
|
|
|
use solana_sdk::clock::Slot;
|
|
|
|
use solana_sdk::commitment_config::CommitmentConfig;
|
|
|
|
use std::env;
|
2024-04-02 05:36:22 -07:00
|
|
|
use tokio::sync::broadcast;
|
2024-01-19 00:04:03 -08:00
|
|
|
|
2024-01-26 10:25:39 -08:00
|
|
|
use geyser_grpc_connector::channel_plugger::spawn_broadcast_channel_plug;
|
|
|
|
use geyser_grpc_connector::grpc_subscription_autoreconnect_tasks::create_geyser_autoconnection_task;
|
|
|
|
use geyser_grpc_connector::grpcmultiplex_fastestwins::FromYellowstoneExtractor;
|
2024-01-22 09:26:26 -08:00
|
|
|
use geyser_grpc_connector::{GeyserFilter, GrpcConnectionTimeouts, GrpcSourceConfig, Message};
|
2024-01-19 00:04:03 -08:00
|
|
|
use tokio::time::{sleep, Duration};
|
|
|
|
use tracing::warn;
|
|
|
|
use yellowstone_grpc_proto::geyser::subscribe_update::UpdateOneof;
|
|
|
|
use yellowstone_grpc_proto::geyser::SubscribeUpdate;
|
|
|
|
use yellowstone_grpc_proto::prost::Message as _;
|
|
|
|
|
|
|
|
pub struct BlockMini {
|
|
|
|
pub blocksize: usize,
|
|
|
|
pub slot: Slot,
|
|
|
|
pub commitment_config: CommitmentConfig,
|
|
|
|
}
|
|
|
|
|
|
|
|
struct BlockMiniExtractor(CommitmentConfig);
|
|
|
|
|
|
|
|
impl FromYellowstoneExtractor for BlockMiniExtractor {
|
|
|
|
type Target = BlockMini;
|
|
|
|
fn map_yellowstone_update(&self, update: SubscribeUpdate) -> Option<(Slot, Self::Target)> {
|
|
|
|
match update.update_oneof {
|
|
|
|
Some(UpdateOneof::Block(update_block_message)) => {
|
|
|
|
let blocksize = update_block_message.encoded_len();
|
|
|
|
let slot = update_block_message.slot;
|
|
|
|
let mini = BlockMini {
|
|
|
|
blocksize,
|
|
|
|
slot,
|
|
|
|
commitment_config: self.0,
|
|
|
|
};
|
|
|
|
Some((slot, mini))
|
|
|
|
}
|
|
|
|
Some(UpdateOneof::BlockMeta(update_blockmeta_message)) => {
|
|
|
|
let blocksize = update_blockmeta_message.encoded_len();
|
|
|
|
let slot = update_blockmeta_message.slot;
|
|
|
|
let mini = BlockMini {
|
|
|
|
blocksize,
|
|
|
|
slot,
|
|
|
|
commitment_config: self.0,
|
|
|
|
};
|
|
|
|
Some((slot, mini))
|
|
|
|
}
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-26 10:25:39 -08:00
|
|
|
#[allow(dead_code)]
|
2024-01-19 00:04:03 -08:00
|
|
|
enum TestCases {
|
|
|
|
Basic,
|
2024-01-19 00:23:55 -08:00
|
|
|
SlowReceiverStartup,
|
|
|
|
TemporaryLaggingReceiver,
|
2024-01-19 00:13:37 -08:00
|
|
|
CloseAfterReceiving,
|
2024-01-19 00:23:55 -08:00
|
|
|
AbortTaskFromOutside,
|
2024-01-19 00:04:03 -08:00
|
|
|
}
|
2024-01-22 01:55:03 -08:00
|
|
|
const TEST_CASE: TestCases = TestCases::Basic;
|
2024-01-19 00:04:03 -08:00
|
|
|
|
|
|
|
#[tokio::main]
|
|
|
|
pub async fn main() {
|
|
|
|
// RUST_LOG=info,stream_blocks_mainnet=debug,geyser_grpc_connector=trace
|
|
|
|
tracing_subscriber::fmt::init();
|
|
|
|
// console_subscriber::init();
|
|
|
|
|
|
|
|
let grpc_addr_green = env::var("GRPC_ADDR").expect("need grpc url for green");
|
|
|
|
let grpc_x_token_green = env::var("GRPC_X_TOKEN").ok();
|
|
|
|
|
|
|
|
info!(
|
|
|
|
"Using grpc source on {} ({})",
|
|
|
|
grpc_addr_green,
|
|
|
|
grpc_x_token_green.is_some()
|
|
|
|
);
|
|
|
|
|
|
|
|
let timeouts = GrpcConnectionTimeouts {
|
|
|
|
connect_timeout: Duration::from_secs(5),
|
|
|
|
request_timeout: Duration::from_secs(5),
|
|
|
|
subscribe_timeout: Duration::from_secs(5),
|
2024-01-26 10:25:39 -08:00
|
|
|
receive_timeout: Duration::from_secs(5),
|
2024-01-19 00:04:03 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
let green_config =
|
|
|
|
GrpcSourceConfig::new(grpc_addr_green, grpc_x_token_green, None, timeouts.clone());
|
|
|
|
|
|
|
|
info!("Write Block stream..");
|
|
|
|
|
2024-04-02 05:36:22 -07:00
|
|
|
let (_, exit_notify) = broadcast::channel(1);
|
2024-03-27 09:47:25 -07:00
|
|
|
|
2024-01-22 01:55:03 -08:00
|
|
|
let (jh_geyser_task, message_channel) = create_geyser_autoconnection_task(
|
2024-01-19 00:04:03 -08:00
|
|
|
green_config.clone(),
|
|
|
|
GeyserFilter(CommitmentConfig::confirmed()).blocks_and_txs(),
|
2024-03-27 09:47:25 -07:00
|
|
|
exit_notify,
|
2024-01-19 00:04:03 -08:00
|
|
|
);
|
2024-01-22 01:55:03 -08:00
|
|
|
let mut message_channel =
|
|
|
|
spawn_broadcast_channel_plug(tokio::sync::broadcast::channel(8), message_channel);
|
2024-01-19 00:04:03 -08:00
|
|
|
|
|
|
|
tokio::spawn(async move {
|
2024-01-19 00:23:55 -08:00
|
|
|
if let TestCases::SlowReceiverStartup = TEST_CASE {
|
2024-01-19 00:04:03 -08:00
|
|
|
sleep(Duration::from_secs(5)).await;
|
|
|
|
}
|
|
|
|
|
2024-01-19 00:23:55 -08:00
|
|
|
let mut message_count = 0;
|
2024-01-19 02:46:19 -08:00
|
|
|
while let Ok(message) = message_channel.recv().await {
|
2024-01-19 00:23:55 -08:00
|
|
|
if let TestCases::AbortTaskFromOutside = TEST_CASE {
|
|
|
|
if message_count > 5 {
|
|
|
|
info!("(testcase) aborting task from outside");
|
|
|
|
jh_geyser_task.abort();
|
|
|
|
}
|
|
|
|
}
|
2024-01-19 00:04:03 -08:00
|
|
|
match message {
|
|
|
|
Message::GeyserSubscribeUpdate(subscriber_update) => {
|
2024-01-19 00:23:55 -08:00
|
|
|
message_count += 1;
|
2024-01-22 01:55:03 -08:00
|
|
|
info!("got update - {} bytes", subscriber_update.encoded_len());
|
2024-01-19 00:13:37 -08:00
|
|
|
|
2024-01-19 00:23:55 -08:00
|
|
|
if let TestCases::CloseAfterReceiving = TEST_CASE {
|
2024-01-19 00:13:37 -08:00
|
|
|
info!("(testcase) closing stream after receiving");
|
|
|
|
return;
|
|
|
|
}
|
2024-01-19 00:04:03 -08:00
|
|
|
}
|
|
|
|
Message::Connecting(attempt) => {
|
|
|
|
warn!("Connection attempt: {}", attempt);
|
|
|
|
}
|
|
|
|
}
|
2024-01-19 00:23:55 -08:00
|
|
|
|
|
|
|
if let TestCases::TemporaryLaggingReceiver = TEST_CASE {
|
|
|
|
if message_count % 3 == 1 {
|
|
|
|
info!("(testcase) lagging a bit");
|
|
|
|
sleep(Duration::from_millis(1500)).await;
|
|
|
|
}
|
|
|
|
}
|
2024-01-19 00:04:03 -08:00
|
|
|
}
|
|
|
|
warn!("Stream aborted");
|
|
|
|
});
|
|
|
|
|
|
|
|
// "infinite" sleep
|
2024-01-22 01:55:03 -08:00
|
|
|
sleep(Duration::from_secs(2000)).await;
|
2024-01-19 00:04:03 -08:00
|
|
|
}
|