bootstrap rust services, auth, and compose stack
This commit is contained in:
89
infra/docker-compose.yml
Normal file
89
infra/docker-compose.yml
Normal file
@@ -0,0 +1,89 @@
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
environment:
|
||||
POSTGRES_DB: stripstream
|
||||
POSTGRES_USER: stripstream
|
||||
POSTGRES_PASSWORD: stripstream
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U stripstream -d stripstream"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
meilisearch:
|
||||
image: getmeili/meilisearch:v1.12
|
||||
environment:
|
||||
MEILI_MASTER_KEY: ${MEILI_MASTER_KEY:-change-me}
|
||||
ports:
|
||||
- "7700:7700"
|
||||
volumes:
|
||||
- meili_data:/meili_data
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-q", "-O", "-", "http://127.0.0.1:7700/health"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
api:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: apps/api/Dockerfile
|
||||
env_file:
|
||||
- ../.env
|
||||
ports:
|
||||
- "8080:8080"
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
meilisearch:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-q", "-O", "-", "http://127.0.0.1:8080/health"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
indexer:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: apps/indexer/Dockerfile
|
||||
env_file:
|
||||
- ../.env
|
||||
ports:
|
||||
- "8081:8081"
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
meilisearch:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-q", "-O", "-", "http://127.0.0.1:8081/health"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
admin-ui:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: apps/admin-ui/Dockerfile
|
||||
env_file:
|
||||
- ../.env
|
||||
ports:
|
||||
- "8082:8082"
|
||||
depends_on:
|
||||
api:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-q", "-O", "-", "http://127.0.0.1:8082/health"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
meili_data:
|
||||
67
infra/migrations/0001_init.sql
Normal file
67
infra/migrations/0001_init.sql
Normal file
@@ -0,0 +1,67 @@
|
||||
CREATE TABLE IF NOT EXISTS libraries (
|
||||
id UUID PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
root_path TEXT NOT NULL UNIQUE,
|
||||
enabled BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS books (
|
||||
id UUID PRIMARY KEY,
|
||||
library_id UUID NOT NULL REFERENCES libraries(id) ON DELETE CASCADE,
|
||||
kind TEXT NOT NULL CHECK (kind IN ('ebook', 'comic', 'bd')),
|
||||
title TEXT NOT NULL,
|
||||
author TEXT,
|
||||
series TEXT,
|
||||
volume TEXT,
|
||||
language TEXT,
|
||||
page_count INT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS book_files (
|
||||
id UUID PRIMARY KEY,
|
||||
book_id UUID NOT NULL REFERENCES books(id) ON DELETE CASCADE,
|
||||
format TEXT NOT NULL CHECK (format IN ('pdf', 'cbz', 'cbr')),
|
||||
abs_path TEXT NOT NULL UNIQUE,
|
||||
size_bytes BIGINT NOT NULL,
|
||||
mtime TIMESTAMPTZ NOT NULL,
|
||||
fingerprint TEXT NOT NULL,
|
||||
checksum_opt TEXT,
|
||||
parse_status TEXT NOT NULL DEFAULT 'pending' CHECK (parse_status IN ('pending', 'ok', 'error')),
|
||||
parse_error_opt TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS index_jobs (
|
||||
id UUID PRIMARY KEY,
|
||||
library_id UUID REFERENCES libraries(id) ON DELETE SET NULL,
|
||||
type TEXT NOT NULL CHECK (type IN ('scan', 'rebuild')),
|
||||
status TEXT NOT NULL CHECK (status IN ('pending', 'running', 'success', 'failed')),
|
||||
started_at TIMESTAMPTZ,
|
||||
finished_at TIMESTAMPTZ,
|
||||
stats_json JSONB,
|
||||
error_opt TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS api_tokens (
|
||||
id UUID PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
prefix TEXT NOT NULL UNIQUE,
|
||||
token_hash TEXT NOT NULL,
|
||||
scope TEXT NOT NULL CHECK (scope IN ('admin', 'read')),
|
||||
last_used_at TIMESTAMPTZ,
|
||||
revoked_at TIMESTAMPTZ,
|
||||
expires_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_books_library_id ON books(library_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_book_files_book_id ON book_files(book_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_book_files_parse_status ON book_files(parse_status);
|
||||
CREATE INDEX IF NOT EXISTS idx_index_jobs_status ON index_jobs(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_api_tokens_scope ON api_tokens(scope);
|
||||
Reference in New Issue
Block a user