Loading debian/changelog +8 −0 Original line number Diff line number Diff line mediadb (20260422+59) unstable; urgency=low * Fix stuck import state: clean up orphaned H2 import sessions on client disconnect so import_running_ is correctly reset. * Show import status (In Progress / Idle) on cluster status page. -- Jan Koester <jan.koester@tuxist.de> Wed, 22 Apr 2026 00:00:00 +0200 mediadb (20260421+58) unstable; urgency=low * Fix admin.html: navigating to albums did not hide domain/ACL Loading html/cluster.html +2 −0 Original line number Diff line number Diff line Loading @@ -149,6 +149,8 @@ async function loadClusterStatus() { health.status === 'OK' ? '' : health.status === 'DEGRADED' ? 'warn' : 'err'); addSummaryCard(summary, 'Nodes Online', (health.nodes_online || 0) + ' / ' + (health.nodes_total || 0), health.nodes_online === health.nodes_total ? '' : 'warn'); addSummaryCard(summary, 'Import', health.import_running ? 'In Progress' : 'Idle', health.import_running ? 'warn' : ''); if (stores.stores) { const missing = stores.stores.filter(s => s.replicated_count < s.total_nodes).length; Loading src/app.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -693,6 +693,10 @@ HttpResponse App::handle_cluster_status(const HttpRequest& req) { if (!auth_.is_authorized(req)) return error_json(401, "unauthorized"); json_object* j = json_object_new_object(); // Import status — always included regardless of cluster state json_object_object_add(j, "import_running", json_object_new_boolean(import_running_.load())); if (!g_Cluster || !g_Cluster->isRunning()) { json_object_object_add(j, "enabled", json_object_new_boolean(false)); return HttpResponse::json(200, j); Loading src/server.cpp +13 −1 Original line number Diff line number Diff line Loading @@ -312,11 +312,23 @@ void MediaHttpEvent::ResponseEvent(libhttppp::HttpRequest& curreq, const int /*t void MediaHttpEvent::ConnectEvent(libhttppp::HttpRequest& /*curreq*/, const int /*tid*/, ULONG_PTR /*args*/) {} void MediaHttpEvent::DisconnectEvent(libhttppp::HttpRequest& curreq, const int /*tid*/, ULONG_PTR /*args*/) { // Clean up any orphaned import session (client disconnected mid-upload) // Clean up any orphaned H1 import session (client disconnected mid-upload) auto it = active_imports_.find(static_cast<netplus::con*>(&curreq)); if (it != active_imports_.end()) { active_imports_.erase(it); app_.finish_import(false, "client disconnected"); return; } // Clean up any orphaned H2 import sessions on this connection for (auto h2it = h2_imports_.begin(); h2it != h2_imports_.end(); ) { if (h2it->first.conn == &curreq) { h2it = h2_imports_.erase(h2it); app_.finish_import(false, "client disconnected"); return; } else { ++h2it; } } } Loading Loading
debian/changelog +8 −0 Original line number Diff line number Diff line mediadb (20260422+59) unstable; urgency=low * Fix stuck import state: clean up orphaned H2 import sessions on client disconnect so import_running_ is correctly reset. * Show import status (In Progress / Idle) on cluster status page. -- Jan Koester <jan.koester@tuxist.de> Wed, 22 Apr 2026 00:00:00 +0200 mediadb (20260421+58) unstable; urgency=low * Fix admin.html: navigating to albums did not hide domain/ACL Loading
html/cluster.html +2 −0 Original line number Diff line number Diff line Loading @@ -149,6 +149,8 @@ async function loadClusterStatus() { health.status === 'OK' ? '' : health.status === 'DEGRADED' ? 'warn' : 'err'); addSummaryCard(summary, 'Nodes Online', (health.nodes_online || 0) + ' / ' + (health.nodes_total || 0), health.nodes_online === health.nodes_total ? '' : 'warn'); addSummaryCard(summary, 'Import', health.import_running ? 'In Progress' : 'Idle', health.import_running ? 'warn' : ''); if (stores.stores) { const missing = stores.stores.filter(s => s.replicated_count < s.total_nodes).length; Loading
src/app.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -693,6 +693,10 @@ HttpResponse App::handle_cluster_status(const HttpRequest& req) { if (!auth_.is_authorized(req)) return error_json(401, "unauthorized"); json_object* j = json_object_new_object(); // Import status — always included regardless of cluster state json_object_object_add(j, "import_running", json_object_new_boolean(import_running_.load())); if (!g_Cluster || !g_Cluster->isRunning()) { json_object_object_add(j, "enabled", json_object_new_boolean(false)); return HttpResponse::json(200, j); Loading
src/server.cpp +13 −1 Original line number Diff line number Diff line Loading @@ -312,11 +312,23 @@ void MediaHttpEvent::ResponseEvent(libhttppp::HttpRequest& curreq, const int /*t void MediaHttpEvent::ConnectEvent(libhttppp::HttpRequest& /*curreq*/, const int /*tid*/, ULONG_PTR /*args*/) {} void MediaHttpEvent::DisconnectEvent(libhttppp::HttpRequest& curreq, const int /*tid*/, ULONG_PTR /*args*/) { // Clean up any orphaned import session (client disconnected mid-upload) // Clean up any orphaned H1 import session (client disconnected mid-upload) auto it = active_imports_.find(static_cast<netplus::con*>(&curreq)); if (it != active_imports_.end()) { active_imports_.erase(it); app_.finish_import(false, "client disconnected"); return; } // Clean up any orphaned H2 import sessions on this connection for (auto h2it = h2_imports_.begin(); h2it != h2_imports_.end(); ) { if (h2it->first.conn == &curreq) { h2it = h2_imports_.erase(h2it); app_.finish_import(false, "client disconnected"); return; } else { ++h2it; } } } Loading