@@ -10,6 +10,7 @@ use graph::cheap_clone::CheapClone;
1010use graph:: components:: network_provider:: ChainName ;
1111use graph:: components:: store:: ChainIdStore ;
1212use graph:: components:: store:: StoreError ;
13+ use graph:: prelude:: anyhow:: Context as _;
1314use graph:: prelude:: BlockNumber ;
1415use graph:: prelude:: ChainStore as _;
1516use graph:: prelude:: LightEthereumBlock ;
@@ -30,8 +31,10 @@ use graph_store_postgres::ChainStore;
3031use graph_store_postgres:: PoolCoordinator ;
3132use graph_store_postgres:: ScopedFutureExt ;
3233use graph_store_postgres:: Shard ;
34+ use graph_store_postgres:: Storage ;
3335use graph_store_postgres:: { command_support:: catalog:: block_store, ConnectionPool } ;
3436
37+ use crate :: manager:: prompt:: prompt_for_confirmation;
3538use crate :: network_setup:: Networks ;
3639
3740pub 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