feat(data): 实现配置表 CRUD 与 Schema 初始化拆分

- 新增 data/db/ 数据库访问层:pool 管理、类型定义、Zod 校验、参数化 SQL 查询
- 新增 data/db/config-crud.ts:MonitoredSymbolsRepo / ExchangeConfigRepo / AppConfigRepo 三个 CRUD 服务类
- 新增 data/config.ts:中心化配置模块,零依赖 .env 解析 + Zod 校验
- 新增 data/schema/:klines.sql + config.sql 参考 DDL
- 新增 data/exchanges/:交易所类型定义与 Binance WebSocket 封装
- 新增 data/run/:交易所连接启动入口
- 重构 data/init-db/:001_init.sql 仅保留 TimescaleDB + klines,配置表拆分至 002_config.sql
- 更新 docker-compose.yml:挂载 init-db 初始化脚本
This commit is contained in:
Rekey
2026-06-07 20:46:35 +08:00
parent 10e13ae8da
commit e91cad79e6
18 changed files with 8560 additions and 5 deletions
+249
View File
@@ -0,0 +1,249 @@
// ============================================================
// schema/types.ts — PostgreSQL 表对应的 TypeScript 类型定义
// ============================================================
// 与 data/schema/*.sql 中的表结构一一对应
//
// 类型约定:
// NUMERIC(20,8) → string (保留精度,避免 IEEE 754 浮点误差)
// TIMESTAMPTZ → Date pg 默认解析为 Date
// SERIAL / INT → number
// SMALLINT → number
// REAL → number
// BOOLEAN → boolean
// ============================================================
// ============================================================
// 联合类型:约束 TEXT 字段的合法值
// ============================================================
/** 支持的交易所标识 */
export type Exchange = "binance" | "okx" | "bybit";
/** K 线周期(原始 1m + 聚合派生) */
export type KlineInterval = "1m" | "5m" | "15m" | "1h" | "4h" | "1d";
/** 日志级别 */
export type LogLevel = "trace" | "debug" | "info" | "warn" | "error" | "fatal";
// ============================================================
// 1. K 线主表 — klines
// ============================================================
/** klines 表完整行类型 */
export interface KlineRow {
/** K 线开盘时间(UTC */
time: Date;
/** 交易所 */
exchange: Exchange;
/** 交易对,如 BTCUSDT */
symbol: string;
/** K 线周期 */
interval: KlineInterval;
/** 开盘价 */
open: string;
/** 最高价 */
high: string;
/** 最低价 */
low: string;
/** 收盘价 */
close: string;
/** 成交量(基准币种) */
volume: string;
/** 成交额(计价币种) */
quote_volume: string;
/** 主动买入量(基准币种) */
taker_buy_base_vol: string;
/** 主动买入额(计价币种) */
taker_buy_quote_vol: string;
/** 成交笔数 */
trade_count: number;
/** K 线是否已闭合 */
is_closed: boolean;
/** 记录创建时间 */
created_at: Date;
/** 记录更新时间 */
updated_at: Date;
}
/** klines 表插入类型(省略自动生成的元数据列) */
export interface KlineInsert {
time: Date;
exchange: Exchange;
symbol: string;
interval: KlineInterval;
open: string;
high: string;
low: string;
close: string;
volume: string;
quote_volume?: string;
taker_buy_base_vol?: string;
taker_buy_quote_vol?: string;
trade_count?: number;
is_closed?: boolean;
}
// ============================================================
// 2. 连续聚合视图 — klines_5m / klines_15m / klines_1h / klines_1d
// ============================================================
/** 聚合 K 线通用类型(OHLCV,无扩展字段) */
export interface AggregatedKlineRow {
time: Date;
exchange: Exchange;
symbol: string;
interval: KlineInterval;
open: string;
high: string;
low: string;
close: string;
volume: string;
quote_volume: string;
taker_buy_base_vol: string;
taker_buy_quote_vol: string;
trade_count: number;
}
// ============================================================
// 3. 监控交易对配置 — monitored_symbols
// ============================================================
/** monitored_symbols 表完整行类型 */
export interface MonitoredSymbolRow {
/** 自增主键 */
id: number;
/** 交易所 */
exchange: Exchange;
/** 交易对 */
symbol: string;
/** K 线周期 */
interval: KlineInterval;
/** 是否启用采集 */
enabled: boolean;
/** 优先级(0-32767,越大越优先) */
priority: number;
/** 人类可读标签 */
label: string | null;
/** 备注 */
notes: string | null;
/** 创建时间 */
created_at: Date;
/** 更新时间 */
updated_at: Date;
}
/** monitored_symbols 插入类型 */
export interface MonitoredSymbolInsert {
exchange: Exchange;
symbol: string;
interval: KlineInterval;
enabled?: boolean;
priority?: number;
label?: string | null;
notes?: string | null;
}
/** monitored_symbols 更新类型(所有字段可选) */
export interface MonitoredSymbolUpdate {
enabled?: boolean;
priority?: number;
label?: string | null;
notes?: string | null;
}
// ============================================================
// 4. 交易所连接配置 — exchange_config
// ============================================================
/** exchange_config 表完整行类型 */
export interface ExchangeConfigRow {
/** 自增主键 */
id: number;
/** 交易所标识(唯一) */
exchange: Exchange;
/** REST API 基础 URLnull = 使用 SDK 默认值) */
rest_url: string | null;
/** WebSocket 基础 URLnull = 使用 SDK 默认值) */
ws_url: string | null;
/** 心跳间隔(毫秒) */
ws_ping_interval_ms: number;
/** 每秒最大请求数 */
rate_limit_per_sec: number;
/** 最大重连次数 */
max_reconnect_attempts: number;
/** 重连延迟基数(毫秒) */
reconnect_delay_ms: number;
/** 是否启用该交易所 */
enabled: boolean;
/** 备注 */
notes: string | null;
/** 创建时间 */
created_at: Date;
/** 更新时间 */
updated_at: Date;
}
/** exchange_config 插入类型 */
export interface ExchangeConfigInsert {
exchange: Exchange;
rest_url?: string | null;
ws_url?: string | null;
ws_ping_interval_ms?: number;
rate_limit_per_sec?: number;
max_reconnect_attempts?: number;
reconnect_delay_ms?: number;
enabled?: boolean;
notes?: string | null;
}
// ============================================================
// 5. 全局应用配置 — app_config
// ============================================================
/** app_config 表完整行类型 */
export interface AppConfigRow {
/** 自增主键 */
id: number;
/** 配置键 */
key: string;
/** 配置值(统一存储为字符串) */
value: string;
/** 说明 */
description: string | null;
/** 更新时间 */
updated_at: Date;
}
/** 已知的 app_config 键名 */
export type AppConfigKey =
| "batch_size"
| "flush_interval_ms"
| "log_level"
| "redis_publish_enabled";
// ============================================================
// 6. 业务聚合类型
// ============================================================
/**
* 唯一标识一个 K 线流
* 对应 klines / monitored_symbols 的 (exchange, symbol, interval) 组合
*/
export interface StreamKey {
exchange: Exchange;
symbol: string;
interval: KlineInterval;
}
/**
* 采集服务启动时加载的完整订阅配置
* = monitored_symbols JOIN exchange_config
*/
export interface StreamSubscription {
/** 流标识 */
streamKey: StreamKey;
/** 优先级 */
priority: number;
/** 连接配置 */
exchangeConfig: ExchangeConfigRow;
}