Commit 1a7a4297 authored by jan.koester's avatar jan.koester
Browse files

test

parent be9a2e11
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
mediadb (20260419+38) unstable; urgency=critical

  * Fix import + tombstone conflict: importing stores that were previously
    deleted caused tombstones to immediately re-delete them on the next sync.
    Import now clears tombstones for all imported store IDs and replicates the
    cleared tombstone list to the cluster. Also fixed replicate_tombstones()
    to push even when the set is empty, so cleared tombstones actually
    propagate to other nodes.

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

mediadb (20260419+37) unstable; urgency=critical

  * Prevent stale index overwrite: replicate_index() now compares local
+18 −2
Original line number Diff line number Diff line
@@ -2903,6 +2903,22 @@ bool ClusterMediaBackend::import_db_from_buffer(const std::uint8_t* data, std::s
              << " replicated=" << repl_count << " failed=" << repl_fail << "\n";
    if (!parse_ok || repl_fail > 0) { importing_.store(false); return false; }

    // Clear tombstones for any stores that were just imported.
    // Without this, a previous delete_store tombstone would cause
    // sync_from_cluster to immediately remove the reimported store.
    {
        auto sids = local_.store_ids();
        bool tombstone_changed = false;
        for (const auto& sid : sids) {
            if (tombstones_.erase(sid) > 0)
                tombstone_changed = true;
        }
        if (tombstone_changed) {
            replicate_tombstones();
            std::cerr << "[CLUSTER-IMPORT] cleared tombstones for imported stores\n";
        }
    }

    // Verify replication: ensure all keys have enough shards on all nodes.
    std::cerr << "[CLUSTER-IMPORT] verifying replication\n";
    {
@@ -3301,8 +3317,8 @@ void ClusterMediaBackend::replicate_store(const std::string& store_id) {

void ClusterMediaBackend::replicate_tombstones() {
    if (!cluster_.isRunning()) return;
    if (tombstones_.empty()) return;
    // Serialise: u32 count, then each id as length-prefixed string
    // Serialise: u32 count, then each id as length-prefixed string.
    // Always replicate — even when empty — so other nodes see the cleared list.
    std::vector<std::uint8_t> buf;
    auto push_u32 = [&](std::uint32_t v) {
        buf.push_back(static_cast<uint8_t>(v & 0xFF));