Accountsdb plugin transaction part 3: Transaction Notifier (#21374)
The TransactionNotifierInterface interface for notifying transactions. Changes to transaction_status_service to notify the notifier of the transaction data. Interface to query the plugin's interest in transaction data
This commit is contained in:
@ -54,9 +54,19 @@ impl AccountsDbPluginManager {
|
||||
}
|
||||
|
||||
/// Check if there is any plugin interested in account data
|
||||
pub fn to_notify_account_data(&self) -> bool {
|
||||
pub fn account_data_notifications_enabled(&self) -> bool {
|
||||
for plugin in &self.plugins {
|
||||
if plugin.to_notify_account_data() {
|
||||
if plugin.account_data_notifications_enabled() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Check if there is any plugin interested in transaction data
|
||||
pub fn transaction_notifications_enabled(&self) -> bool {
|
||||
for plugin in &self.plugins {
|
||||
if plugin.transaction_notifications_enabled() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -3,11 +3,15 @@ use {
|
||||
accounts_update_notifier::AccountsUpdateNotifierImpl,
|
||||
accountsdb_plugin_manager::AccountsDbPluginManager,
|
||||
slot_status_notifier::SlotStatusNotifierImpl, slot_status_observer::SlotStatusObserver,
|
||||
transaction_notifier::TransactionNotifierImpl,
|
||||
},
|
||||
crossbeam_channel::Receiver,
|
||||
log::*,
|
||||
serde_json,
|
||||
solana_rpc::optimistically_confirmed_bank_tracker::BankNotification,
|
||||
solana_rpc::{
|
||||
optimistically_confirmed_bank_tracker::BankNotification,
|
||||
transaction_notifier_interface::TransactionNotifierLock,
|
||||
},
|
||||
solana_runtime::accounts_update_notifier_interface::AccountsUpdateNotifier,
|
||||
std::{
|
||||
fs::File,
|
||||
@ -45,6 +49,7 @@ pub struct AccountsDbPluginService {
|
||||
slot_status_observer: Option<SlotStatusObserver>,
|
||||
plugin_manager: Arc<RwLock<AccountsDbPluginManager>>,
|
||||
accounts_update_notifier: Option<AccountsUpdateNotifier>,
|
||||
transaction_notifier: Option<TransactionNotifierLock>,
|
||||
}
|
||||
|
||||
impl AccountsDbPluginService {
|
||||
@ -74,33 +79,47 @@ impl AccountsDbPluginService {
|
||||
for accountsdb_plugin_config_file in accountsdb_plugin_config_files {
|
||||
Self::load_plugin(&mut plugin_manager, accountsdb_plugin_config_file)?;
|
||||
}
|
||||
let to_notify_account_data = plugin_manager.to_notify_account_data();
|
||||
let account_data_notifications_enabled =
|
||||
plugin_manager.account_data_notifications_enabled();
|
||||
let transaction_notifications_enabled = plugin_manager.transaction_notifications_enabled();
|
||||
|
||||
let plugin_manager = Arc::new(RwLock::new(plugin_manager));
|
||||
|
||||
let accounts_update_notifier: Option<AccountsUpdateNotifier> = if to_notify_account_data {
|
||||
let accounts_update_notifier = AccountsUpdateNotifierImpl::new(plugin_manager.clone());
|
||||
Some(Arc::new(RwLock::new(accounts_update_notifier)))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let accounts_update_notifier: Option<AccountsUpdateNotifier> =
|
||||
if account_data_notifications_enabled {
|
||||
let accounts_update_notifier =
|
||||
AccountsUpdateNotifierImpl::new(plugin_manager.clone());
|
||||
Some(Arc::new(RwLock::new(accounts_update_notifier)))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let slot_status_observer = if to_notify_account_data {
|
||||
let slot_status_notifier = SlotStatusNotifierImpl::new(plugin_manager.clone());
|
||||
let slot_status_notifier = Arc::new(RwLock::new(slot_status_notifier));
|
||||
Some(SlotStatusObserver::new(
|
||||
confirmed_bank_receiver,
|
||||
slot_status_notifier,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let transaction_notifier: Option<TransactionNotifierLock> =
|
||||
if transaction_notifications_enabled {
|
||||
let transaction_notifier = TransactionNotifierImpl::new(plugin_manager.clone());
|
||||
Some(Arc::new(RwLock::new(transaction_notifier)))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let slot_status_observer =
|
||||
if account_data_notifications_enabled || transaction_notifications_enabled {
|
||||
let slot_status_notifier = SlotStatusNotifierImpl::new(plugin_manager.clone());
|
||||
let slot_status_notifier = Arc::new(RwLock::new(slot_status_notifier));
|
||||
Some(SlotStatusObserver::new(
|
||||
confirmed_bank_receiver,
|
||||
slot_status_notifier,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
info!("Started AccountsDbPluginService");
|
||||
Ok(AccountsDbPluginService {
|
||||
slot_status_observer,
|
||||
plugin_manager,
|
||||
accounts_update_notifier,
|
||||
transaction_notifier,
|
||||
})
|
||||
}
|
||||
|
||||
@ -163,6 +182,10 @@ impl AccountsDbPluginService {
|
||||
self.accounts_update_notifier.clone()
|
||||
}
|
||||
|
||||
pub fn get_transaction_notifier(&self) -> Option<TransactionNotifierLock> {
|
||||
self.transaction_notifier.clone()
|
||||
}
|
||||
|
||||
pub fn join(self) -> thread::Result<()> {
|
||||
if let Some(mut slot_status_observer) = self.slot_status_observer {
|
||||
slot_status_observer.join()?;
|
||||
|
@ -3,3 +3,4 @@ pub mod accountsdb_plugin_manager;
|
||||
pub mod accountsdb_plugin_service;
|
||||
pub mod slot_status_notifier;
|
||||
pub mod slot_status_observer;
|
||||
pub mod transaction_notifier;
|
||||
|
93
accountsdb-plugin-manager/src/transaction_notifier.rs
Normal file
93
accountsdb-plugin-manager/src/transaction_notifier.rs
Normal file
@ -0,0 +1,93 @@
|
||||
/// Module responsible for notifying plugins of transactions
|
||||
use {
|
||||
crate::accountsdb_plugin_manager::AccountsDbPluginManager,
|
||||
log::*,
|
||||
solana_accountsdb_plugin_interface::accountsdb_plugin_interface::{
|
||||
ReplicaTransactionInfo, ReplicaTransactionInfoVersions,
|
||||
},
|
||||
solana_measure::measure::Measure,
|
||||
solana_metrics::*,
|
||||
solana_rpc::transaction_notifier_interface::TransactionNotifier,
|
||||
solana_runtime::bank,
|
||||
solana_sdk::{clock::Slot, signature::Signature, transaction::SanitizedTransaction},
|
||||
solana_transaction_status::TransactionStatusMeta,
|
||||
std::sync::{Arc, RwLock},
|
||||
};
|
||||
|
||||
/// This implementation of TransactionNotifier is passed to the rpc's TransactionStatusService
|
||||
/// at the validator startup. TransactionStatusService invokes the notify_transaction method
|
||||
/// for new transactions. The implementation in turn invokes the notify_transaction of each
|
||||
/// plugin enabled with transaction notification managed by the AccountsDbPluginManager.
|
||||
pub(crate) struct TransactionNotifierImpl {
|
||||
plugin_manager: Arc<RwLock<AccountsDbPluginManager>>,
|
||||
}
|
||||
|
||||
impl TransactionNotifier for TransactionNotifierImpl {
|
||||
fn notify_transaction(
|
||||
&self,
|
||||
slot: Slot,
|
||||
signature: &Signature,
|
||||
transaction_status_meta: &TransactionStatusMeta,
|
||||
transaction: &SanitizedTransaction,
|
||||
) {
|
||||
let mut measure = Measure::start("accountsdb-plugin-notify_plugins_of_transaction_info");
|
||||
let transaction_log_info =
|
||||
Self::build_replica_transaction_info(signature, transaction_status_meta, transaction);
|
||||
|
||||
let mut plugin_manager = self.plugin_manager.write().unwrap();
|
||||
|
||||
if plugin_manager.plugins.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
for plugin in plugin_manager.plugins.iter_mut() {
|
||||
if !plugin.transaction_notifications_enabled() {
|
||||
continue;
|
||||
}
|
||||
match plugin.notify_transaction(
|
||||
ReplicaTransactionInfoVersions::V0_0_1(&transaction_log_info),
|
||||
slot,
|
||||
) {
|
||||
Err(err) => {
|
||||
error!(
|
||||
"Failed to notify transaction, error: ({}) to plugin {}",
|
||||
err,
|
||||
plugin.name()
|
||||
)
|
||||
}
|
||||
Ok(_) => {
|
||||
trace!(
|
||||
"Successfully notified transaction to plugin {}",
|
||||
plugin.name()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
measure.stop();
|
||||
inc_new_counter_debug!(
|
||||
"accountsdb-plugin-notify_plugins_of_transaction_info-us",
|
||||
measure.as_us() as usize,
|
||||
10000,
|
||||
10000
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl TransactionNotifierImpl {
|
||||
pub fn new(plugin_manager: Arc<RwLock<AccountsDbPluginManager>>) -> Self {
|
||||
Self { plugin_manager }
|
||||
}
|
||||
|
||||
fn build_replica_transaction_info<'a>(
|
||||
signature: &'a Signature,
|
||||
transaction_status_meta: &'a TransactionStatusMeta,
|
||||
transaction: &'a SanitizedTransaction,
|
||||
) -> ReplicaTransactionInfo<'a> {
|
||||
ReplicaTransactionInfo {
|
||||
signature,
|
||||
is_vote: bank::is_simple_vote_transaction(transaction),
|
||||
transaction,
|
||||
transaction_status_meta,
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user