Release 2026.08.02-1
SQLite replaces Postgres, and two fixes from using the thing. - The database is a file under ./storage instead of a second container. Ten members never needed a database server, and the driver is pure Go, so the build stays CGO_ENABLED=0 and the dependency count is unchanged. One bind mount is now the whole backup: no pgdata, no healthcheck-gated depends_on, no startup retry loop. Timestamps are UTC text, idle_ttl is seconds, the divisive/unified boards carry their own stddev, and foreign keys are on by pragma. Tests get a database file each and run without any setup - Invites are copied, not clicked. An invite is something to send, and the anchor opened the join form in the admin's own browser - Feedback asks for more than faults: the footer reads "Ongelmia? Ideoita? Palautetta?" and the page behind it invites ideas rather than only bugs - Kuuntele YouTubessa opens in a new tab, so a half-typed review survives it
This commit is contained in:
+48
-44
@@ -1,52 +1,56 @@
|
||||
-- Timestamps are declared `timestamp` and hold UTC 'YYYY-MM-DD HH:MM:SS': the declared type is what
|
||||
-- makes the driver hand them back as time.Time, and a fixed-width UTC string is what makes
|
||||
-- `order by created_at` and `expires_at > datetime('now')` mean what they say.
|
||||
|
||||
create table users (
|
||||
id bigserial primary key,
|
||||
name text not null,
|
||||
email text not null unique,
|
||||
password_hash text not null,
|
||||
id integer primary key autoincrement,
|
||||
name text not null,
|
||||
email text not null unique,
|
||||
password_hash text not null,
|
||||
avatar text,
|
||||
banned boolean not null default false,
|
||||
created_at timestamptz not null default now()
|
||||
banned integer not null default 0,
|
||||
created_at timestamp not null default (datetime('now'))
|
||||
);
|
||||
|
||||
create table sessions (
|
||||
token text primary key,
|
||||
user_id bigint not null references users (id) on delete cascade,
|
||||
idle_ttl interval not null,
|
||||
expires_at timestamptz not null,
|
||||
created_at timestamptz not null default now()
|
||||
token text primary key,
|
||||
user_id integer not null references users (id) on delete cascade,
|
||||
idle_ttl integer not null, -- seconds; SQLite has no interval type
|
||||
expires_at timestamp not null,
|
||||
created_at timestamp not null default (datetime('now'))
|
||||
);
|
||||
|
||||
create index on sessions (user_id);
|
||||
create index sessions_user on sessions (user_id);
|
||||
|
||||
create table invites (
|
||||
id bigserial primary key,
|
||||
code text not null unique,
|
||||
is_valid boolean not null default true,
|
||||
created_at timestamptz not null default now()
|
||||
id integer primary key autoincrement,
|
||||
code text not null unique,
|
||||
is_valid integer not null default 1,
|
||||
created_at timestamp not null default (datetime('now'))
|
||||
);
|
||||
|
||||
create table songs (
|
||||
id bigserial primary key,
|
||||
title text not null,
|
||||
artist text not null,
|
||||
genre text not null,
|
||||
id integer primary key autoincrement,
|
||||
title text not null,
|
||||
artist text not null,
|
||||
genre text not null,
|
||||
description text,
|
||||
-- LRC or plain text, told apart by whether the first line starts with '['. Not covered by the
|
||||
-- lock: nobody reviewed the lyrics.
|
||||
lyrics text,
|
||||
audio_file text not null,
|
||||
duration_seconds integer not null,
|
||||
audio_file text not null,
|
||||
duration_seconds integer not null,
|
||||
source_url text,
|
||||
submitted_by bigint not null references users (id),
|
||||
created_at timestamptz not null default now()
|
||||
submitted_by integer not null references users (id),
|
||||
created_at timestamp not null default (datetime('now'))
|
||||
);
|
||||
|
||||
create index on songs (created_at desc);
|
||||
create index songs_created_at on songs (created_at desc);
|
||||
|
||||
create table submissions (
|
||||
id bigserial primary key,
|
||||
user_id bigint not null references users (id) on delete cascade,
|
||||
status text not null default 'queued',
|
||||
id integer primary key autoincrement,
|
||||
user_id integer not null references users (id) on delete cascade,
|
||||
status text not null default 'queued',
|
||||
status_msg text,
|
||||
source_url text,
|
||||
tmp_path text,
|
||||
@@ -55,37 +59,37 @@ create table submissions (
|
||||
genre text,
|
||||
description text,
|
||||
lyrics text,
|
||||
created_at timestamptz not null default now(),
|
||||
created_at timestamp not null default (datetime('now')),
|
||||
constraint submissions_status check (
|
||||
status in ('queued', 'downloading', 'converting', 'ready', 'failed')
|
||||
)
|
||||
);
|
||||
|
||||
-- The submission quota (5 per rolling 24h, failures excluded) reads this.
|
||||
create index on submissions (user_id, created_at desc);
|
||||
create index submissions_user_created on submissions (user_id, created_at desc);
|
||||
|
||||
create table reviews (
|
||||
id bigserial primary key,
|
||||
song_id bigint not null references songs (id) on delete cascade,
|
||||
reviewer_id bigint not null references users (id),
|
||||
score integer not null check (score between 1 and 100),
|
||||
text text not null,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now(),
|
||||
id integer primary key autoincrement,
|
||||
song_id integer not null references songs (id) on delete cascade,
|
||||
reviewer_id integer not null references users (id),
|
||||
score integer not null check (score between 1 and 100),
|
||||
text text not null,
|
||||
created_at timestamp not null default (datetime('now')),
|
||||
updated_at timestamp not null default (datetime('now')),
|
||||
unique (song_id, reviewer_id)
|
||||
);
|
||||
|
||||
create index on reviews (song_id);
|
||||
create index reviews_song on reviews (song_id);
|
||||
|
||||
-- The queue asks "songs this member has not reviewed" — that lookup is by reviewer.
|
||||
create index on reviews (reviewer_id, song_id);
|
||||
create index reviews_reviewer_song on reviews (reviewer_id, song_id);
|
||||
|
||||
create table reports (
|
||||
id bigserial primary key,
|
||||
user_id bigint not null references users (id) on delete cascade,
|
||||
body text not null,
|
||||
id integer primary key autoincrement,
|
||||
user_id integer not null references users (id) on delete cascade,
|
||||
body text not null,
|
||||
page text,
|
||||
user_agent text,
|
||||
resolved_at timestamptz,
|
||||
created_at timestamptz not null default now()
|
||||
resolved_at timestamp,
|
||||
created_at timestamp not null default (datetime('now'))
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user