Commit 6541a85e authored by jan.koester's avatar jan.koester
Browse files

test

parent 7802eb7f
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
mediadb (20260419+31) unstable; urgency=critical

  * Fix critical data corruption during concurrent import + periodic 
    repair/sync: `repair_replication()`, `sync_from_cluster()`, scrub, and 
    rebalance are now blocked while an import is in progress. Previously 
    these could push half-imported index/store metadata to the cluster, 
    overwriting valid data with garbage.

 -- Jan Koester <jan.koester@tuxist.de>  Sun, 19 Apr 2026 17:30:00 +0200

mediadb (20260419+30) unstable; urgency=medium

  * Add Repair Index button to cluster.html UI.
+8 −0
Original line number Diff line number Diff line
@@ -884,6 +884,10 @@ HttpResponse App::handle_cluster_scrub(const HttpRequest& req) {
        return error_json(400, "cluster not enabled");
    }

    if (import_running_.load()) {
        return error_json(409, "import in progress — scrub blocked to prevent data corruption");
    }

    if (g_Cluster->isCritical()) {
        return error_json(503, "cluster is critical — need more nodes online");
    }
@@ -913,6 +917,10 @@ HttpResponse App::handle_cluster_rebalance(const HttpRequest& req) {
        return error_json(400, "cluster not enabled");
    }

    if (import_running_.load()) {
        return error_json(409, "import in progress — rebalance blocked to prevent data corruption");
    }

    if (g_Cluster->isCritical()) {
        return error_json(503, "cluster is critical — need more nodes online");
    }
+9 −1
Original line number Diff line number Diff line
@@ -2981,6 +2981,10 @@ void ClusterMediaBackend::sync_from_cluster() {
        std::cerr << "[CLUSTER-SYNC] cluster not running, skipping sync\n";
        return;
    }
    if (importing_.load()) {
        std::cerr << "[CLUSTER-SYNC] import in progress, skipping sync\n";
        return;
    }

    uint64_t index_gid = cluster_group_id("index");
    bool has_index = false;
@@ -3226,6 +3230,8 @@ void ClusterMediaBackend::replicate_store(const std::string& store_id) {

void ClusterMediaBackend::repair_replication() {
    if (!cluster_.isRunning()) return;
    if (importing_.load()) return;
    if (!initial_sync_ok_.load()) return;
    size_t total_peers = cluster_.getTotalPeers();
    if (total_peers < 2) return;

@@ -3306,8 +3312,10 @@ void ClusterMediaBackend::sync_loop() {
            // Run repair every 6th cycle (~30s)
            if (++cycle >= 6) {
                cycle = 0;
                if (!importing_.load()) {
                    repair_replication();
                }
            }
        } catch (const std::exception& e) {
            DBG_LOG("[CLUSTER-SYNC] periodic sync failed: " << e.what() << "\n");
        } catch (...) {