Add async pipeline with progress monitoring, resumability, and result transparency
Pipeline engine rewritten with combo-first loop: each combination is processed through all requested passes before moving to the next, with incremental DB saves after every step (crash-safe). Blocked combos now get result rows so they appear in the results page with constraint violation reasons. New pipeline_runs table tracks run lifecycle (pending/running/completed/failed/ cancelled). Web route launches pipeline in a background thread with its own DB connection. HTMX polling partial shows live progress with per-pass breakdown. Also: status guard prevents reviewed->scored downgrade, save_combination loads existing status on dedup for correct resume, per-metric scores show domain bounds + units + position bars, ensure_metric backfills units on existing rows. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -40,18 +40,8 @@ def entity_new():
|
||||
dimensions=repo.list_dimensions())
|
||||
|
||||
|
||||
@bp.route("/<int:entity_id>")
|
||||
@bp.route("/<int:entity_id>", methods=["GET", "POST"])
|
||||
def entity_detail(entity_id: int):
|
||||
repo = get_repo()
|
||||
entity = repo.get_entity(entity_id)
|
||||
if not entity:
|
||||
flash("Entity not found.", "error")
|
||||
return redirect(url_for("entities.entity_list"))
|
||||
return render_template("entities/detail.html", entity=entity)
|
||||
|
||||
|
||||
@bp.route("/<int:entity_id>/edit", methods=["GET", "POST"])
|
||||
def entity_edit(entity_id: int):
|
||||
repo = get_repo()
|
||||
entity = repo.get_entity(entity_id)
|
||||
if not entity:
|
||||
@@ -62,13 +52,17 @@ def entity_edit(entity_id: int):
|
||||
description = request.form.get("description", "").strip()
|
||||
if not name:
|
||||
flash("Name is required.", "error")
|
||||
return render_template("entities/form.html", entity=entity,
|
||||
dimensions=repo.list_dimensions())
|
||||
repo.update_entity(entity_id, name, description)
|
||||
flash(f"Entity '{name}' updated.", "success")
|
||||
return redirect(url_for("entities.entity_detail", entity_id=entity_id))
|
||||
return render_template("entities/form.html", entity=entity,
|
||||
dimensions=repo.list_dimensions())
|
||||
else:
|
||||
repo.update_entity(entity_id, name, description)
|
||||
flash(f"Entity '{name}' updated.", "success")
|
||||
entity = repo.get_entity(entity_id)
|
||||
return render_template("entities/detail.html", entity=entity)
|
||||
|
||||
|
||||
@bp.route("/<int:entity_id>/edit")
|
||||
def entity_edit(entity_id: int):
|
||||
"""Legacy route — redirect to detail page."""
|
||||
return redirect(url_for("entities.entity_detail", entity_id=entity_id))
|
||||
|
||||
|
||||
@bp.route("/<int:entity_id>/delete", methods=["POST"])
|
||||
|
||||
Reference in New Issue
Block a user