check / check (push) Successful in 10m10s
"Storage" names the cache directories pixa uses (cache/sources, cache/metadata, cache/variants) and how files are named in each; the schema comments name the same paths, and the output_content comment says the table is not written. Routes and the signature section give one list of output formats, jpg and original included, and say how those two are signed. The TLS sentence names allow_http as its exception. "Metrics" says what exists: generic HTTP and Go runtime metrics at /metrics, measured and served only when the metrics username and password are set. Model: opus-5-5
114 lines
4.6 KiB
SQL
114 lines
4.6 KiB
SQL
-- Migration 001: Initial schema
|
|
-- Creates all tables for the pixa caching image proxy
|
|
|
|
-- Source content blobs
|
|
-- Files stored at: cache/sources/<ab>/<cd>/<sha256>
|
|
-- last_accessed_at is NULL until the first LRU touch; eviction falls
|
|
-- back to fetched_at for rows that have never been touched.
|
|
CREATE TABLE IF NOT EXISTS source_content (
|
|
content_hash TEXT PRIMARY KEY,
|
|
content_type TEXT NOT NULL,
|
|
size_bytes INTEGER NOT NULL,
|
|
fetched_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
last_accessed_at DATETIME
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_source_content_last_accessed
|
|
ON source_content(last_accessed_at);
|
|
|
|
-- Source URL metadata - maps URLs to content hashes
|
|
-- JSON stored at: cache/metadata/<hostname>/<path_hash>.json
|
|
CREATE TABLE IF NOT EXISTS source_metadata (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
source_host TEXT NOT NULL,
|
|
source_path TEXT NOT NULL,
|
|
source_query TEXT NOT NULL DEFAULT '',
|
|
path_hash TEXT NOT NULL,
|
|
content_hash TEXT,
|
|
status_code INTEGER NOT NULL,
|
|
content_type TEXT,
|
|
response_headers TEXT,
|
|
fetched_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
expires_at DATETIME,
|
|
etag TEXT,
|
|
last_modified TEXT,
|
|
UNIQUE(source_host, source_path, source_query),
|
|
FOREIGN KEY (content_hash) REFERENCES source_content(content_hash)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_source_meta_host ON source_metadata(source_host);
|
|
CREATE INDEX IF NOT EXISTS idx_source_meta_path_hash ON source_metadata(path_hash);
|
|
CREATE INDEX IF NOT EXISTS idx_source_meta_expires ON source_metadata(expires_at);
|
|
CREATE INDEX IF NOT EXISTS idx_source_meta_content_hash ON source_metadata(content_hash);
|
|
|
|
-- Processed variant blobs
|
|
-- Files stored at: cache/variants/<ab>/<cd>/<cache_key> (plus a .meta
|
|
-- sidecar with the content type). Tracked here (like source content
|
|
-- blobs above) so total cache usage can be computed with a SUM query,
|
|
-- never a directory scan, and so LRU eviction has a timestamp to order
|
|
-- on.
|
|
CREATE TABLE IF NOT EXISTS variant_content (
|
|
cache_key TEXT PRIMARY KEY,
|
|
size_bytes INTEGER NOT NULL,
|
|
content_type TEXT NOT NULL,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
last_accessed_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_variant_content_last_accessed
|
|
ON variant_content(last_accessed_at);
|
|
|
|
-- Output/transformed content blobs
|
|
-- Not written: transformed images are stored in cache/variants and
|
|
-- tracked in variant_content above.
|
|
CREATE TABLE IF NOT EXISTS output_content (
|
|
content_hash TEXT PRIMARY KEY,
|
|
content_type TEXT NOT NULL,
|
|
size_bytes INTEGER NOT NULL,
|
|
fetched_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- Request cache - maps full request params to output content
|
|
CREATE TABLE IF NOT EXISTS request_cache (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
cache_key TEXT NOT NULL UNIQUE,
|
|
source_metadata_id INTEGER NOT NULL,
|
|
output_hash TEXT NOT NULL,
|
|
width INTEGER NOT NULL,
|
|
height INTEGER NOT NULL,
|
|
format TEXT NOT NULL,
|
|
quality INTEGER NOT NULL DEFAULT 85,
|
|
fit_mode TEXT NOT NULL DEFAULT 'cover',
|
|
fetched_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
access_count INTEGER NOT NULL DEFAULT 1,
|
|
FOREIGN KEY (source_metadata_id) REFERENCES source_metadata(id),
|
|
FOREIGN KEY (output_hash) REFERENCES output_content(content_hash)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_request_cache_key ON request_cache(cache_key);
|
|
CREATE INDEX IF NOT EXISTS idx_request_cache_source ON request_cache(source_metadata_id);
|
|
CREATE INDEX IF NOT EXISTS idx_request_cache_output ON request_cache(output_hash);
|
|
CREATE INDEX IF NOT EXISTS idx_request_cache_fetched ON request_cache(fetched_at);
|
|
|
|
-- Negative cache for failed fetches (404s, timeouts, etc.)
|
|
CREATE TABLE IF NOT EXISTS negative_cache (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
source_host TEXT NOT NULL,
|
|
source_path TEXT NOT NULL,
|
|
source_query TEXT NOT NULL DEFAULT '',
|
|
status_code INTEGER NOT NULL,
|
|
error_message TEXT,
|
|
fetched_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
expires_at DATETIME NOT NULL,
|
|
UNIQUE(source_host, source_path, source_query)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_negative_cache_expires ON negative_cache(expires_at);
|
|
|
|
-- Cache statistics for monitoring
|
|
CREATE TABLE IF NOT EXISTS cache_stats (
|
|
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
hit_count INTEGER NOT NULL DEFAULT 0,
|
|
miss_count INTEGER NOT NULL DEFAULT 0,
|
|
upstream_fetch_count INTEGER NOT NULL DEFAULT 0,
|
|
upstream_fetch_bytes INTEGER NOT NULL DEFAULT 0,
|
|
transform_count INTEGER NOT NULL DEFAULT 0,
|
|
last_updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
INSERT OR IGNORE INTO cache_stats (id) VALUES (1);
|