Initial miaojingAI project with image resolution guard

This commit is contained in:
FengLee
2026-05-09 11:32:34 +08:00
commit d499020d4e
264 changed files with 54160 additions and 0 deletions

View File

@@ -0,0 +1,110 @@
import { NextRequest, NextResponse } from 'next/server';
import { getDbClient } from '@/storage/database/local-db';
import { getAuthenticatedUser } from '@/lib/session-auth';
import {
buildInitialGenerationProgress,
ensureGenerationJobRuntimeSchema,
getGenerationJobEstimate,
} from '@/lib/generation-job-estimates';
const UUID_REGEX =
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
export async function GET(
request: NextRequest,
context: { params: Promise<{ id: string }> },
) {
try {
const user = await getAuthenticatedUser(request);
if (!user) {
return NextResponse.json({ error: '请先登录' }, { status: 401 });
}
const { id } = await context.params;
if (!UUID_REGEX.test(id)) {
return NextResponse.json({ error: '任务ID格式无效' }, { status: 400 });
}
const client = await getDbClient();
try {
await ensureGenerationJobRuntimeSchema(client);
await client.query(
`UPDATE generation_jobs
SET status = 'failed',
error = '任务执行超时或被服务重启中断',
payload = '{}'::jsonb,
finished_at = NOW(),
updated_at = NOW()
WHERE id = $1
AND status = 'running'
AND updated_at < NOW() - INTERVAL '30 minutes'`,
[id],
);
const result = await client.query(
`SELECT id, type, status, result, error, provider, model_name, api_url, progress,
created_at, started_at, finished_at, updated_at,
CASE
WHEN started_at IS NOT NULL
THEN FLOOR(EXTRACT(EPOCH FROM (COALESCE(finished_at, NOW()) - started_at)))::int
ELSE 0
END AS elapsed_seconds
FROM generation_jobs
WHERE id = $1
AND (user_id = $2 OR $3 = true)
LIMIT 1`,
[id, user.userId, user.role === 'admin' || user.role === 'enterprise_admin'],
);
if (result.rows.length === 0) {
return NextResponse.json({ error: '任务不存在' }, { status: 404 });
}
const job = result.rows[0];
const progress = job.progress && typeof job.progress === 'object' ? job.progress : {};
const progressEstimate = Number(progress.estimateSeconds || progress.etaSeconds || 0);
let estimateSeconds = Number.isFinite(progressEstimate) && progressEstimate > 0
? Math.ceil(progressEstimate)
: 0;
let etaSource = typeof progress.source === 'string' ? progress.source : 'default';
let etaSampleCount = Number(progress.sampleCount || 0);
let etaWindowDays = progress.windowDays ?? null;
if (estimateSeconds <= 0 && (job.status === 'queued' || job.status === 'running')) {
const estimate = await getGenerationJobEstimate(
client,
job.type,
String(job.provider || ''),
String(job.model_name || ''),
);
estimateSeconds = estimate.estimateSeconds;
etaSource = estimate.source;
etaSampleCount = estimate.sampleCount;
etaWindowDays = estimate.windowDays;
await client.query(
`UPDATE generation_jobs
SET progress = COALESCE(progress, '{}'::jsonb) || $2::jsonb,
updated_at = NOW()
WHERE id = $1`,
[id, JSON.stringify(buildInitialGenerationProgress(estimate))],
);
}
return NextResponse.json({
...job,
estimateSeconds,
eta: {
estimateSeconds,
source: etaSource,
sampleCount: etaSampleCount,
windowDays: etaWindowDays,
},
});
} finally {
client.release();
}
} catch (err) {
console.error('[generation-jobs] GET error:', err);
return NextResponse.json({ error: '查询生成任务失败' }, { status: 500 });
}
}