feat: harden storyforge production baseline
This commit is contained in:
@@ -1,11 +1,16 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sqlite3
|
||||
from contextlib import contextmanager
|
||||
from pathlib import Path
|
||||
from typing import Any, Iterator
|
||||
|
||||
|
||||
SQLITE_BUSY_TIMEOUT_MS = int(os.getenv("SQLITE_BUSY_TIMEOUT_MS", "5000"))
|
||||
SQLITE_CONNECT_TIMEOUT_SEC = float(os.getenv("SQLITE_CONNECT_TIMEOUT_SEC", "30"))
|
||||
|
||||
|
||||
def utc_now() -> str:
|
||||
from datetime import datetime, timezone
|
||||
|
||||
@@ -22,9 +27,14 @@ class Database:
|
||||
self.path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
def connect(self) -> sqlite3.Connection:
|
||||
conn = sqlite3.connect(self.path)
|
||||
conn = sqlite3.connect(self.path, timeout=SQLITE_CONNECT_TIMEOUT_SEC)
|
||||
conn.row_factory = dict_factory
|
||||
conn.execute("PRAGMA journal_mode = WAL")
|
||||
conn.execute("PRAGMA synchronous = NORMAL")
|
||||
conn.execute(f"PRAGMA busy_timeout = {SQLITE_BUSY_TIMEOUT_MS}")
|
||||
conn.execute("PRAGMA foreign_keys = ON")
|
||||
conn.execute("PRAGMA temp_store = MEMORY")
|
||||
conn.execute("PRAGMA wal_autocheckpoint = 1000")
|
||||
return conn
|
||||
|
||||
@contextmanager
|
||||
@@ -265,6 +275,41 @@ class Database:
|
||||
FOREIGN KEY(source_id) REFERENCES live_recorder_sources(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS tenant_quota_profiles (
|
||||
id TEXT PRIMARY KEY,
|
||||
user_id TEXT NOT NULL,
|
||||
project_id TEXT NOT NULL DEFAULT '',
|
||||
monthly_budget_cents INTEGER NOT NULL DEFAULT 0,
|
||||
storage_limit_bytes INTEGER NOT NULL DEFAULT 0,
|
||||
analysis_quota INTEGER NOT NULL DEFAULT 0,
|
||||
copy_quota INTEGER NOT NULL DEFAULT 0,
|
||||
ai_video_quota INTEGER NOT NULL DEFAULT 0,
|
||||
real_cut_quota INTEGER NOT NULL DEFAULT 0,
|
||||
recorder_quota INTEGER NOT NULL DEFAULT 0,
|
||||
enabled INTEGER NOT NULL DEFAULT 1,
|
||||
config_json TEXT NOT NULL DEFAULT '{}',
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL,
|
||||
UNIQUE(user_id, project_id),
|
||||
FOREIGN KEY(user_id) REFERENCES accounts(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS tenant_usage_ledger (
|
||||
id TEXT PRIMARY KEY,
|
||||
user_id TEXT NOT NULL,
|
||||
project_id TEXT NOT NULL DEFAULT '',
|
||||
category TEXT NOT NULL,
|
||||
quantity INTEGER NOT NULL DEFAULT 1,
|
||||
cost_cents INTEGER NOT NULL DEFAULT 0,
|
||||
reference_type TEXT NOT NULL DEFAULT '',
|
||||
reference_id TEXT NOT NULL DEFAULT '',
|
||||
details_json TEXT NOT NULL DEFAULT '{}',
|
||||
created_at TEXT NOT NULL,
|
||||
FOREIGN KEY(user_id) REFERENCES accounts(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS job_events (
|
||||
id TEXT PRIMARY KEY,
|
||||
job_id TEXT NOT NULL,
|
||||
|
||||
Reference in New Issue
Block a user