Some checks failed
CI / check (push) Failing after 10s
sqlx's query!/query_as! macros only check raw SQL strings against the live schema; Diesel's table!-derived DSL type-checks query structure itself at compile time. SQLite has no native async driver, so diesel-async wraps a blocking SqliteConnection via SyncConnectionWrapper, pooled with bb8. Migrations move from sqlx's single-file-per-migration format to Diesel's up.sql/down.sql pairs, run transactionally via diesel_migrations against a throwaway sync connection at boot (MigrationHarness needs a sync Connection), giving revertable migrations that sqlx::migrate! doesn't support. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
60 lines
2 KiB
SQL
60 lines
2 KiB
SQL
CREATE TABLE feeds (
|
|
id TEXT PRIMARY KEY,
|
|
url TEXT NOT NULL UNIQUE,
|
|
title TEXT NOT NULL,
|
|
last_fetched_at TEXT
|
|
);
|
|
|
|
CREATE TABLE articles (
|
|
id TEXT PRIMARY KEY,
|
|
feed_id TEXT NOT NULL REFERENCES feeds(id),
|
|
url TEXT NOT NULL UNIQUE,
|
|
title TEXT NOT NULL,
|
|
summary TEXT NOT NULL,
|
|
content TEXT,
|
|
published_at TEXT,
|
|
fetched_at TEXT NOT NULL,
|
|
topics TEXT NOT NULL DEFAULT '[]', -- JSON array of strings
|
|
embedding TEXT, -- JSON array of floats
|
|
embedding_score REAL,
|
|
llm_score REAL,
|
|
llm_rationale TEXT,
|
|
final_score REAL,
|
|
estimated_read_seconds INTEGER
|
|
);
|
|
|
|
CREATE INDEX idx_articles_feed_id ON articles(feed_id);
|
|
CREATE INDEX idx_articles_final_score ON articles(final_score);
|
|
|
|
-- Append-only interaction log. Affinities and any future scoring model are
|
|
-- derived from this; it is never mutated except to backfill dwell_seconds
|
|
-- once known.
|
|
CREATE TABLE reading_events (
|
|
id TEXT PRIMARY KEY,
|
|
article_id TEXT NOT NULL REFERENCES articles(id),
|
|
occurred_at TEXT NOT NULL,
|
|
outcome TEXT NOT NULL, -- 'impression' | 'opened' | 'starred' | 'dismissed'
|
|
dwell_seconds INTEGER
|
|
);
|
|
|
|
CREATE INDEX idx_reading_events_article_id ON reading_events(article_id);
|
|
|
|
-- Single-row-per-user table (multi-user support can add a user_id column
|
|
-- later); holds the current TopicAffinities snapshot as JSON so it doesn't
|
|
-- need to be recomputed from the full event log on every request. Rebuild
|
|
-- from reading_events at any time if the scoring model changes.
|
|
CREATE TABLE topic_affinities (
|
|
user_id TEXT PRIMARY KEY DEFAULT 'default',
|
|
affinities TEXT NOT NULL DEFAULT '{}',
|
|
updated_at TEXT NOT NULL
|
|
);
|
|
|
|
-- Free-text preferences the user writes explicitly (e.g. "I care about
|
|
-- distributed systems and Rust internals, not general AI news"), embedded
|
|
-- once and used as the anchor for the embedding-similarity stage.
|
|
CREATE TABLE preferences (
|
|
user_id TEXT PRIMARY KEY DEFAULT 'default',
|
|
description TEXT NOT NULL DEFAULT '',
|
|
embedding TEXT,
|
|
updated_at TEXT NOT NULL
|
|
);
|