Add timestamp to pools table

To speed up historical price queries, add timestamp to pools.
This denormalizes the database a bit for improved query performance.
This commit is contained in:
Dagur Valberg Johannsson 2024-10-08 17:21:22 +02:00
parent fdf03bc48c
commit 3abbdbc177
No known key found for this signature in database
GPG key ID: FD701804AEE88107
3 changed files with 50 additions and 17 deletions

View file

@ -29,7 +29,9 @@ pub fn create_table(conn: &Connection) {
utxo TEXT PRIMARY KEY REFERENCES utxo_funding(new_utxo_hash) ON DELETE CASCADE, utxo TEXT PRIMARY KEY REFERENCES utxo_funding(new_utxo_hash) ON DELETE CASCADE,
pool TEXT REFERENCES pool(creation_utxo) ON DELETE CASCADE, pool TEXT REFERENCES pool(creation_utxo) ON DELETE CASCADE,
txid TEXT REFERENCES tx(txid) ON DELETE CASCADE, txid TEXT REFERENCES tx(txid) ON DELETE CASCADE,
tx_pos TEXT NOT NULL tx_pos TEXT NOT NULL,
mtp_timestamp BIGINT,
first_seen_timestamp BIGINT
)", )",
[], [],
) )
@ -83,10 +85,18 @@ fn insert_pool_history_entry(
conn: &Connection, conn: &Connection,
pool: &OutPointHash, pool: &OutPointHash,
cauldron: &ParsedContract, cauldron: &ParsedContract,
mtp_timestamp: Option<u64>,
first_seen_timestamp: Option<u64>,
) -> Result<()> { ) -> Result<()> {
// or replace, as it could have been added in mempool, then block
conn.execute( conn.execute(
"INSERT OR REPLACE INTO pool_history_entry (utxo, pool, txid, tx_pos) VALUES (?, ?, ?, ?)", "INSERT INTO pool_history_entry (utxo, pool, txid, tx_pos, mtp_timestamp, first_seen_timestamp)
VALUES (?, ?, ?, ?, ?, ?)
ON CONFLICT(utxo) DO UPDATE SET
pool = excluded.pool,
txid = excluded.txid,
tx_pos = excluded.tx_pos,
mtp_timestamp = COALESCE(excluded.mtp_timestamp, pool_history_entry.mtp_timestamp),
first_seen_timestamp = COALESCE(excluded.first_seen_timestamp, pool_history_entry.first_seen_timestamp)",
params![ params![
cauldron cauldron
.new_utxo_hash .new_utxo_hash
@ -100,13 +110,20 @@ fn insert_pool_history_entry(
cauldron cauldron
.new_utxo_n .new_utxo_n
.expect("utxo index of new pool history entry"), .expect("utxo index of new pool history entry"),
mtp_timestamp,
first_seen_timestamp,
], ],
) )
.context("inserting pool_history_entry")?; .context("inserting pool_history_entry")?;
Ok(()) Ok(())
} }
pub fn update_pool_history(conn: &Connection, cauldrons: Vec<ParsedContract>) -> Result<()> { pub fn update_pool_history(
conn: &Connection,
cauldrons: Vec<ParsedContract>,
mtp_timestamp: Option<u64>,
first_seen_timestamp: Option<u64>,
) -> Result<()> {
if cauldrons.is_empty() { if cauldrons.is_empty() {
return Ok(()); return Ok(());
} }
@ -158,10 +175,22 @@ pub fn update_pool_history(conn: &Connection, cauldrons: Vec<ParsedContract>) ->
.to_hex() .to_hex()
); );
insert_new_pool(conn, &current)?; insert_new_pool(conn, &current)?;
insert_pool_history_entry(conn, &pool_utxo, &current)?; insert_pool_history_entry(
conn,
&pool_utxo,
&current,
mtp_timestamp,
first_seen_timestamp,
)?;
} else { } else {
debug!("New entry for pool {}", pool_utxo.to_hex()); debug!("New entry for pool {}", pool_utxo.to_hex());
insert_pool_history_entry(conn, &pool_utxo, &current)?; insert_pool_history_entry(
conn,
&pool_utxo,
&current,
mtp_timestamp,
first_seen_timestamp,
)?;
} }
} }

View file

