solana_geyser_plugin_postgres/postgres_client/
postgres_client_block_metadata.rs

1use {
2    crate::{
3        geyser_plugin_postgres::{GeyserPluginPostgresConfig, GeyserPluginPostgresError},
4        postgres_client::{
5            postgres_client_transaction::DbReward, SimplePostgresClient, UpdateBlockMetadataRequest,
6        },
7    },
8    chrono::Utc,
9    log::*,
10    postgres::{Client, Statement},
11    solana_geyser_plugin_interface::geyser_plugin_interface::{
12        GeyserPluginError, ReplicaBlockInfo,
13    },
14};
15
16#[derive(Clone, Debug)]
17pub struct DbBlockInfo {
18    pub slot: i64,
19    pub blockhash: String,
20    pub rewards: Vec<DbReward>,
21    pub block_time: Option<i64>,
22    pub block_height: Option<i64>,
23}
24
25impl<'a> From<&ReplicaBlockInfo<'a>> for DbBlockInfo {
26    fn from(block_info: &ReplicaBlockInfo) -> Self {
27        Self {
28            slot: block_info.slot as i64,
29            blockhash: block_info.blockhash.to_string(),
30            rewards: block_info.rewards.iter().map(DbReward::from).collect(),
31            block_time: block_info.block_time,
32            block_height: block_info
33                .block_height
34                .map(|block_height| block_height as i64),
35        }
36    }
37}
38
39impl SimplePostgresClient {
40    pub(crate) fn build_block_metadata_upsert_statement(
41        client: &mut Client,
42        config: &GeyserPluginPostgresConfig,
43    ) -> Result<Statement, GeyserPluginError> {
44        let stmt =
45            "INSERT INTO block (slot, blockhash, rewards, block_time, block_height, updated_on) \
46        VALUES ($1, $2, $3, $4, $5, $6)";
47
48        let stmt = client.prepare(stmt);
49
50        match stmt {
51            Err(err) => {
52                return Err(GeyserPluginError::Custom(Box::new(GeyserPluginPostgresError::DataSchemaError {
53                    msg: format!(
54                        "Error in preparing for the block metadata update PostgreSQL database: ({}) host: {:?} user: {:?} config: {:?}",
55                        err, config.host, config.user, config
56                    ),
57                })));
58            }
59            Ok(stmt) => Ok(stmt),
60        }
61    }
62
63    pub(crate) fn update_block_metadata_impl(
64        &mut self,
65        block_info: UpdateBlockMetadataRequest,
66    ) -> Result<(), GeyserPluginError> {
67        let client = self.client.get_mut().unwrap();
68        let statement = &client.update_block_metadata_stmt;
69        let client = &mut client.client;
70        let updated_on = Utc::now().naive_utc();
71
72        let block_info = block_info.block_info;
73        let result = client.query(
74            statement,
75            &[
76                &block_info.slot,
77                &block_info.blockhash,
78                &block_info.rewards,
79                &block_info.block_time,
80                &block_info.block_height,
81                &updated_on,
82            ],
83        );
84
85        if let Err(err) = result {
86            let msg = format!(
87                "Failed to persist the update of block metadata to the PostgreSQL database. Error: {:?}",
88                err);
89            error!("{}", msg);
90            return Err(GeyserPluginError::AccountsUpdateError { msg });
91        }
92
93        Ok(())
94    }
95}