Files
model-asynch/update.sql
WangLiZhao 4e6b98b7d3 feat(stat): 添加模型请求按天统计功能
- 新增统计控制器、服务层与数据访问层,提供按天统计接口
- 在 worker 处理任务时原子累加请求计数(仅实际调用模型时计数)
- 更新数据库表结构,添加 asynch_model_stat 表及索引
- 更新文档说明统计功能的使用方式与统计口径
2026-04-27 10:42:42 +08:00

195 lines
10 KiB
SQL
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- model-asynch 三张核心表pgsql
-- 1) asynch_models模型配置
-- 2) asynch_task异步任务
-- 3) asynch_op_log操作日志统计用
-- 4) asynch_model_stat按天模型请求统计限流/监控用)
-- =========================
-- 1) asynch_models
-- =========================
CREATE TABLE IF NOT EXISTS asynch_models (
-- 基础字段(与现有表保持一致)
id BIGINT PRIMARY KEY, -- 主键ID非自增
tenant_id BIGINT NOT NULL DEFAULT 0, -- 租户ID
creator VARCHAR(64) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP(6),
-- 业务字段
model_name VARCHAR(128) NOT NULL, -- 模型名称(路由键)
base_url VARCHAR(256) NOT NULL, -- 模型服务基础地址(如 http://1.2.3.4:8080
route VARCHAR(256) NOT NULL DEFAULT '',-- 模型服务路由(如 /v1/infer
http_method VARCHAR(8) NOT NULL DEFAULT 'POST', -- 请求方式GET/POST
api_key VARCHAR(1024) DEFAULT '', -- 请求头绑定支持多个逗号分隔X-API-Key:xxx,operation:true
enabled SMALLINT NOT NULL DEFAULT 1, -- 是否启用1启用/0停用
max_concurrency INT NOT NULL DEFAULT 10, -- 单模型最大并发
queue_limit INT NOT NULL DEFAULT 1000, -- 排队上限(近似控制)
timeout_seconds INT NOT NULL DEFAULT 60, -- 调用模型服务超时(秒)
retry_times SMALLINT NOT NULL DEFAULT 0, -- 失败后最多再重试 N 次(不含首次)
retry_queue_max_seconds INT NOT NULL DEFAULT 0, -- 失败重试最大排队时间0=插队到队首;>0=排队超过该时间后插队,否则仍到队尾
auto_clean_seconds INT NOT NULL DEFAULT 86400, -- 已下载(state=4)后的保留时间(秒)
remark TEXT DEFAULT '' -- 备注
);
CREATE UNIQUE INDEX IF NOT EXISTS uk_asynch_models_tenant_model_name
ON asynch_models(tenant_id, model_name);
CREATE INDEX IF NOT EXISTS idx_asynch_models_tenant_id ON asynch_models(tenant_id);
CREATE INDEX IF NOT EXISTS idx_asynch_models_model_name ON asynch_models(model_name);
CREATE INDEX IF NOT EXISTS idx_asynch_models_enabled ON asynch_models(enabled);
CREATE INDEX IF NOT EXISTS idx_asynch_models_deleted_at ON asynch_models(deleted_at);
COMMENT ON TABLE asynch_models IS '异步模型表(模型服务配置)';
COMMENT ON COLUMN asynch_models.model_name IS '模型名称(路由键)';
COMMENT ON COLUMN asynch_models.api_key IS '请求头绑定支持多个逗号分隔X-API-Key:xxx,operation:true';
COMMENT ON COLUMN asynch_models.retry_times IS '失败后最多再重试 N 次(不含首次)';
COMMENT ON COLUMN asynch_models.retry_queue_max_seconds IS '失败重试最大排队时间0=插队到队首;>0=排队超过该时间后插队,否则仍到队尾';
COMMENT ON COLUMN asynch_models.auto_clean_seconds IS '已下载(state=4)后的保留时间(秒),到期清理';
-- =========================
-- 2) asynch_task
-- =========================
CREATE TABLE IF NOT EXISTS asynch_task (
-- 基础字段(与现有表保持一致)
id BIGINT PRIMARY KEY, -- 主键ID非自增
tenant_id BIGINT NOT NULL DEFAULT 0, -- 租户ID
creator VARCHAR(64) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP(6),
-- 任务核心字段
model_name VARCHAR(128) NOT NULL, -- 模型名称
task_id VARCHAR(64) NOT NULL, -- 任务ID对外返回
state SMALLINT NOT NULL DEFAULT 0, -- 0排队中/1执行中/2成功/3失败/4已下载
oss_file VARCHAR(512) DEFAULT '', -- 结果文件OSS地址
file_type VARCHAR(32) DEFAULT '', -- 文件类型mp3/mp4/png/...
file_size BIGINT NOT NULL DEFAULT 0, -- 文件大小(字节)
error_msg TEXT DEFAULT '', -- 错误信息
started_at TIMESTAMP, -- 开始执行时间
finished_at TIMESTAMP, -- 执行结束时间
expire_at TIMESTAMP, -- state=4 后写入,用于清理
-- 重试/排队
retry_count INT NOT NULL DEFAULT 0, -- 已重试次数(不含首次)
enqueue_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- 入队时间(用于排队顺序)
-- 任务执行阶段:用于区分“重试模型”与“仅重试 OSS”
phase SMALLINT NOT NULL DEFAULT 0, -- 0模型阶段/1OSS阶段
tmp_file TEXT DEFAULT '', -- 临时结果文件路径phase=1 时仅重试 OSS 上传)
-- 输入信息(可选)
input_ref TEXT DEFAULT '', -- 输入引用如OSS/业务资源ID等
request_payload JSONB -- 请求参数(可选)
);
CREATE UNIQUE INDEX IF NOT EXISTS uk_asynch_task_tenant_task_id
ON asynch_task(tenant_id, task_id);
CREATE INDEX IF NOT EXISTS idx_asynch_task_tenant_id ON asynch_task(tenant_id);
CREATE INDEX IF NOT EXISTS idx_asynch_task_model_name ON asynch_task(model_name);
CREATE INDEX IF NOT EXISTS idx_asynch_task_state ON asynch_task(state);
CREATE INDEX IF NOT EXISTS idx_asynch_task_enqueue_at ON asynch_task(enqueue_at);
CREATE INDEX IF NOT EXISTS idx_asynch_task_updated_at ON asynch_task(updated_at);
CREATE INDEX IF NOT EXISTS idx_asynch_task_expire_at ON asynch_task(expire_at);
CREATE INDEX IF NOT EXISTS idx_asynch_task_deleted_at ON asynch_task(deleted_at);
COMMENT ON TABLE asynch_task IS '异步任务表';
COMMENT ON COLUMN asynch_task.state IS '0排队中/1执行中/2成功/3失败/4已下载';
COMMENT ON COLUMN asynch_task.retry_count IS '已重试次数(不含首次)';
COMMENT ON COLUMN asynch_task.enqueue_at IS '入队时间(用于排队顺序)';
COMMENT ON COLUMN asynch_task.phase IS '执行阶段0模型阶段/1OSS阶段模型已成功等待上传OSS';
COMMENT ON COLUMN asynch_task.tmp_file IS '临时结果文件路径phase=1 时仅重试 OSS 上传)';
-- =========================
-- 3) asynch_op_log
-- =========================
CREATE TABLE IF NOT EXISTS asynch_op_log (
-- 基础字段(与现有表保持一致)
id BIGINT PRIMARY KEY,
tenant_id BIGINT NOT NULL DEFAULT 0,
creator VARCHAR(64) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP(6),
-- 基础审计信息
ip VARCHAR(64) DEFAULT '',
user_agent VARCHAR(256) DEFAULT '',
api_path VARCHAR(256) DEFAULT '',
http_method VARCHAR(16) DEFAULT '',
-- 业务信息
biz_name VARCHAR(128) NOT NULL DEFAULT '', -- 调用方业务模块/系统
model_name VARCHAR(128) NOT NULL DEFAULT '',
task_id VARCHAR(64) NOT NULL DEFAULT '',
-- 统计字段
op_type VARCHAR(64) NOT NULL DEFAULT 'createTask', -- 操作类型(默认创建任务)
success SMALLINT NOT NULL DEFAULT 1, -- 1成功/0失败
error_msg TEXT DEFAULT '',
cost_ms BIGINT NOT NULL DEFAULT 0, -- 耗时(毫秒)
-- 请求/响应 JSON用于后期统计分析
request_payload JSONB,
response_payload JSONB
);
CREATE INDEX IF NOT EXISTS idx_asynch_op_log_tenant_time ON asynch_op_log(tenant_id, created_at);
CREATE INDEX IF NOT EXISTS idx_asynch_op_log_model_name ON asynch_op_log(model_name);
CREATE INDEX IF NOT EXISTS idx_asynch_op_log_biz_name ON asynch_op_log(biz_name);
CREATE INDEX IF NOT EXISTS idx_asynch_op_log_task_id ON asynch_op_log(task_id);
CREATE INDEX IF NOT EXISTS idx_asynch_op_log_op_type ON asynch_op_log(op_type);
CREATE INDEX IF NOT EXISTS idx_asynch_op_log_deleted_at ON asynch_op_log(deleted_at);
COMMENT ON TABLE asynch_op_log IS '操作记录日志表(创建任务等,用于统计)';
COMMENT ON COLUMN asynch_op_log.biz_name IS '业务名称(调用方模块/系统)';
COMMENT ON COLUMN asynch_op_log.model_name IS '模型名称';
COMMENT ON COLUMN asynch_op_log.task_id IS '任务ID';
COMMENT ON COLUMN asynch_op_log.op_type IS '操作类型(如 createTask/getTaskResult/getTaskBatch 等)';
COMMENT ON COLUMN asynch_op_log.success IS '是否成功1成功/0失败';
COMMENT ON COLUMN asynch_op_log.error_msg IS '错误信息(失败时)';
COMMENT ON COLUMN asynch_op_log.cost_ms IS '耗时(毫秒)';
COMMENT ON COLUMN asynch_op_log.request_payload IS '请求 JSON';
COMMENT ON COLUMN asynch_op_log.response_payload IS '响应 JSON';
-- =========================
-- 4) asynch_model_stat
-- =========================
CREATE TABLE IF NOT EXISTS asynch_model_stat (
day DATE NOT NULL, -- 天YYYY-MM-DD
tenant_id BIGINT NOT NULL DEFAULT 0, -- 租户ID
creator VARCHAR(64) NOT NULL DEFAULT '', -- 创建人
model_name VARCHAR(128) NOT NULL DEFAULT '', -- 模型名称
request_count BIGINT NOT NULL DEFAULT 0, -- 请求次数
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY(day, tenant_id, creator, model_name)
);
-- 便于时间段/租户/人/模型过滤
CREATE INDEX IF NOT EXISTS idx_asynch_model_stat_tenant_day ON asynch_model_stat(tenant_id, day);
CREATE INDEX IF NOT EXISTS idx_asynch_model_stat_day ON asynch_model_stat(day);
CREATE INDEX IF NOT EXISTS idx_asynch_model_stat_model_name ON asynch_model_stat(model_name);
CREATE INDEX IF NOT EXISTS idx_asynch_model_stat_creator ON asynch_model_stat(creator);
COMMENT ON TABLE asynch_model_stat IS '按天模型请求统计(用于限流/监控)';
COMMENT ON COLUMN asynch_model_stat.day IS 'YYYY-MM-DD';
COMMENT ON COLUMN asynch_model_stat.tenant_id IS '租户ID';
COMMENT ON COLUMN asynch_model_stat.creator IS '创建人';
COMMENT ON COLUMN asynch_model_stat.model_name IS '模型名称';
COMMENT ON COLUMN asynch_model_stat.request_count IS '请求次数';
COMMENT ON COLUMN asynch_model_stat.created_at IS '创建时间';
COMMENT ON COLUMN asynch_model_stat.updated_at IS '更新时间';