feat: replace Cancel with Pause/Resume — survives server restarts
- scanner.py: replace cancel_requested with pause_requested throughout; pause during walk drains in-flight futures gracefully then saves state; phash phase processes in 500-image chunks with pause check between each; _save_pause_state() persists files_indexed/phashes_done/last_phase to DB; init_db() already detects killed-mid-scan (running→paused) on startup - main.py: add POST /api/scan/pause and POST /api/scan/resume endpoints; /api/scan/cancel kept as alias; scan_status now returns folder_path, files_indexed, phashes_done; scan_reset clears all new fields - index.html: "Cancel" → "⏸ Pause" button; new #paused-area banner shows folder, files indexed, phashes done with "▶ Resume" and "Full reset" buttons; updateScanUI handles paused status; pauseScan()/resumeScan() JS functions added; chip gains .paused amber style Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
83
app/main.py
83
app/main.py
@@ -105,11 +105,14 @@ def scan_start(body: ScanStartBody):
|
||||
sc.scan_state.update(
|
||||
scan_id=scan_id,
|
||||
status="running",
|
||||
phase="discovery",
|
||||
phase="takeout",
|
||||
progress=0,
|
||||
total=0,
|
||||
message="Starting...",
|
||||
cancel_requested=False,
|
||||
pause_requested=False,
|
||||
files_indexed=0,
|
||||
phashes_done=0,
|
||||
folder_path=body.folder_path,
|
||||
stats={},
|
||||
)
|
||||
|
||||
@@ -146,24 +149,76 @@ def scan_status():
|
||||
con.close()
|
||||
|
||||
return {
|
||||
"scan_id": state["scan_id"],
|
||||
"status": state["status"],
|
||||
"phase": state["phase"],
|
||||
"progress": state["progress"],
|
||||
"total": state["total"],
|
||||
"message": state["message"],
|
||||
"stats": stats,
|
||||
"scan_id": state["scan_id"],
|
||||
"status": state["status"],
|
||||
"phase": state["phase"],
|
||||
"progress": state["progress"],
|
||||
"total": state["total"],
|
||||
"message": state["message"],
|
||||
"folder_path": state.get("folder_path"),
|
||||
"files_indexed": state.get("files_indexed", 0),
|
||||
"phashes_done": state.get("phashes_done", 0),
|
||||
"stats": stats,
|
||||
}
|
||||
|
||||
|
||||
@app.post("/api/scan/cancel")
|
||||
def scan_cancel():
|
||||
@app.post("/api/scan/pause")
|
||||
def scan_pause():
|
||||
if sc.scan_state["status"] != "running":
|
||||
raise HTTPException(400, "No scan is currently running")
|
||||
sc.scan_state["cancel_requested"] = True
|
||||
sc.scan_state["pause_requested"] = True
|
||||
return {"success": True}
|
||||
|
||||
|
||||
# Keep /cancel as an alias so any lingering clients still work
|
||||
@app.post("/api/scan/cancel")
|
||||
def scan_cancel():
|
||||
return scan_pause()
|
||||
|
||||
|
||||
@app.post("/api/scan/resume")
|
||||
def scan_resume():
|
||||
if sc.scan_state["status"] != "paused":
|
||||
raise HTTPException(400, "No paused scan to resume")
|
||||
|
||||
folder_path = sc.scan_state.get("folder_path")
|
||||
if not folder_path:
|
||||
raise HTTPException(400, "No folder path saved — please start a new scan")
|
||||
|
||||
con = get_db()
|
||||
cur = con.cursor()
|
||||
cur.execute(
|
||||
"INSERT INTO scans (folder_path, status) VALUES (?, 'running')",
|
||||
(folder_path,),
|
||||
)
|
||||
scan_id = cur.lastrowid
|
||||
con.commit()
|
||||
con.close()
|
||||
|
||||
sc.scan_state.update(
|
||||
scan_id=scan_id,
|
||||
status="running",
|
||||
phase="takeout",
|
||||
progress=0,
|
||||
total=0,
|
||||
message="Resuming scan...",
|
||||
pause_requested=False,
|
||||
files_indexed=0,
|
||||
phashes_done=0,
|
||||
folder_path=folder_path,
|
||||
stats={},
|
||||
)
|
||||
|
||||
thread = threading.Thread(
|
||||
target=sc.run_scan,
|
||||
args=(folder_path, scan_id, "incremental"),
|
||||
daemon=True,
|
||||
)
|
||||
thread.start()
|
||||
|
||||
return {"scan_id": scan_id}
|
||||
|
||||
|
||||
@app.delete("/api/scan/reset")
|
||||
def scan_reset(confirm: str = Query("")):
|
||||
if confirm != "RESET":
|
||||
@@ -178,7 +233,9 @@ def scan_reset(confirm: str = Query("")):
|
||||
con.close()
|
||||
sc.scan_state.update(
|
||||
scan_id=None, status="idle", phase="idle",
|
||||
progress=0, total=0, message="", stats={},
|
||||
progress=0, total=0, message="",
|
||||
pause_requested=False, files_indexed=0,
|
||||
phashes_done=0, folder_path=None, stats={},
|
||||
)
|
||||
return {"success": True}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user