feat: API-Runtime 版本兼容协议 (API-AI-072)
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 46s
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 46s
- pollJobs: 记录/更新 RuntimeInstance (capabilities + heartbeat) - submitResult: 校验 schemaVersion 匹配 job.outputSchemaVersion - heartbeat: 首次调用设置 startedAt - 错误码: RESULT_SCHEMA_UNSUPPORTED + RUNTIME_VERSION_INCOMPATIBLE Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
00ac32a103
commit
012e26b950
@ -35,6 +35,24 @@ export class RuntimeInternalService {
|
||||
},
|
||||
});
|
||||
|
||||
// Register / update RuntimeInstance with capabilities
|
||||
if (supSnapshot.length > 0 || supOutput.length > 0) {
|
||||
await this.prisma.runtimeInstance.upsert({
|
||||
where: { runtimeInstanceId },
|
||||
create: {
|
||||
runtimeInstanceId,
|
||||
status: 'active',
|
||||
lastHeartbeatAt: new Date(),
|
||||
capabilities: capabilities as any,
|
||||
},
|
||||
update: {
|
||||
status: 'active',
|
||||
lastHeartbeatAt: new Date(),
|
||||
capabilities: capabilities as any,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Post-filter by snapshotVersion if needed (requires snapshot join)
|
||||
if (supSnapshot.length > 0) {
|
||||
const snapshotIds = [...new Set(jobs.map(j => j.snapshotId).filter(Boolean))];
|
||||
@ -92,14 +110,14 @@ export class RuntimeInternalService {
|
||||
const now = new Date();
|
||||
const lockUntil = new Date(now.getTime() + 60_000);
|
||||
|
||||
// First heartbeat: locked → running; subsequent heartbeats: extend lockUntil
|
||||
// First heartbeat: locked → running + set startedAt; subsequent: extend lockUntil
|
||||
const result = await this.prisma.aiRuntimeJob.updateMany({
|
||||
where: {
|
||||
id: jobId,
|
||||
lockedBy: runtimeInstanceId,
|
||||
status: { in: ['locked', 'running'] },
|
||||
},
|
||||
data: { lockUntil, status: 'running' },
|
||||
data: { lockUntil, status: 'running', startedAt: new Date() },
|
||||
});
|
||||
|
||||
if (result.count === 0) {
|
||||
@ -176,6 +194,14 @@ export class RuntimeInternalService {
|
||||
throw new ConflictException({ errorCode: 'JOB_NOT_ACTIVE', message: `Job is ${job.status}, cannot accept result` });
|
||||
}
|
||||
|
||||
// Validate schema version compatibility
|
||||
if (job.outputSchemaVersion && dto.schemaVersion !== job.outputSchemaVersion) {
|
||||
throw new BadRequestException({
|
||||
errorCode: 'RESULT_SCHEMA_UNSUPPORTED',
|
||||
message: `Result schemaVersion ${dto.schemaVersion} does not match job outputSchemaVersion ${job.outputSchemaVersion}`,
|
||||
});
|
||||
}
|
||||
|
||||
const resultIdempotencyKey = `${jobId}:${dto.attemptNo}:${dto.outputHash ?? ''}`;
|
||||
|
||||
// Check duplicate
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user