diff --git a/pipekit/repo.py b/pipekit/repo.py index 297eacc..138f37b 100644 --- a/pipekit/repo.py +++ b/pipekit/repo.py @@ -177,6 +177,26 @@ def list_modules() -> list[dict]: return [dict(r) for r in c.execute("SELECT * FROM module ORDER BY name")] +class ModuleRunning(RuntimeError): + """Raised by delete_module when the module is currently running.""" + + +def delete_module(module_id: int) -> bool: + """Delete a module and its run_log history. Watermarks, hooks, and + group_member rows cascade via FK. Refuses to delete if the module + is currently running.""" + with db.connect() as c: + row = c.execute("SELECT running FROM module WHERE id=?", + (module_id,)).fetchone() + if row is None: + return False + if row[0]: + raise ModuleRunning(f"module id={module_id} is currently running") + c.execute("DELETE FROM run_log WHERE module_id=?", (module_id,)) + cur = c.execute("DELETE FROM module WHERE id=?", (module_id,)) + return cur.rowcount > 0 + + def set_next_resolved_query(module_id: int, sql: str) -> None: with db.connect() as c: c.execute("UPDATE module SET next_resolved_query=?, " diff --git a/pipekit/web/app.py b/pipekit/web/app.py index 4cd03d8..f252dfb 100644 --- a/pipekit/web/app.py +++ b/pipekit/web/app.py @@ -131,6 +131,17 @@ def module_detail(request: Request, module_id: int): ) +@_router.post("/modules/{module_id}/delete") +def module_delete(module_id: int): + if repo.get_module(module_id) is None: + raise HTTPException(404, f"module id={module_id} not found") + try: + repo.delete_module(module_id) + except repo.ModuleRunning as e: + raise HTTPException(409, str(e)) + return RedirectResponse(url="/", status_code=303) + + @_router.post("/modules/{module_id}/run") async def module_run_action(module_id: int, request: Request): form = await request.form() @@ -293,6 +304,10 @@ async def wizard_create(request: Request): dest_description = (form.get("dest_description") or "").strip() or None picked = form.getlist("col") + if repo.get_module_by_name(module_name) is not None: + raise HTTPException( + 409, f"module name {module_name!r} already exists — pick another") + src_conn = repo.get_connection(source_connection_id) if src_conn is None: raise HTTPException(404, f"connection id={source_connection_id} not found") diff --git a/pipekit/web/templates/module_detail.html b/pipekit/web/templates/module_detail.html index 8ee2e4f..b039af8 100644 --- a/pipekit/web/templates/module_detail.html +++ b/pipekit/web/templates/module_detail.html @@ -19,6 +19,10 @@ +
+ +