Skip to content

Commit 1600218

Browse files
node: Add graphman chain rebuild-storage command
Adds the rebuild-storage subcommand to graphman chain. Looks up the chain in public.chains, rejects shared-storage chains, prompts for confirmation when storage already exists (--force skips the prompt), then delegates to BlockStore::rebuild_chain_storage.
1 parent b8b07ef commit 1600218

2 files changed

Lines changed: 73 additions & 0 deletions

File tree

node/src/bin/manager.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,20 @@ pub enum ChainCommand {
604604
/// The block number to ingest
605605
number: BlockNumber,
606606
},
607+
608+
/// Rebuild a chain's storage schema and reset head metadata.
609+
///
610+
/// If the storage schema is missing, rebuilds it silently.
611+
/// If the storage already exists, prompts for confirmation before
612+
/// dropping and rebuilding it (use --force to skip the prompt).
613+
RebuildStorage {
614+
/// Chain name (must be an existing chain, see 'chain list')
615+
#[clap(value_parser = clap::builder::NonEmptyStringValueParser::new())]
616+
chain_name: String,
617+
/// Skip confirmation prompt when storage already exists
618+
#[clap(long, short)]
619+
force: bool,
620+
},
607621
}
608622

609623
#[derive(Clone, Debug, Subcommand)]
@@ -1586,6 +1600,10 @@ async fn main() -> anyhow::Result<()> {
15861600
ctx.chain_store_and_adapter(&name).await?;
15871601
commands::chain::ingest(&logger, chain_store, ethereum_adapter, number).await
15881602
}
1603+
RebuildStorage { chain_name, force } => {
1604+
let (block_store, primary) = ctx.block_store_and_primary_pool().await;
1605+
commands::chain::rebuild_storage(primary, block_store, chain_name, force).await
1606+
}
15891607
}
15901608
}
15911609
Stats(cmd) => {

node/src/manager/commands/chain.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use graph::components::store::StoreError;
1313
use graph::prelude::BlockNumber;
1414
use graph::prelude::ChainStore as _;
1515
use graph::prelude::LightEthereumBlock;
16+
use graph::prelude::anyhow::Context as _;
1617
use graph::prelude::{anyhow, anyhow::bail};
1718
use graph::slog::Logger;
1819
use graph::{
@@ -27,11 +28,13 @@ use graph_store_postgres::ChainStore;
2728
use graph_store_postgres::PoolCoordinator;
2829
use graph_store_postgres::ScopedFutureExt;
2930
use graph_store_postgres::Shard;
31+
use graph_store_postgres::Storage;
3032
use graph_store_postgres::add_chain;
3133
use graph_store_postgres::find_chain;
3234
use graph_store_postgres::update_chain_name;
3335
use graph_store_postgres::{ConnectionPool, command_support::catalog::block_store};
3436

37+
use crate::manager::prompt::prompt_for_confirmation;
3538
use crate::network_setup::Networks;
3639

3740
pub async fn list(primary: ConnectionPool, store: BlockStore) -> Result<(), Error> {
@@ -329,3 +332,55 @@ pub async fn ingest(
329332
}
330333
Ok(())
331334
}
335+
336+
pub async fn rebuild_storage(
337+
primary: ConnectionPool,
338+
store: BlockStore,
339+
name: String,
340+
force: bool,
341+
) -> Result<(), Error> {
342+
let mut conn = primary.get().await?;
343+
344+
let chain = block_store::find_chain(&mut conn, &name)
345+
.await?
346+
.ok_or_else(|| {
347+
anyhow!(
348+
"Chain {} not found in public.chains.\n\
349+
This command only supports chains already present in metadata.",
350+
name
351+
)
352+
})?;
353+
354+
if matches!(chain.storage, Storage::Shared) {
355+
bail!(
356+
"Chain {} uses shared storage public and cannot be rebuilt with this command.",
357+
name
358+
);
359+
}
360+
361+
let namespace = chain.storage.to_string();
362+
let shard = &chain.shard;
363+
let ident = chain.network_identifier()?;
364+
365+
if store.has_namespace(&chain).await? {
366+
let prompt = format!(
367+
"Storage {namespace} for chain {name} already exists on shard {shard}.\n\
368+
This will drop and rebuild chain storage. All cached blocks and call cache \
369+
data in that namespace will be permanently deleted.\n\
370+
Proceed?"
371+
);
372+
if !force && !prompt_for_confirmation(&prompt)? {
373+
println!("Aborting.");
374+
return Ok(());
375+
}
376+
}
377+
378+
store
379+
.rebuild_chain_storage(&name, &ident)
380+
.await
381+
.with_context(|| format!("Failed to rebuild storage {namespace} for chain {name}"))?;
382+
383+
println!("Successfully rebuilt storage {namespace} for chain {name} on shard {shard}.");
384+
385+
Ok(())
386+
}

0 commit comments

Comments
 (0)