api shell
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
POSTGRES_USER=admin
|
||||
POSTGRES_PASSWORD=changeme
|
||||
POSTGRES_DB=postcard-im-app
|
||||
REDIS_URL=redis://redis:6379
|
||||
MINIO_ROOT_USER=minioadmin
|
||||
MINIO_ROOT_PASSWORD=changeme
|
||||
MINIO_BUCKET=media
|
||||
MINIO_ENDPOINT=http://minio:9000
|
||||
JWT_SECRET=changeme
|
||||
BACKEND_URL=http://backend:8080
|
||||
@@ -0,0 +1 @@
|
||||
.env
|
||||
@@ -0,0 +1,11 @@
|
||||
:80 {
|
||||
route /api/* {
|
||||
reverse_proxy backend:8080
|
||||
}
|
||||
route /ws {
|
||||
reverse_proxy backend:8080
|
||||
}
|
||||
route /* {
|
||||
reverse_proxy web:3000
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "backend"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
@@ -0,0 +1,12 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM rust:1.82-slim AS builder
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
RUN cargo build --release
|
||||
|
||||
FROM debian:trixie-slim
|
||||
WORKDIR /app
|
||||
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
|
||||
COPY --from=builder /app/target/release/backend /app/backend
|
||||
EXPOSE 8080
|
||||
CMD ["/app/backend"]
|
||||
@@ -0,0 +1,9 @@
|
||||
use std::time::Duration;
|
||||
use std::thread;
|
||||
|
||||
fn main() {
|
||||
println!("Backend stub started...");
|
||||
loop {
|
||||
thread::sleep(Duration::from_secs(60));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
CREATE TABLE users (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
username VARCHAR(32) UNIQUE NOT NULL,
|
||||
display_name VARCHAR(64) NOT NULL,
|
||||
avatar_url TEXT,
|
||||
password_hash TEXT NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE conversations (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
next_sequence BIGINT NOT NULL DEFAULT 0
|
||||
);
|
||||
|
||||
CREATE TABLE conversation_participants (
|
||||
conversation_id UUID REFERENCES conversations(id),
|
||||
user_id UUID REFERENCES users(id),
|
||||
last_read_seq BIGINT NOT NULL DEFAULT 0,
|
||||
joined_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (conversation_id, user_id),
|
||||
UNIQUE (conversation_id, user_id)
|
||||
);
|
||||
|
||||
CREATE TABLE messages (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
conversation_id UUID REFERENCES conversations(id) NOT NULL,
|
||||
sender_id UUID REFERENCES users(id) NOT NULL,
|
||||
sequence BIGINT NOT NULL,
|
||||
message_type VARCHAR(16) NOT NULL,
|
||||
body TEXT,
|
||||
media_metadata JSONB,
|
||||
client_msg_id UUID NOT NULL,
|
||||
status VARCHAR(16) NOT NULL DEFAULT 'sent',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
UNIQUE (conversation_id, sequence),
|
||||
UNIQUE (client_msg_id)
|
||||
);
|
||||
|
||||
CREATE TABLE sticker_packs (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name VARCHAR(64) NOT NULL,
|
||||
author VARCHAR(64),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE stickers (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
pack_id UUID REFERENCES sticker_packs(id) NOT NULL,
|
||||
emoji_tag VARCHAR(8),
|
||||
image_url TEXT NOT NULL,
|
||||
thumbnail_url TEXT NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
@@ -0,0 +1,7 @@
|
||||
-- Unique constraints on (conversation_id, sequence) and (client_msg_id)
|
||||
-- inherently create indexes in PostgreSQL, so we only need to explicitly
|
||||
-- define the remaining requested indexes.
|
||||
|
||||
CREATE INDEX idx_messages_conv_created_at ON messages(conversation_id, created_at);
|
||||
CREATE INDEX idx_conv_participants_user_id ON conversation_participants(user_id);
|
||||
CREATE INDEX idx_stickers_pack_id ON stickers(pack_id);
|
||||
@@ -0,0 +1,13 @@
|
||||
-- Atomic sequence increment for message ordering
|
||||
CREATE OR REPLACE FUNCTION next_message_sequence(conv_id UUID)
|
||||
RETURNS BIGINT AS $$
|
||||
DECLARE
|
||||
seq BIGINT;
|
||||
BEGIN
|
||||
UPDATE conversations
|
||||
SET next_sequence = next_sequence + 1, updated_at = now()
|
||||
WHERE id = conv_id
|
||||
RETURNING next_sequence INTO seq;
|
||||
RETURN seq;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
@@ -0,0 +1,110 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:18
|
||||
environment:
|
||||
POSTGRES_USER: ${POSTGRES_USER:-admin}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-Lord5673}
|
||||
POSTGRES_DB: ${POSTGRES_DB:-postcard-im-app}
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
- ./migrations:/docker-entrypoint-initdb.d:ro
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-admin} -d ${POSTGRES_DB:-postcard-im-app}"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
ports:
|
||||
- "5432:5432"
|
||||
|
||||
redis:
|
||||
image: redis:8
|
||||
ports:
|
||||
- "6379:6379"
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
minio:
|
||||
image: minio/minio:latest
|
||||
environment:
|
||||
MINIO_ROOT_USER: ${MINIO_ROOT_USER:-minioadmin}
|
||||
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-ChuckNorris52!}
|
||||
volumes:
|
||||
- minio_data:/data
|
||||
command: server /data --console-address ":9001"
|
||||
ports:
|
||||
- "9000:9000"
|
||||
- "9001:9001"
|
||||
healthcheck:
|
||||
test: ["CMD", "mc", "ready", "local"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
minio-init:
|
||||
image: minio/mc:latest
|
||||
depends_on:
|
||||
minio:
|
||||
condition: service_healthy
|
||||
entrypoint: >
|
||||
/bin/sh -c "
|
||||
/usr/bin/mc alias set myminio http://minio:9000 ${MINIO_ROOT_USER:-minioadmin} ${MINIO_ROOT_PASSWORD:-ChuckNorris52!} &&
|
||||
/usr/bin/mc mb myminio/${MINIO_BUCKET:-media} --ignore-existing &&
|
||||
/usr/bin/mc anonymous set public myminio/${MINIO_BUCKET:-media}
|
||||
"
|
||||
|
||||
backend:
|
||||
build:
|
||||
context: ./backend
|
||||
dockerfile: Containerfile
|
||||
environment:
|
||||
- DATABASE_URL=postgres://${POSTGRES_USER:-admin}:${POSTGRES_PASSWORD:-Lord5673}@postgres:5432/${POSTGRES_DB:-postcard-im-app}
|
||||
- REDIS_URL=${REDIS_URL:-redis://redis:6379}
|
||||
- MINIO_ENDPOINT=${MINIO_ENDPOINT:-http://minio:9000}
|
||||
- MINIO_ROOT_USER=${MINIO_ROOT_USER:-minioadmin}
|
||||
- MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD:-ChuckNorris52!}
|
||||
- MINIO_BUCKET=${MINIO_BUCKET:-media}
|
||||
- JWT_SECRET=${JWT_SECRET:-changeme}
|
||||
ports:
|
||||
- "8080:8080"
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
minio:
|
||||
condition: service_healthy
|
||||
|
||||
web:
|
||||
build:
|
||||
context: ./web
|
||||
dockerfile: Containerfile
|
||||
environment:
|
||||
- BACKEND_URL=${BACKEND_URL:-http://backend:8080}
|
||||
ports:
|
||||
- "3000:3000"
|
||||
depends_on:
|
||||
- backend
|
||||
|
||||
caddy:
|
||||
image: caddy:latest
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- ./Caddyfile:/etc/caddy/Caddyfile
|
||||
- caddy_data:/data
|
||||
- caddy_config:/config
|
||||
depends_on:
|
||||
- backend
|
||||
- web
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
minio_data:
|
||||
caddy_data:
|
||||
caddy_config:
|
||||
Reference in New Issue
Block a user