refactor: complete v0.8 core architecture
This commit is contained in:
1 parent
f138a645f8
commit
d7e0ac7679
98 files changed
+8413
-3044
No files matched your search
+102
-84
@@ -30,55 +30,89 @@ pub async fn run(
|
||||
}
|
||||
|
||||
let start_time = std::time::Instant::now();
|
||||
let admin_dir = config.data_dir.join("admin");
|
||||
let system_db_path = admin_dir.join("system.db");
|
||||
let users_db_path = admin_dir.join("users.db");
|
||||
let topology = crate::db::topology::Topology::new(&config.data_dir);
|
||||
let system_db_path = topology.system_db();
|
||||
let users_db_path = topology.users_registry_db();
|
||||
let urls_db_path = topology.global_urls_db();
|
||||
let pages_db_path = topology.global_landing_pages_db();
|
||||
|
||||
if !system_db_path.exists() || !users_db_path.exists() {
|
||||
println!("Error: system.db or users.db not found.");
|
||||
if !system_db_path.exists()
|
||||
|| !users_db_path.exists()
|
||||
|| !urls_db_path.exists()
|
||||
|| !pages_db_path.exists()
|
||||
{
|
||||
println!("Error: Core databases (system.db, users.db, slugs/*.db) not found.");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut sys_conn = Connection::open(&system_db_path)?;
|
||||
let sys_conn = Connection::open(&system_db_path)?;
|
||||
let usr_conn = Connection::open(&users_db_path)?;
|
||||
let mut urls_conn = Connection::open(&urls_db_path)?;
|
||||
let mut pages_conn = Connection::open(&pages_db_path)?;
|
||||
|
||||
let slug_filter = slug.as_deref();
|
||||
|
||||
if dry_run {
|
||||
println!("BZOD Registry Repair\n");
|
||||
println!("Scanning Global Slug Registry...");
|
||||
println!("BZOD Registry Repair (v0.8)\n");
|
||||
println!("Scanning Authoritative Slug Registries (global_urls.db, global_landing_pages.db)...");
|
||||
|
||||
let issues =
|
||||
RegistryValidator::scan(&sys_conn, &usr_conn, &config.data_dir, slug_filter)?;
|
||||
let orphaned = issues
|
||||
.into_iter()
|
||||
|
||||
let true_orphans = issues
|
||||
.iter()
|
||||
.filter(|i| {
|
||||
matches!(
|
||||
i.issue_type,
|
||||
RegistryIssueType::MissingTarget
|
||||
| RegistryIssueType::MissingDatabase
|
||||
| RegistryIssueType::MissingOwner
|
||||
| RegistryIssueType::TrueOrphan
|
||||
| RegistryIssueType::MissingTenant
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let orphaned_pages = orphaned.iter().filter(|i| i.target_type == "page").count();
|
||||
let orphaned_urls = orphaned.iter().filter(|i| i.target_type == "url").count();
|
||||
let corrupt = issues
|
||||
.iter()
|
||||
.filter(|i| i.issue_type == RegistryIssueType::CorruptDatabase)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
println!("\nDetected:");
|
||||
println!("\nPages:\n {} orphaned", orphaned_pages);
|
||||
println!("\nURLs:\n {} orphaned", orphaned_urls);
|
||||
let access_failures = issues
|
||||
.iter()
|
||||
.filter(|i| i.issue_type == RegistryIssueType::AccessFailure)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if !orphaned.is_empty() {
|
||||
println!("\nThe following entries would be removed:");
|
||||
for issue in &orphaned {
|
||||
println!("\n{}\n {}", issue.target_type.to_uppercase(), issue.slug);
|
||||
println!("\nDetected Issues (Total: {}):", issues.len());
|
||||
println!(" Orphaned/Missing Targets: {}", true_orphans.len());
|
||||
println!(" Corrupt Databases (Protected): {}", corrupt.len());
|
||||
println!(" Access Failures (Protected): {}", access_failures.len());
|
||||
|
||||
if !true_orphans.is_empty() {
|
||||
println!("\nThe following orphaned entries would be repaired/removed:");
|
||||
for issue in &true_orphans {
|
||||
println!(
|
||||
" {} [{}] — Tenant: {}",
|
||||
issue.slug,
|
||||
issue.target_type.to_uppercase(),
|
||||
issue.owner_tenant_id
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
println!("\nNo changes have been made.");
|
||||
if !corrupt.is_empty() {
|
||||
println!("\nProtected from destructive repair (Corrupt DBs):");
|
||||
for issue in &corrupt {
|
||||
println!(
|
||||
" {} [{}] — Path: {:?}",
|
||||
issue.slug,
|
||||
issue.target_type.to_uppercase(),
|
||||
issue.database_path
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
println!("\nNo changes have been made (dry-run).");
|
||||
println!(
|
||||
"\nRun again with:\n\n bzod repair registry --force{}",
|
||||
"Run again with:\n bzod repair registry --force{}",
|
||||
if let Some(s) = slug_filter {
|
||||
format!(" --slug {}", s)
|
||||
} else {
|
||||
@@ -87,89 +121,73 @@ pub async fn run(
|
||||
);
|
||||
|
||||
info!(
|
||||
"Registry Repair Started. Scanned. Orphaned Pages: {}, Orphaned URLs: {}. Duration: {:?}",
|
||||
orphaned_pages, orphaned_urls, start_time.elapsed()
|
||||
"Registry Repair Scan completed. Orphaned: {}, Corrupt: {}, Duration: {:?}",
|
||||
true_orphans.len(),
|
||||
corrupt.len(),
|
||||
start_time.elapsed()
|
||||
);
|
||||
} else if force {
|
||||
let tx = sys_conn.transaction()?;
|
||||
|
||||
let issues =
|
||||
RegistryValidator::scan(&tx, &usr_conn, &config.data_dir, slug_filter)?;
|
||||
let orphaned = issues
|
||||
RegistryValidator::scan(&sys_conn, &usr_conn, &config.data_dir, slug_filter)?;
|
||||
|
||||
// Only repair true orphans, missing targets, or missing tenants.
|
||||
// Never delete records with CorruptDatabase or AccessFailure per safety policies.
|
||||
let repairable = issues
|
||||
.into_iter()
|
||||
.filter(|i| {
|
||||
matches!(
|
||||
i.issue_type,
|
||||
RegistryIssueType::MissingTarget
|
||||
| RegistryIssueType::MissingDatabase
|
||||
| RegistryIssueType::MissingOwner
|
||||
| RegistryIssueType::TrueOrphan
|
||||
| RegistryIssueType::MissingTenant
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let orphaned_pages = orphaned.iter().filter(|i| i.target_type == "page").count();
|
||||
let orphaned_urls = orphaned.iter().filter(|i| i.target_type == "url").count();
|
||||
|
||||
if orphaned.is_empty() {
|
||||
println!("No repairs required.");
|
||||
if repairable.is_empty() {
|
||||
println!("No repairable registry issues found.");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let Some(s) = slug_filter {
|
||||
println!("Checking slug:\n\n{}\n", s);
|
||||
if let Some(issue) = orphaned.first() {
|
||||
println!("Owner:\n\n{}\n", issue.owner_user_id);
|
||||
println!("Status:\n\nOrphaned\n");
|
||||
let tx_urls = urls_conn.transaction()?;
|
||||
let tx_pages = pages_conn.transaction()?;
|
||||
|
||||
let mut removed_count = 0;
|
||||
for issue in &repairable {
|
||||
if issue.target_type == "url" {
|
||||
removed_count += tx_urls
|
||||
.execute("DELETE FROM global_urls WHERE slug = ?1;", [&issue.slug])?;
|
||||
} else {
|
||||
removed_count += tx_pages.execute(
|
||||
"DELETE FROM global_landing_pages WHERE slug = ?1;",
|
||||
[&issue.slug],
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
let mut removed_count = 0;
|
||||
for issue in &orphaned {
|
||||
let rows = tx.execute(
|
||||
"DELETE FROM global_slugs WHERE slug = ?1",
|
||||
rusqlite::params![issue.slug],
|
||||
)?;
|
||||
removed_count += rows;
|
||||
}
|
||||
tx_urls.commit()?;
|
||||
tx_pages.commit()?;
|
||||
|
||||
tx.commit()?;
|
||||
// Record audit event in system.db
|
||||
let _ = crate::db::audit_events::write_audit_event(
|
||||
&sys_conn,
|
||||
"cli",
|
||||
"REGISTRY_REPAIR",
|
||||
"registry",
|
||||
slug_filter.unwrap_or("*"),
|
||||
Some(&format!(
|
||||
"Repaired/removed {} orphaned slug entries",
|
||||
removed_count
|
||||
)),
|
||||
);
|
||||
|
||||
if slug_filter.is_some() {
|
||||
println!("Removed:\n\nSUCCESS");
|
||||
} else {
|
||||
println!("Repair Complete\n");
|
||||
println!("Removed:\n");
|
||||
println!("Pages:\n {}\n", orphaned_pages);
|
||||
println!("URLs:\n {}\n", orphaned_urls);
|
||||
|
||||
let remaining: i64 =
|
||||
sys_conn
|
||||
.query_row("SELECT COUNT(*) FROM global_slugs;", [], |r| r.get(0))?;
|
||||
println!("Remaining Registry Entries:\n {}\n", remaining);
|
||||
|
||||
let post_issues =
|
||||
RegistryValidator::scan(&sys_conn, &usr_conn, &config.data_dir, None)?;
|
||||
let post_orphaned = post_issues
|
||||
.iter()
|
||||
.filter(|i| {
|
||||
matches!(
|
||||
i.issue_type,
|
||||
RegistryIssueType::MissingTarget
|
||||
| RegistryIssueType::MissingDatabase
|
||||
| RegistryIssueType::MissingOwner
|
||||
)
|
||||
})
|
||||
.count();
|
||||
|
||||
println!(
|
||||
"Integrity:\n {}",
|
||||
if post_orphaned == 0 { "PASS" } else { "FAIL" }
|
||||
);
|
||||
}
|
||||
println!("Registry Repair Complete.");
|
||||
println!("Repaired/Removed: {} entries", removed_count);
|
||||
|
||||
info!(
|
||||
"Registry Repair Started. Scanned. Orphaned Pages: {}, Orphaned URLs: {}. Removed: {}. Duration: {:?}",
|
||||
orphaned_pages, orphaned_urls, removed_count, start_time.elapsed()
|
||||
"Registry Repair Complete. Removed: {}. Duration: {:?}",
|
||||
removed_count,
|
||||
start_time.elapsed()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user