Skip to content

Commit 309d130

Browse files
authored
Merge branch 'main' into fail-if-mismatch-ts-moose-lib
2 parents 4fa8c9e + 2735260 commit 309d130

13 files changed

Lines changed: 673 additions & 380 deletions

File tree

apps/framework-cli/src/cli/local_webserver.rs

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3502,7 +3502,6 @@ async fn get_admin_reconciled_inframap(
35023502
) -> Result<InfrastructureMap, crate::framework::core::plan::PlanningError> {
35033503
use crate::framework::core::state_storage::StateStorageBuilder;
35043504
use crate::infrastructure::olap::clickhouse;
3505-
use std::collections::HashSet;
35063505

35073506
// Build state storage from project configuration.
35083507
// This provides access to the persisted infrastructure map (stored in Redis or ClickHouse).
@@ -3530,21 +3529,10 @@ async fn get_admin_reconciled_inframap(
35303529
};
35313530

35323531
// For admin endpoints, reconcile all currently managed tables and SQL resources only.
3533-
// Pass the managed table IDs as target_table_ids - this ensures that
3534-
// reconcile_with_reality only operates on resources that are already managed by Moose.
3535-
let target_table_ids: HashSet<String> = current_map
3536-
.tables
3537-
.values()
3538-
.map(|t| t.id(&current_map.default_database))
3539-
.collect();
3540-
3541-
let target_sql_resource_ids: HashSet<String> =
3542-
current_map.sql_resources.keys().cloned().collect();
3543-
3544-
let target_materialized_view_ids: HashSet<String> =
3545-
current_map.materialized_views.keys().cloned().collect();
3546-
3547-
let target_view_ids: HashSet<String> = current_map.views.keys().cloned().collect();
3532+
// Use the current map's resource IDs as the filter—this ensures that
3533+
// reconcile_with_reality only operates on resources already managed by Moose,
3534+
// not external tables that happen to exist in the same database.
3535+
let filter = crate::framework::core::plan::ReconciliationFilter::from_infra_map(&current_map);
35483536

35493537
// Reconcile the loaded map with actual database state (single load, no race condition).
35503538
// reconcile_with_reality handles the OLAP-disabled case internally, and in the future
@@ -3555,10 +3543,7 @@ async fn get_admin_reconciled_inframap(
35553543
crate::framework::core::plan::reconcile_with_reality(
35563544
project,
35573545
&current_map,
3558-
&target_table_ids,
3559-
&target_sql_resource_ids,
3560-
&target_materialized_view_ids,
3561-
&target_view_ids,
3546+
&filter,
35623547
clickhouse_client,
35633548
)
35643549
.await?

apps/framework-cli/src/cli/routines/migrate.rs

Lines changed: 32 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::cli::routines::RoutineFailure;
55
use crate::framework::core::infrastructure::table::Table;
66
use crate::framework::core::infrastructure_map::InfrastructureMap;
77
use 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};
99
use crate::framework::core::state_storage::{StateStorage, StateStorageBuilder};
1010
use crate::infrastructure::olap::clickhouse::config::{ClickHouseConfig, ClusterConfig};
1111
use 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,

apps/framework-cli/src/cli/routines/mod.rs

Lines changed: 9 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ use super::{Message, MessageType};
120120
use crate::framework::core::partial_infrastructure_map::LifeCycle;
121121
use crate::framework::core::plan::plan_changes;
122122
use crate::framework::core::plan::InfraPlan;
123+
use crate::framework::core::plan::ReconciliationFilter;
123124
use crate::framework::core::state_storage::StateStorageBuilder;
124125
use crate::framework::languages::SupportedLanguages;
125126
use crate::infrastructure::olap::clickhouse::diff_strategy::ClickHouseTableDiffStrategy;
@@ -1268,30 +1269,9 @@ pub async fn remote_plan(
12681269
);
12691270
}
12701271

1271-
let table_names: HashSet<String> = local_infra_map
1272-
.tables
1273-
.values()
1274-
.map(|t| t.id(&local_infra_map.default_database))
1275-
.collect();
1276-
1277-
let sql_resource_ids: HashSet<String> =
1278-
local_infra_map.sql_resources.keys().cloned().collect();
1272+
let filter = ReconciliationFilter::from_infra_map(&local_infra_map);
12791273

1280-
let materialized_view_ids: HashSet<String> =
1281-
local_infra_map.materialized_views.keys().cloned().collect();
1282-
1283-
let view_ids: HashSet<String> = local_infra_map.views.keys().cloned().collect();
1284-
1285-
get_remote_inframap_serverless(
1286-
project,
1287-
clickhouse_url,
1288-
None,
1289-
&table_names,
1290-
&sql_resource_ids,
1291-
&materialized_view_ids,
1292-
&view_ids,
1293-
)
1294-
.await?
1274+
get_remote_inframap_serverless(project, clickhouse_url, None, &filter).await?
12951275
} else {
12961276
// Moose server flow
12971277
if !json {
@@ -1478,27 +1458,10 @@ pub async fn remote_gen_migration(
14781458
},
14791459
);
14801460

1481-
let target_table_ids: HashSet<String> = local_infra_map
1482-
.tables
1483-
.values()
1484-
.map(|t| t.id(&local_infra_map.default_database))
1485-
.collect();
1486-
let target_sql_resource_ids: HashSet<String> =
1487-
local_infra_map.sql_resources.keys().cloned().collect();
1488-
let target_materialized_view_ids: HashSet<String> =
1489-
local_infra_map.materialized_views.keys().cloned().collect();
1490-
let target_view_ids: HashSet<String> = local_infra_map.views.keys().cloned().collect();
1491-
1492-
get_remote_inframap_serverless(
1493-
project,
1494-
clickhouse_url,
1495-
redis_url.as_deref(),
1496-
&target_table_ids,
1497-
&target_sql_resource_ids,
1498-
&target_materialized_view_ids,
1499-
&target_view_ids,
1500-
)
1501-
.await?
1461+
let filter = ReconciliationFilter::from_infra_map(&local_infra_map);
1462+
1463+
get_remote_inframap_serverless(project, clickhouse_url, redis_url.as_deref(), &filter)
1464+
.await?
15021465
}
15031466
};
15041467

@@ -1561,10 +1524,7 @@ async fn get_remote_inframap_serverless(
15611524
project: &Project,
15621525
clickhouse_url: &str,
15631526
redis_url: Option<&str>,
1564-
target_table_ids: &HashSet<String>,
1565-
target_sql_resource_ids: &HashSet<String>,
1566-
target_materialized_view_ids: &HashSet<String>,
1567-
target_view_ids: &HashSet<String>,
1527+
filter: &ReconciliationFilter,
15681528
) -> anyhow::Result<InfrastructureMap> {
15691529
use crate::infrastructure::olap::clickhouse::config::parse_clickhouse_connection_string;
15701530
use crate::infrastructure::olap::clickhouse::create_client;
@@ -1584,10 +1544,7 @@ async fn get_remote_inframap_serverless(
15841544
project,
15851545
&*state_storage,
15861546
olap_client,
1587-
target_table_ids,
1588-
target_sql_resource_ids,
1589-
target_materialized_view_ids,
1590-
target_view_ids,
1547+
filter,
15911548
)
15921549
.await?;
15931550

0 commit comments

Comments
 (0)