forked from 0LNetworkCommunity/libra-framework
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
cli entry point to load txs to remote
- Loading branch information
1 parent
fd7a244
commit 65f0b24
Showing
11 changed files
with
311 additions
and
85 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
use crate::{ | ||
extract_transactions::extract_current_transactions, | ||
load_tx_cypher, | ||
scan::{ArchiveMap, ManifestInfo}, | ||
}; | ||
|
||
use anyhow::Result; | ||
use neo4rs::Graph; | ||
|
||
/// takes all the archives from a map, and tries to load them sequentially | ||
pub async fn ingest_all(archive_map: &ArchiveMap, pool: &Graph) -> Result<()> { | ||
for (_p, m) in archive_map.0.iter() { | ||
let (merged, ignored) = try_load_one_archive(m, pool).await?; | ||
println!( | ||
"TOTAL transactions updated: {}, ignored: {}", | ||
merged, ignored | ||
); | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
||
pub async fn try_load_one_archive(man: &ManifestInfo, pool: &Graph) -> Result<(u64, u64)> { | ||
let mut records_updated = 0u64; | ||
let mut records_ignored = 0u64; | ||
match man.contents { | ||
crate::scan::BundleContent::Unknown => todo!(), | ||
crate::scan::BundleContent::StateSnapshot => todo!(), | ||
crate::scan::BundleContent::Transaction => { | ||
let (txs, _) = extract_current_transactions(&man.archive_dir).await?; | ||
let (merged, ignored) = load_tx_cypher::tx_batch(&txs, pool, 100).await?; | ||
records_updated += merged; | ||
records_ignored += ignored; | ||
println!("transactions updated: {}, ignored: {}", merged, ignored); | ||
} | ||
crate::scan::BundleContent::EpochEnding => todo!(), | ||
} | ||
Ok((records_updated, records_ignored)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,41 +1,40 @@ | ||
use anyhow::Result; | ||
use neo4rs::{query, Graph}; | ||
|
||
use crate::table_structs::WarehouseTxMaster; | ||
use crate::{cypher_templates::write_batch_tx_string, table_structs::WarehouseTxMaster}; | ||
|
||
pub async fn load_tx_cypher( | ||
pub async fn tx_batch( | ||
txs: &[WarehouseTxMaster], | ||
pool: &Graph, | ||
batch_len: usize, | ||
) -> Result<()> { | ||
) -> Result<(u64, u64)> { | ||
let chunks: Vec<&[WarehouseTxMaster]> = txs.chunks(batch_len).collect(); | ||
let mut merged_count = 0u64; | ||
let mut ignored_count = 0u64; | ||
|
||
for c in chunks { | ||
impl_batch_tx_insert(pool, c).await?; | ||
let (m, ig) = impl_batch_tx_insert(pool, c).await?; | ||
merged_count += m; | ||
ignored_count += ig; | ||
} | ||
|
||
Ok(()) | ||
Ok((merged_count, ignored_count)) | ||
} | ||
|
||
pub async fn impl_batch_tx_insert(pool: &Graph, batch_txs: &[WarehouseTxMaster]) -> Result<u64> { | ||
let transactions = WarehouseTxMaster::slice_to_bolt_list(batch_txs); | ||
|
||
// for tx in batch_txs { | ||
// let mut this_query = tx.to_hashmap(); | ||
// transactions.push(this_query); | ||
// } | ||
|
||
let mut txn = pool.start_txn().await?; | ||
pub async fn impl_batch_tx_insert( | ||
pool: &Graph, | ||
batch_txs: &[WarehouseTxMaster], | ||
) -> Result<(u64, u64)> { | ||
let list_str = WarehouseTxMaster::slice_to_template(batch_txs); | ||
let cypher_string = write_batch_tx_string(list_str); | ||
|
||
let q = query( | ||
"UNWIND $transactions AS tx | ||
MERGE (from:Account {address: tx.sender}) | ||
MERGE (to:Account {address: tx.recipient}) | ||
MERGE (from)-[:Tx {tx_hash: tx.tx_hash}]->(to)", | ||
) | ||
.param("transactions", transactions); | ||
// Execute the query | ||
let cypher_query = query(&cypher_string); | ||
let mut res = pool.execute(cypher_query).await?; | ||
|
||
txn.run(q).await?; | ||
txn.commit().await?; | ||
let row = res.next().await?.unwrap(); | ||
let merged: i64 = row.get("merged_tx_count").unwrap(); | ||
let ignored: i64 = row.get("ignored_tx_count").unwrap(); | ||
|
||
Ok(0) | ||
Ok((merged as u64, ignored as u64)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,108 @@ | ||
use anyhow::{bail, Result}; | ||
use clap::{Parser, Subcommand}; | ||
use neo4rs::Graph; | ||
use std::path::PathBuf; | ||
|
||
// use crate::{read_snapshot, restore, restore_bundle::RestoreBundle}; | ||
use crate::{ | ||
load_entrypoint::{ingest_all, try_load_one_archive}, | ||
neo4j_init::{get_credentials_from_env, PASS_ENV, URI_ENV, USER_ENV}, | ||
scan::scan_dir_archive, | ||
}; | ||
|
||
#[derive(Parser)] | ||
#[clap(author, version, about, long_about = None)] | ||
#[clap(arg_required_else_help(true))] | ||
/// DB tools e.g.: backup, restore, export to json | ||
pub struct WarehouseCli { | ||
#[clap(long, short('d'))] | ||
/// URI of graphDB e.g. neo4j+s://localhost:port | ||
db_uri: Option<String>, | ||
/// username of db | ||
db_username: Option<String>, | ||
/// db password | ||
db_password: Option<String>, | ||
|
||
#[clap(subcommand)] | ||
command: Sub, | ||
} | ||
|
||
#[derive(Subcommand)] | ||
#[allow(clippy::large_enum_variant)] | ||
pub enum Sub { | ||
/// scans directory and subdirectory for manifests | ||
/// Tries to identify the libra version they belong to (v5 etc.) | ||
// #[clap(su)] | ||
Scan { | ||
/// scans sub directories for archive bundles | ||
IngestAll { | ||
#[clap(long, short('d'))] | ||
start_path: PathBuf, | ||
}, | ||
/// process and load a single archive | ||
LoadOne { | ||
#[clap(long, short('d'))] | ||
archive_dir: PathBuf, | ||
}, | ||
/// check archive is valid and can be decoded | ||
Check { | ||
#[clap(long, short('d'))] | ||
dir_archive: PathBuf, | ||
archive_dir: PathBuf, | ||
}, | ||
} | ||
|
||
impl WarehouseCli { | ||
pub fn run(&self) { | ||
pub async fn run(&self) -> anyhow::Result<()> { | ||
match &self.command { | ||
Sub::Scan { dir_archive } => { | ||
dbg!(&dir_archive) | ||
Sub::IngestAll { start_path } => { | ||
let map = scan_dir_archive(start_path)?; | ||
let pool = try_db_connection_pool(self).await?; | ||
|
||
ingest_all(&map, &pool).await?; | ||
} | ||
Sub::LoadOne { archive_dir } => match scan_dir_archive(archive_dir)?.0.get(archive_dir) | ||
{ | ||
Some(man) => { | ||
let pool = try_db_connection_pool(self).await?; | ||
try_load_one_archive(man, &pool).await?; | ||
} | ||
None => { | ||
bail!(format!( | ||
"ERROR: cannot find .manifest file under {}", | ||
archive_dir.display() | ||
)); | ||
} | ||
}, | ||
Sub::Check { archive_dir } => match scan_dir_archive(archive_dir)?.0.get(archive_dir) { | ||
Some(_) => todo!(), | ||
None => { | ||
bail!(format!( | ||
"ERROR: cannot find .manifest file under {}", | ||
archive_dir.display() | ||
)); | ||
} | ||
}, | ||
}; | ||
Ok(()) | ||
} | ||
} | ||
|
||
pub async fn try_db_connection_pool(cli: &WarehouseCli) -> Result<Graph> { | ||
let db = match get_credentials_from_env() { | ||
Ok((uri, user, password)) => Graph::new(uri, user, password).await?, | ||
Err(_) => { | ||
if cli.db_uri.is_some() && cli.db_username.is_some() && cli.db_password.is_some() { | ||
Graph::new( | ||
cli.db_uri.as_ref().unwrap(), | ||
cli.db_username.as_ref().unwrap(), | ||
cli.db_password.as_ref().unwrap(), | ||
) | ||
.await? | ||
} else { | ||
println!("Must pass DB credentials, either with CLI args or environment variable"); | ||
println!("call with --db-uri, --db-user, and --db-password"); | ||
println!( | ||
"Alternatively export credentials to env variables: {}, {}, {}", | ||
URI_ENV, USER_ENV, PASS_ENV | ||
); | ||
bail!("could not get a db instance with credentials"); | ||
} | ||
} | ||
}; | ||
Ok(db) | ||
} |
Oops, something went wrong.