@ -2,7 +2,6 @@
// //
// This software is licensed under the GNU Affero General Public License (AGPL), version 3.0 or later. // This software is licensed under the GNU Affero General Public License (AGPL), version 3.0 or later.
// A copy of the license can be found in the LICENSE file or at https://www.gnu.org/licenses/agpl-3.0.html // A copy of the license can be found in the LICENSE file or at https://www.gnu.org/licenses/agpl-3.0.html
use std::time::{SystemTime, UNIX_EPOCH};
use anyhow::Result; use anyhow::Result;
use bitcoin_hashes::hex::{FromHex, ToHex}; use bitcoin_hashes::hex::{FromHex, ToHex};
@ -35,18 +34,17 @@ pub fn insert_block_tx(
Ok(()) Ok(())
} }
pub fn insert_mempool_tx(conn: &rusqlite::Connection, txid: &Txid) -> Result<()> { pub fn insert_mempool_tx(
conn: &rusqlite::Connection,
txid: &Txid,
first_seen_timestamp: u64,
) -> Result<()> {
let sql = "INSERT INTO tx (txid, first_seen_timestamp) let sql = "INSERT INTO tx (txid, first_seen_timestamp)
VALUES (?1, ?2) VALUES (?1, ?2)
ON CONFLICT(txid) DO UPDATE SET ON CONFLICT(txid) DO UPDATE SET
first_seen_timestamp = excluded.first_seen_timestamp"; first_seen_timestamp = excluded.first_seen_timestamp";
let current_timestamp = SystemTime::now() conn.execute(sql, params![&txid.to_hex(), first_seen_timestamp])?;
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs() as i64;
conn.execute(sql, params![&txid.to_hex(), current_timestamp])?;
Ok(()) Ok(())
} }

View file

@ -6,6 +6,7 @@
use std::{ use std::{
collections::HashSet, collections::HashSet,
sync::{mpsc::sync_channel, Arc, Mutex}, sync::{mpsc::sync_channel, Arc, Mutex},
time::{SystemTime, UNIX_EPOCH},
}; };
use bitcoin_hashes::hex::{FromHex, ToHex}; use bitcoin_hashes::hex::{FromHex, ToHex};
@ -74,10 +75,15 @@ pub fn update_mempool(db: DBPool, electrum: Arc<Mutex<Client>>) -> Result<()> {
db::cauldron::mempool::delete_mempool_tx(&db_tx, txid)?; db::cauldron::mempool::delete_mempool_tx(&db_tx, txid)?;
} }
let current_timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs();
for tx in txs_to_add { for tx in txs_to_add {
let txid = tx.txid(); let txid = tx.txid();
debug!("mempool add {}", txid.to_hex()); debug!("mempool add {}", txid.to_hex());
db::cauldron::tx::insert_mempool_tx(&db_tx, &txid)?; db::cauldron::tx::insert_mempool_tx(&db_tx, &txid, current_timestamp)?;
let cauldrons: Vec<ParsedContract> = tx let cauldrons: Vec<ParsedContract> = tx
.input .input
.iter() .iter()
@ -92,7 +98,7 @@ pub fn update_mempool(db: DBPool, electrum: Arc<Mutex<Client>>) -> Result<()> {
all_cauldrons.extend(cauldrons); all_cauldrons.extend(cauldrons);
} }
db::cauldron::pool::update_pool_history(&db_tx, all_cauldrons) db::cauldron::pool::update_pool_history(&db_tx, all_cauldrons, None, Some(current_timestamp))
.context("update pool history")?; .context("update pool history")?;
Ok(db_tx.commit()?) Ok(db_tx.commit()?)
@ -236,7 +242,7 @@ pub fn index_blocks(
} }
// Figuring out initial utxo needs to be done on all cauldrons in a block. // Figuring out initial utxo needs to be done on all cauldrons in a block.
db::cauldron::pool::update_pool_history(&db_tx, all_cauldrons) db::cauldron::pool::update_pool_history(&db_tx, all_cauldrons, Some(mtp), None)
.context("update pool history")?; .context("update pool history")?;
config_set(&db_tx, KEY_LAST_INDEXED, &blockhash.to_hex()); config_set(&db_tx, KEY_LAST_INDEXED, &blockhash.to_hex());