api-server/src/modules/document-import/document-import.service.ts

62 lines
2.1 KiB
TypeScript
Raw Normal View History

import { Injectable } from '@nestjs/common';
import { DocumentImportRepository } from './document-import.repository';
import { RedisService } from '../../infrastructure/redis/redis.service';
import { QueueService } from '../../infrastructure/queue/queue.service';
@Injectable()
export class DocumentImportService {
constructor(
private readonly repository: DocumentImportRepository,
private readonly redis: RedisService,
private readonly queue: QueueService,
) {}
async createImport(dto: {
userId?: string;
knowledgeBaseId?: string;
fileName?: string;
sourceType?: string;
rawText?: string;
}) {
const lockKey = `lock:document-import:${dto.fileName || Date.now()}`;
const lockToken = await this.redis.lock(lockKey, 1800);
if (!lockToken) {
throw new Error('相同文件正在导入中,请稍候');
}
const job = await this.repository.create(dto);
await this.redis.set(`job:document-import:${job.id}:status`, 'pending', 86400);
await this.redis.set(`job:document-import:${job.id}:progress`, '0', 86400);
await this.redis.set(`job:document-import:${job.id}:message`, '任务已加入队列', 86400);
await this.queue.add('document-import', {
importId: job.id,
userId: dto.userId || 'anonymous',
knowledgeBaseId: dto.knowledgeBaseId,
rawText: dto.rawText,
fileName: dto.fileName,
});
// Release the lock — the worker will re-lock if needed
await this.redis.unlock(lockKey, lockToken);
return { jobId: job.id, status: 'queued' };
}
async getStatus(id: string) {
const redisStatus = await this.redis.get(`job:document-import:${id}:status`);
const redisProgress = await this.redis.get(`job:document-import:${id}:progress`);
const redisMessage = await this.redis.get(`job:document-import:${id}:message`);
const dbJob = await this.repository.findById(id);
return {
id,
fileName: dbJob?.sourceName,
status: redisStatus || dbJob?.status || 'unknown',
progress: redisProgress ? parseInt(redisProgress, 10) : 0,
message: redisMessage || null,
};
}
}