@@ -5,7 +5,7 @@ use crate::cli::routines::RoutineFailure;
55use crate :: framework:: core:: infrastructure:: table:: Table ;
66use crate :: framework:: core:: infrastructure_map:: InfrastructureMap ;
77use crate :: framework:: core:: migration_plan:: MigrationPlan ;
8- use crate :: framework:: core:: plan:: reconcile_with_reality;
8+ use crate :: framework:: core:: plan:: { reconcile_with_reality, ReconciliationFilter } ;
99use crate :: framework:: core:: state_storage:: { StateStorage , StateStorageBuilder } ;
1010use crate :: infrastructure:: olap:: clickhouse:: config:: { ClickHouseConfig , ClusterConfig } ;
1111use crate :: infrastructure:: olap:: clickhouse:: IgnorableOperation ;
@@ -570,85 +570,59 @@ pub async fn execute_migration(
570570
571571 // Wrap all operations to ensure lock cleanup on any error
572572 let result = async {
573- // Load current state from ClickHouse state table and reconcile with reality
573+ // Load target state from current code first—we need its resource IDs to
574+ // correctly filter which unmapped ClickHouse objects to adopt during
575+ // reconciliation. Without this, a fresh Redis (no stored state) would
576+ // produce an empty filter, causing reconciliation to ignore every
577+ // pre-existing table and the drift check to report them all as "removed".
578+ let target_infra_map = InfrastructureMap :: load_from_user_code ( project, true )
579+ . await
580+ . map_err ( |e| {
581+ RoutineFailure :: new (
582+ Message :: new (
583+ "Code" . to_string ( ) ,
584+ "Failed to load infrastructure from code" . to_string ( ) ,
585+ ) ,
586+ e,
587+ )
588+ } ) ?;
589+
590+ // Load current state from state storage and reconcile with reality
574591 let current_infra_map = state_storage
575592 . load_infrastructure_map ( )
576593 . await
577594 . map_err ( |e| {
578595 RoutineFailure :: new (
579596 Message :: new (
580597 "State" . to_string ( ) ,
581- "Failed to load infrastructure state from ClickHouse " . to_string ( ) ,
598+ "Failed to load infrastructure state" . to_string ( ) ,
582599 ) ,
583600 e,
584601 )
585602 } ) ?
586603 . unwrap_or_else ( || InfrastructureMap :: empty_from_project ( project) ) ;
587604
588605 let current_infra_map = if project. features . olap {
589- use std:: collections:: HashSet ;
590-
591- // current_infra_map should have gone through fixup_default_db, but better safe than sorry
592- let target_table_ids: HashSet < String > = current_infra_map
593- . tables
594- . values ( )
595- . map ( |t| t. id ( & current_infra_map. default_database ) )
596- . collect ( ) ;
597-
598- let target_sql_resource_ids: HashSet < String > =
599- current_infra_map. sql_resources . keys ( ) . cloned ( ) . collect ( ) ;
600-
601- let target_materialized_view_ids: HashSet < String > = current_infra_map
602- . materialized_views
603- . keys ( )
604- . cloned ( )
605- . collect ( ) ;
606-
607- let target_view_ids: HashSet < String > =
608- current_infra_map. views . keys ( ) . cloned ( ) . collect ( ) ;
609-
606+ let filter = ReconciliationFilter :: from_infra_map ( & target_infra_map) ;
610607 let olap_client = create_client ( clickhouse_config. clone ( ) ) ;
611608
612- // We already have the current_infra_map loaded, so reconcile it directly
613- // instead of reloading from storage via load_reconciled_infrastructure
614- reconcile_with_reality (
615- project,
616- & current_infra_map,
617- & target_table_ids,
618- & target_sql_resource_ids,
619- & target_materialized_view_ids,
620- & target_view_ids,
621- olap_client,
622- )
623- . await
624- . map_err ( |e| {
625- RoutineFailure :: new (
626- Message :: new (
627- "Reconciliation" . to_string ( ) ,
628- "Failed to reconcile state with ClickHouse reality" . to_string ( ) ,
629- ) ,
630- anyhow:: anyhow!( "{:?}" , e) ,
631- )
632- } ) ?
609+ reconcile_with_reality ( project, & current_infra_map, & filter, olap_client)
610+ . await
611+ . map_err ( |e| {
612+ RoutineFailure :: new (
613+ Message :: new (
614+ "Reconciliation" . to_string ( ) ,
615+ "Failed to reconcile state with ClickHouse reality" . to_string ( ) ,
616+ ) ,
617+ e,
618+ )
619+ } ) ?
633620 } else {
634621 current_infra_map
635622 } ;
636623
637624 let current_tables = & current_infra_map. tables ;
638625
639- // Load target state from current code with credentials resolved for migration DDL
640- let target_infra_map = InfrastructureMap :: load_from_user_code ( project, true )
641- . await
642- . map_err ( |e| {
643- RoutineFailure :: new (
644- Message :: new (
645- "Code" . to_string ( ) ,
646- "Failed to load infrastructure from code" . to_string ( ) ,
647- ) ,
648- e,
649- )
650- } ) ?;
651-
652626 // Execute migration
653627 execute_migration_plan (
654628 project,
0 commit comments