- completedAt → finishedAt, errorMessage → internalErrorMessage - API JSON keys preserved for backward compat Co-Authored-By: Claude <noreply@anthropic.com>
75 lines
2.5 KiB
TypeScript
75 lines
2.5 KiB
TypeScript
import { Injectable } from '@nestjs/common';
|
||
import { PrismaService } from '../../infrastructure/database/prisma.service';
|
||
|
||
@Injectable()
|
||
export class AiAnalysisRepository {
|
||
constructor(private readonly prisma: PrismaService) {}
|
||
|
||
// ── M-AI-02-10: 旧状态 → 新 lifecycleStatus 映射 ──
|
||
private static readonly STATUS_TO_LIFECYCLE: Record<string, string> = {
|
||
pending: 'pending',
|
||
processing: 'running',
|
||
completed: 'succeeded',
|
||
failed: 'failed',
|
||
};
|
||
|
||
async createJob(userId: string, jobType: string, sessionId?: string, answerId?: string) {
|
||
return this.prisma.aiJob.create({
|
||
data: {
|
||
userId,
|
||
jobType,
|
||
sessionId: sessionId ?? null,
|
||
answerId: answerId ?? null,
|
||
status: 'pending',
|
||
queuedAt: new Date(),
|
||
// ── M-AI-02-10 Shadow Write ──
|
||
lifecycleStatus: 'pending',
|
||
triggerType: 'api',
|
||
queueName: 'ai-interactive',
|
||
inputSchemaVersion: 'legacy-v1',
|
||
attemptCount: 0,
|
||
},
|
||
});
|
||
}
|
||
|
||
async updateJobStatus(id: string, status: string, errorMessage?: string) {
|
||
const data: Record<string, any> = { status };
|
||
if (status === 'processing') data.startedAt = new Date();
|
||
if (status === 'completed' || status === 'failed') data.finishedAt = new Date();
|
||
if (errorMessage) data.internalErrorMessage = errorMessage;
|
||
|
||
// ── M-AI-02-10 Shadow Write:映射旧 status 到新 lifecycleStatus ──
|
||
const lifecycleStatus = AiAnalysisRepository.STATUS_TO_LIFECYCLE[status];
|
||
if (lifecycleStatus) data.lifecycleStatus = lifecycleStatus;
|
||
|
||
return this.prisma.aiJob.update({ where: { id }, data });
|
||
}
|
||
|
||
async findJobById(id: string) {
|
||
return this.prisma.aiJob.findUnique({
|
||
where: { id },
|
||
include: { results: true },
|
||
});
|
||
}
|
||
|
||
async createResult(userId: string, jobId: string, result: Record<string, any>) {
|
||
return this.prisma.aiAnalysisResult.create({
|
||
data: {
|
||
userId,
|
||
jobId,
|
||
summary: result.summary ?? '',
|
||
masteryScore: result.score ?? null,
|
||
strengths: (result.strengths ?? []) as any,
|
||
weaknesses: (result.weaknesses ?? []) as any,
|
||
suggestions: (result.focusItems ?? result.suggestions ?? []) as any,
|
||
nextActions: (result.reviewSuggestion ?? result.recommendations ?? null) as any,
|
||
rawResult: result as any,
|
||
},
|
||
});
|
||
}
|
||
|
||
async findResultById(id: string) {
|
||
return this.prisma.aiAnalysisResult.findUnique({ where: { id } });
|
||
}
|
||
}
|