Commit 01594b7a authored by jan.koester's avatar jan.koester
Browse files

fixes

parent ff3312ae
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
mediadb (20260419+21) unstable; urgency=low

  * Fix delete_store in ClusterMediaBackend to properly delete all associated media blobs from cluster storage.

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

mediadb (20260419+20) unstable; urgency=low

  * Make MDB import synchronous without background thread.

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

mediadb (20260419+19) unstable; urgency=low

  * Add cluster-wide Scrub & Rebalance status to admin UI:
+2 −28
Original line number Diff line number Diff line
@@ -1639,34 +1639,8 @@ HttpResponse App::handle_export(const HttpRequest& req) {
HttpResponse App::handle_import(const HttpRequest& req) {
    if (!auth_.is_authorized(req)) return error_json(401, "unauthorized");
    if (!auth_.check_gpo(req, GPO_IMPORT)) return error_json(403, "no permission: db.import");
    if (req.body.empty()) return error_json(400, "empty body");
    if (import_running_.load()) return error_json(409, "import already in progress");

    // Copy body and run import in background thread
    auto data = std::make_shared<std::vector<uint8_t>>(
        reinterpret_cast<const uint8_t*>(req.body.data()),
        reinterpret_cast<const uint8_t*>(req.body.data()) + req.body.size());

    {
        std::lock_guard<std::mutex> lk(import_mutex_);
        import_running_.store(true);
        import_ok_.store(false);
        import_error_.clear();
    }

    if (import_thread_.joinable()) import_thread_.join();
    import_thread_ = std::thread([this, data]() {
        bool ok = db_.import_db_from_buffer(data->data(), data->size());
        std::lock_guard<std::mutex> lk(import_mutex_);
        import_ok_.store(ok);
        if (!ok) import_error_ = "import failed";
        import_running_.store(false);
    });
    
    json_object* j = json_object_new_object();
    json_object_object_add(j, "status", json_object_new_string("accepted"));
    json_object_object_add(j, "message", json_object_new_string("import started, poll /api/import/status"));
    return HttpResponse::json(202, j);
    return start_import(reinterpret_cast<const uint8_t*>(req.body.data()), req.body.size());
}

// ---- login handler ----
+19 −1
Original line number Diff line number Diff line
@@ -2467,9 +2467,27 @@ std::vector<StoreRecord> ClusterMediaBackend::list_stores() const {

bool ClusterMediaBackend::delete_store(const std::string& id) {
    std::unique_lock<std::shared_mutex> cguard(cluster_op_mutex_);
    
    // Collect all media and albums to remove their cluster objects
    std::vector<std::string> media_to_remove;
    auto albums = local_.list_albums(id);
    for (const auto& album : albums) {
        auto media_list = local_.list_media(album.id);
        for (const auto& m : media_list) {
            media_to_remove.push_back(m.id);
        }
    }

    if (!local_.delete_store(id)) return false;
    // Remove store blob (contains all media data inline)

    // Remove store metadata blob
    cluster_.remove("store:" + id);
    
    // Remove all associated media data blobs
    for (const auto& mid : media_to_remove) {
        cluster_.remove("media:" + mid);
    }
    
    replicate_index();
    return true;
}