tejasashinde's picture
Integrate HF Bucket storage
4784470
Raw
History Blame Contribute Delete
11.7 kB
from __future__ import annotations
import json
import os
import sqlite3
import threading
from contextlib import contextmanager
from datetime import datetime, timezone
from pathlib import Path
from typing import Sequence
DEFAULT_STORAGE_DIR = Path("/data/hackathon-space-recommender")
def _default_storage_dir() -> Path:
custom = os.getenv("BSQF_STORAGE_DIR", "").strip()
if custom:
candidate = Path(custom).expanduser()
if candidate.is_absolute() and str(candidate).startswith("/data/"):
return candidate
raise RuntimeError("BSQF_STORAGE_DIR must point inside the HF bucket mount under /data/")
return DEFAULT_STORAGE_DIR
STORAGE_DIR = _default_storage_dir()
DB_PATH = STORAGE_DIR / "build_small_quest_finder.sqlite3"
DB_LOCK = threading.RLock()
def _ensure_parent(path: Path) -> None:
if not Path("/data").exists():
raise RuntimeError(
"HF Storage Bucket mount not found at /data. "
"This app is bucket-only and must run inside a Hugging Face Space with the bucket mounted."
)
path.parent.mkdir(parents=True, exist_ok=True)
@contextmanager
def get_connection():
with DB_LOCK:
_ensure_parent(DB_PATH)
conn = sqlite3.connect(
DB_PATH,
timeout=30,
check_same_thread=False,
isolation_level=None,
)
conn.row_factory = sqlite3.Row
conn.execute("PRAGMA busy_timeout = 30000")
conn.execute("PRAGMA foreign_keys = ON")
conn.execute("PRAGMA journal_mode = DELETE")
conn.execute("PRAGMA synchronous = NORMAL")
try:
yield conn
finally:
conn.close()
@contextmanager
def _transaction(conn: sqlite3.Connection):
conn.execute("BEGIN IMMEDIATE")
try:
yield
conn.commit()
except Exception:
conn.rollback()
raise
def init_db() -> None:
with get_connection() as conn:
conn.execute(
"""
CREATE TABLE IF NOT EXISTS llm_cache (
cache_key TEXT PRIMARY KEY,
cache_value TEXT NOT NULL,
updated_at TEXT NOT NULL
)
"""
)
conn.execute(
"""
CREATE TABLE IF NOT EXISTS quest_feedback (
id INTEGER PRIMARY KEY AUTOINCREMENT,
repo_id TEXT NOT NULL,
space_title TEXT NOT NULL,
track TEXT NOT NULL,
question TEXT NOT NULL,
answer TEXT NOT NULL,
source_query TEXT,
owner_session_id TEXT NOT NULL DEFAULT '',
updated_at TEXT NOT NULL DEFAULT '',
deleted_at TEXT,
created_at TEXT NOT NULL
)
"""
)
existing_columns = {row["name"] for row in conn.execute("PRAGMA table_info(quest_feedback)").fetchall()}
if "owner_session_id" not in existing_columns:
conn.execute("ALTER TABLE quest_feedback ADD COLUMN owner_session_id TEXT NOT NULL DEFAULT ''")
if "updated_at" not in existing_columns:
conn.execute("ALTER TABLE quest_feedback ADD COLUMN updated_at TEXT NOT NULL DEFAULT ''")
if "deleted_at" not in existing_columns:
conn.execute("ALTER TABLE quest_feedback ADD COLUMN deleted_at TEXT")
conn.execute(
"""
CREATE TABLE IF NOT EXISTS app_state (
state_key TEXT PRIMARY KEY,
state_value TEXT NOT NULL,
updated_at TEXT NOT NULL
)
"""
)
conn.execute(
"""
CREATE TABLE IF NOT EXISTS space_metrics (
repo_id TEXT PRIMARY KEY,
likes INTEGER NOT NULL DEFAULT 0,
synced_at TEXT NOT NULL DEFAULT '',
updated_at TEXT NOT NULL
)
"""
)
conn.commit()
def now_iso() -> str:
return datetime.now(timezone.utc).isoformat()
def cache_get(cache_key: str) -> str | None:
with get_connection() as conn:
row = conn.execute(
"SELECT cache_value FROM llm_cache WHERE cache_key = ?",
(cache_key,),
).fetchone()
return row["cache_value"] if row else None
def cache_set(cache_key: str, cache_value: str) -> None:
with get_connection() as conn:
with _transaction(conn):
conn.execute(
"""
INSERT INTO llm_cache (cache_key, cache_value, updated_at)
VALUES (?, ?, ?)
ON CONFLICT(cache_key) DO UPDATE SET
cache_value = excluded.cache_value,
updated_at = excluded.updated_at
""",
(cache_key, cache_value, now_iso()),
)
def state_get(state_key: str) -> str | None:
with get_connection() as conn:
row = conn.execute(
"SELECT state_value FROM app_state WHERE state_key = ?",
(state_key,),
).fetchone()
return row["state_value"] if row else None
def state_set(state_key: str, state_value: str) -> None:
with get_connection() as conn:
with _transaction(conn):
conn.execute(
"""
INSERT INTO app_state (state_key, state_value, updated_at)
VALUES (?, ?, ?)
ON CONFLICT(state_key) DO UPDATE SET
state_value = excluded.state_value,
updated_at = excluded.updated_at
""",
(state_key, state_value, now_iso()),
)
def save_feedback(
repo_id: str,
space_title: str,
track: str,
question: str,
answer: str,
source_query: str = "",
owner_session_id: str = "",
) -> dict:
created_at = now_iso()
record = {
"repo_id": repo_id,
"space_title": space_title,
"track": track,
"question": question,
"answer": answer,
"source_query": source_query,
"owner_session_id": owner_session_id,
"created_at": created_at,
"updated_at": created_at,
"deleted_at": None,
}
with get_connection() as conn:
with _transaction(conn):
cursor = conn.execute(
"""
INSERT INTO quest_feedback (repo_id, space_title, track, question, answer, source_query, owner_session_id, updated_at, deleted_at, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
repo_id,
space_title,
track,
question,
answer,
source_query,
owner_session_id,
record["updated_at"],
None,
record["created_at"],
),
)
record["id"] = int(cursor.lastrowid or 0)
return record
def get_recent_feedback(limit: int = 10, repo_id: str | None = None) -> list[dict]:
query = """
SELECT id, repo_id, space_title, track, question, answer, source_query,
owner_session_id, updated_at, deleted_at, created_at
FROM quest_feedback
WHERE COALESCE(deleted_at, '') = ''
"""
params: list[object] = []
if repo_id:
query += " AND repo_id = ?"
params.append(repo_id)
query += " ORDER BY id DESC LIMIT ?"
params.append(limit)
try:
with get_connection() as conn:
db_rows = conn.execute(query, tuple(params)).fetchall()
except Exception:
return []
return list(reversed([dict(row) for row in db_rows]))
def get_space_metrics(repo_ids: Sequence[str] | None = None) -> dict[str, dict]:
query = "SELECT repo_id, likes, synced_at, updated_at FROM space_metrics"
params: tuple[object, ...] = ()
if repo_ids is not None:
cleaned = [str(repo_id).strip() for repo_id in repo_ids if str(repo_id).strip()]
if not cleaned:
return {}
placeholders = ",".join("?" for _ in cleaned)
query += f" WHERE repo_id IN ({placeholders})"
params = tuple(cleaned)
try:
with get_connection() as conn:
rows = conn.execute(query, params).fetchall()
except Exception:
return {}
return {str(row["repo_id"]): dict(row) for row in rows}
def upsert_space_metrics(rows: Sequence[dict]) -> None:
cleaned_rows: list[tuple[str, int, str, str]] = []
for row in rows:
repo_id = str(row.get("repo_id", "")).strip()
if not repo_id:
continue
likes = int(row.get("likes", 0) or 0)
synced_at = str(row.get("synced_at", "") or now_iso())
updated_at = str(row.get("updated_at", "") or synced_at)
cleaned_rows.append((repo_id, likes, synced_at, updated_at))
if not cleaned_rows:
return
with get_connection() as conn:
with _transaction(conn):
conn.executemany(
"""
INSERT INTO space_metrics (repo_id, likes, synced_at, updated_at)
VALUES (?, ?, ?, ?)
ON CONFLICT(repo_id) DO UPDATE SET
likes = excluded.likes,
synced_at = excluded.synced_at,
updated_at = excluded.updated_at
""",
cleaned_rows,
)
def update_feedback_comment(comment_id: int, owner_session_id: str, answer: str) -> bool:
answer = (answer or "").strip()
owner_session_id = (owner_session_id or "").strip()
if not comment_id or not answer or not owner_session_id:
return False
updated_at = now_iso()
with get_connection() as conn:
with _transaction(conn):
row = conn.execute(
"""
SELECT id FROM quest_feedback
WHERE id = ? AND owner_session_id = ? AND COALESCE(deleted_at, '') = ''
""",
(comment_id, owner_session_id),
).fetchone()
if not row:
return False
conn.execute(
"""
UPDATE quest_feedback
SET answer = ?, updated_at = ?
WHERE id = ? AND owner_session_id = ? AND COALESCE(deleted_at, '') = ''
""",
(answer, updated_at, comment_id, owner_session_id),
)
return True
def delete_feedback_comment(comment_id: int, owner_session_id: str) -> bool:
owner_session_id = (owner_session_id or "").strip()
if not comment_id or not owner_session_id:
return False
deleted_at = now_iso()
with get_connection() as conn:
with _transaction(conn):
row = conn.execute(
"""
SELECT id FROM quest_feedback
WHERE id = ? AND owner_session_id = ? AND COALESCE(deleted_at, '') = ''
""",
(comment_id, owner_session_id),
).fetchone()
if not row:
return False
conn.execute(
"""
UPDATE quest_feedback
SET deleted_at = ?, updated_at = ?
WHERE id = ? AND owner_session_id = ? AND COALESCE(deleted_at, '') = ''
""",
(deleted_at, deleted_at, comment_id, owner_session_id),
)
return True
def dump_json(table_name: str) -> str:
if table_name == "quest_feedback":
rows = get_recent_feedback(limit=100000)
else:
rows = []
return json.dumps(rows, ensure_ascii=False, indent=2)