MCPcopy
hub / github.com/opentrace/opentrace / clear_database

Function clear_database

agent/src/opentrace_agent/cli/serve.py:580–660  ·  view source on GitHub ↗

POST /api/clear — drop every node and relationship. Used by the UI's Settings → "Clear Database" button in server mode (Fix #11). Closes the live store, removes the underlying LadybugDB files, then opens a fresh empty store and swaps it back in. The atomic file-repla

(request: Request)

Source from the content-addressed store, hash-verified

578 return JSONResponse(dict(active[0]))
579
580 async def clear_database(request: Request) -> JSONResponse:
581 """POST /api/clear — drop every node and relationship.
582
583 Used by the UI's Settings → "Clear Database" button in server
584 mode (Fix #11). Closes the live store, removes the underlying
585 LadybugDB files, then opens a fresh empty store and swaps it
586 back in. The atomic file-replace is simpler and safer than
587 iterating every repo through `delete_repo()` — and matches
588 the spirit of what the user clicked ("delete everything").
589
590 Refuses while an `/api/index-url` job is running because that
591 worker also writes to the on-disk DB; clearing under its feet
592 would corrupt the staging swap.
593 """
594 if db_path is None:
595 return _error(503, "Server was started without --db; clear is unavailable")
596
597 # Atomically reserve exclusivity against index-url: check that no job
598 # is active AND register a sentinel under the SAME lock acquisition.
599 # Without this, a concurrent index-url could pass its own guard
600 # between our check and our unlink, then have its pipeline swap a
601 # staging DB over the files we're deleting (clear-vs-index TOCTOU).
602 # The index-vs-index hole is already closed by index_url's atomic
603 # check-and-insert; this extends the same guard to clear.
604 clear_job_id = uuid.uuid4().hex
605 with index_jobs_lock:
606 active = [jid for jid, st in index_jobs.items() if not st.get("done")]
607 if active:
608 return _error(
609 409,
610 "An index job is currently running — wait for it to finish before clearing the database.",
611 )
612 index_jobs[clear_job_id] = {
613 "jobId": clear_job_id,
614 "kind": "clear",
615 "phase": "clearing",
616 "message": "Clearing database",
617 "done": False,
618 "error": None,
619 "result": None,
620 "startedAt": time.time(),
621 }
622
623 from pathlib import Path as _Path
624
625 try:
626 with store_lock:
627 cur = store_ref["store"]
628 if cur is not None:
629 try:
630 cur.close()
631 except Exception:
632 logger.warning("Failed to close store cleanly before clear", exc_info=True)
633 store_ref["store"] = None
634
635 # Drop the on-disk artifacts. Mirrors what `opentraceai
636 # index` does when it swaps staging into place — same set
637 # of files to remove. Cleared in this order so a partial

Callers

nothing calls this directly

Calls 4

GraphStoreClass · 0.90
_errorFunction · 0.85
getMethod · 0.65
closeMethod · 0.65

Tested by

no test coverage detected