jimeng-free-api/src/lib/database/models/GenerationResult.ts

244 lines
8.3 KiB
TypeScript
Raw 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.

import NeDBManager from '@/lib/database/nedb.js';
// 生成结果表数据模型
export interface IGenerationResult {
task_id: string; // 关联的任务ID主键
task_type: 'image' | 'video'; // 任务类型
server_id: string; // 处理服务器ID
// 生成结果
status: 'success' | 'failed'; // 最终状态
original_urls: string[]; // 原始URL数组即梦返回的地址
tos_urls: string[]; // TOS URL数组上传后的地址
// 处理元数据
metadata: {
generation_time?: number; // 生成耗时(毫秒)
tos_upload_time?: number; // TOS上传耗时毫秒
total_files: number; // 文件总数
successful_uploads: number; // 成功上传数量
upload_retry_count?: number; // 上传重试次数
tos_upload_errors?: string[]; // TOS上传错误信息
fail_reason?: string; // 失败原因
};
// 时间管理
created_at: number; // 创建时间戳(秒)
expires_at: number; // 过期时间戳用于自动清理默认24小时后
// 读取状态
is_read: boolean; // 是否已被读取
first_read_at?: number; // 首次读取时间戳(秒)
read_count: number; // 读取次数
}
// NeDB 数据操作类
export class GenerationResult {
private static dbName = 'generation_results';
// 默认过期时间24小时86400秒
private static DEFAULT_EXPIRY_SECONDS = 24 * 60 * 60;
// 创建结果
static async create(resultData: Omit<IGenerationResult, '_id'>): Promise<IGenerationResult> {
const currentTime = Math.floor(Date.now() / 1000);
const result = {
...resultData,
created_at: resultData.created_at || currentTime,
expires_at: resultData.expires_at || (currentTime + this.DEFAULT_EXPIRY_SECONDS),
is_read: resultData.is_read || false,
read_count: resultData.read_count || 0
};
return await NeDBManager.insert(this.dbName, result);
}
// 查找单个结果
static async findOne(query: any): Promise<IGenerationResult | null> {
// 自动过滤过期数据
const currentTime = Math.floor(Date.now() / 1000);
const filterQuery = {
...query,
expires_at: { $gt: currentTime }
};
return await NeDBManager.findOne(this.dbName, filterQuery);
}
// 查找多个结果
static async find(query: any, sort?: any, limit?: number): Promise<IGenerationResult[]> {
// 自动过滤过期数据
const currentTime = Math.floor(Date.now() / 1000);
const filterQuery = {
...query,
expires_at: { $gt: currentTime }
};
return await NeDBManager.find(this.dbName, filterQuery, sort, limit);
}
// 更新结果
static async updateOne(query: any, update: any, options: any = {}): Promise<number> {
// 自动过滤过期数据
const currentTime = Math.floor(Date.now() / 1000);
const filterQuery = {
...query,
expires_at: { $gt: currentTime }
};
return await NeDBManager.update(this.dbName, filterQuery, update, { ...options, multi: false });
}
// 批量更新结果
static async updateMany(query: any, update: any, options: any = {}): Promise<number> {
// 自动过滤过期数据
const currentTime = Math.floor(Date.now() / 1000);
const filterQuery = {
...query,
expires_at: { $gt: currentTime }
};
return await NeDBManager.update(this.dbName, filterQuery, update, { ...options, multi: true });
}
// 删除结果
static async deleteOne(query: any): Promise<number> {
return await NeDBManager.remove(this.dbName, query, { multi: false });
}
// 批量删除结果
static async deleteMany(query: any): Promise<number> {
return await NeDBManager.remove(this.dbName, query, { multi: true });
}
// 批量插入结果
static async insertMany(results: Omit<IGenerationResult, '_id'>[]): Promise<IGenerationResult[]> {
const insertedResults: IGenerationResult[] = [];
for (const resultData of results) {
const currentTime = Math.floor(Date.now() / 1000);
const result = {
...resultData,
created_at: resultData.created_at || currentTime,
expires_at: resultData.expires_at || (currentTime + this.DEFAULT_EXPIRY_SECONDS),
is_read: resultData.is_read || false,
read_count: resultData.read_count || 0
};
const insertedResult = await NeDBManager.insert(this.dbName, result);
insertedResults.push(insertedResult);
}
return insertedResults;
}
// 计数(排除过期数据)
static async countDocuments(query: any): Promise<number> {
const currentTime = Math.floor(Date.now() / 1000);
const filterQuery = {
...query,
expires_at: { $gt: currentTime }
};
return await NeDBManager.count(this.dbName, filterQuery);
}
// 根据任务ID查找结果并更新读取状态
static async findByTaskIdAndMarkRead(taskId: string): Promise<IGenerationResult | null> {
const result = await this.findOne({ task_id: taskId });
if (result) {
// 更新读取状态和计数
const currentTime = Math.floor(Date.now() / 1000);
await this.updateOne(
{ task_id: taskId },
{
$set: {
is_read: true,
first_read_at: result.first_read_at || currentTime
},
$inc: { read_count: 1 }
}
);
// 返回更新后的结果
result.is_read = true;
result.first_read_at = result.first_read_at || currentTime;
result.read_count = (result.read_count || 0) + 1;
}
return result;
}
// 清理过期数据
static async cleanupExpiredResults(): Promise<number> {
const currentTime = Math.floor(Date.now() / 1000);
return await this.deleteMany({
expires_at: { $lte: currentTime }
});
}
// 获取即将过期的结果(用于预警)
static async getExpiringResults(warningSeconds: number = 3600): Promise<IGenerationResult[]> {
const currentTime = Math.floor(Date.now() / 1000);
const warningTime = currentTime + warningSeconds;
return await this.find({
expires_at: {
$gt: currentTime,
$lte: warningTime
}
});
}
// 延长结果过期时间
static async extendExpiry(taskId: string, additionalSeconds: number): Promise<boolean> {
const numUpdated = await this.updateOne(
{ task_id: taskId },
{
$inc: { expires_at: additionalSeconds }
}
);
return numUpdated > 0;
}
// 获取统计信息
static async getStats(): Promise<{
total: number;
unread: number;
read: number;
byType: { [key: string]: number };
byStatus: { [key: string]: number };
}> {
const allResults = await this.find({});
const stats = {
total: allResults.length,
unread: 0,
read: 0,
byType: {} as { [key: string]: number },
byStatus: {} as { [key: string]: number }
};
allResults.forEach(result => {
// 读取状态统计
if (!result.is_read) {
stats.unread++;
} else {
stats.read++;
}
// 任务类型统计
stats.byType[result.task_type] = (stats.byType[result.task_type] || 0) + 1;
// 最终状态统计
stats.byStatus[result.status] = (stats.byStatus[result.status] || 0) + 1;
});
return stats;
}
}
export default GenerationResult;