Initial AlphaPulse implementation: news crawler and Binance klines

- Backend (FastAPI, SQLAlchemy 2, Alembic): single-admin cookie auth,
  news/crawler/market APIs with SSE and WebSocket streaming
- Crawler (Scrapy + Scrapy-Redis): wscn_news, wscn_live, cls_depth,
  cls_telegraph spiders, idempotent upserts with revisions, raw response
  archiving, per-source subprocess supervision, restart and backoff
- Market worker: full-history Binance spot/USD-M kline backfill,
  realtime WS stream, hourly and on-reconnect catch-up
- Frontend (Vue 3, Element Plus, UnoCSS, KLineChart): news feed,
  crawler console with live logs, Binance-style chart page
- Deploy: docker compose, nginx site, migrate and daily backup scripts
This commit is contained in:
eezd committed 2026-10-13 13:32:55 +08:00
commit aabc81ba5b
88 files changed
+12603

No files matched your search

+8
View File
@@ -0,0 +1,8 @@
# 复制为仓库根目录 .env(chmod 600);只有这一套配置
DATABASE_URL=postgresql+asyncpg://alphapulse:<密码>@postgres:5432/alphapulse
# DB 14 与 AFFiNE 共用,key 一律带 ap: 前缀
REDIS_URL=redis://:<密码>@redis:6379/14
JWT_SECRET=<openssl rand -hex 32>
ADMIN_USERNAME=admin
# 哈希含 $,必须用单引号包住,否则 compose 会做变量替换
ADMIN_PASSWORD_HASH='<python -m alphapulse.core.auth hash-password 的输出>'
+8
View File
@@ -0,0 +1,8 @@
FROM python:3.13-slim
COPY --from=ghcr.io/astral-sh/uv:0.12 /uv /usr/local/bin/uv
ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy UV_PROJECT_ENVIRONMENT=/opt/venv PATH=/opt/venv/bin:$PATH
WORKDIR /app
COPY pyproject.toml uv.lock ./
RUN uv sync --locked --no-dev --no-install-project
COPY . .
RUN uv sync --locked --no-dev
+11
View File
@@ -0,0 +1,11 @@
FROM node:24-alpine AS build
RUN corepack enable
WORKDIR /app
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
RUN pnpm install --frozen-lockfile
COPY . .
RUN pnpm build
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
+11
View File
@@ -0,0 +1,11 @@
#!/bin/sh
# 每日备份 alphapulse 库,保留最近 14 份;backrest 03:00 会把 /srv 整体备份到异地
set -eu
dir=/srv/AlphaPulse/backups/daily
mkdir -p "$dir"
target="$dir/alphapulse-$(date +%Y%m%d).dump"
# 先写临时文件,成功后再改名,避免留下半截备份
docker exec postgres pg_dump -U alphapulse -Fc alphapulse > "$target.tmp"
mv "$target.tmp" "$target"
ls -1t "$dir"/alphapulse-*.dump | tail -n +15 | xargs -r rm --
echo "$(date '+%F %T') 备份完成:$target $(du -h "$target" | cut -f1)"
+39
View File
@@ -0,0 +1,39 @@
name: alphapulse
x-backend: &backend
build:
context: ../backend
dockerfile: ../deploy/Dockerfile.backend
image: alphapulse-backend
env_file: ../.env
restart: unless-stopped
networks: [dev_default]
services:
api:
<<: *backend
command: [uvicorn, alphapulse.api.main:app, --host, 0.0.0.0, --port, "8000", --proxy-headers, --forwarded-allow-ips, "*"]
crawler:
<<: *backend
command: [python, -m, alphapulse.crawler.manager]
# 留时间给 scrapy 子进程优雅退出并刷完日志
stop_grace_period: 30s
market:
<<: *backend
command: [python, -m, alphapulse.market.worker]
web:
build:
context: ../web
dockerfile: ../deploy/Dockerfile.web
restart: unless-stopped
depends_on: [api]
ports:
- 127.0.0.1:21030:80
networks: [dev_default]
networks:
dev_default:
external: true
+10
View File
@@ -0,0 +1,10 @@
#!/bin/sh
# 迁移前先备份:只有一套环境,迁移即生产操作
set -eu
cd "$(dirname "$0")"
mkdir -p ../backups
dump="../backups/alphapulse-premigrate-$(date +%Y%m%d-%H%M%S).dump"
docker exec postgres pg_dump -U alphapulse -Fc alphapulse > "$dump"
echo "已备份:$dump"
docker compose build api
docker compose run --rm -T api alembic upgrade head
+31
View File
@@ -0,0 +1,31 @@
# alpha.134333.xyz -> AlphaPulse web 容器(127.0.0.1:21030)
server {
listen 80;
server_name alpha.134333.xyz;
return 308 https://alpha.134333.xyz$request_uri;
}
server {
listen 443 ssl;
http2 on;
server_name alpha.134333.xyz;
include /etc/nginx/snippets/ssl-134333.xyz.conf;
include /etc/nginx/snippets/no-spider.conf;
access_log /var/log/nginx/alpha.134333.xyz.log;
error_log /var/log/nginx/alpha.134333.xyz.error.log warn;
location / {
proxy_pass http://127.0.0.1:21030;
proxy_http_version 1.1;
# SSE 不缓冲;WebSocket 需要升级头
proxy_buffering off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 1h;
}
}