Merge pull request '发布切换等待共享抠图服务完成' (#47) from codex/rmbg-active-job-drain-20261105 into main

This commit is contained in:
WuYongJie 2026-11-05 15:36:16 +08:00
commit 1f5528331d
3 changed files with 29 additions and 0 deletions

View File

@ -8,6 +8,7 @@ import { executeConfiguredVip98kTask } from "@/lib/ai/vip98k-runtime";
import { db } from "@/lib/db";
import { generatedImage } from "@/lib/db/schema";
import { createLogger } from "@/lib/observability/logger";
import { trackRuntimeWork } from "@/lib/observability/active-work";
import { uploadFile } from "@/lib/storage/service";
const logger = createLogger("rmbg-service");
@ -654,6 +655,12 @@ export async function fetchImageBufferFromUrl(imageUrl: string): Promise<Buffer>
export async function executeRmbgJob(
params: ExecuteRmbgJobParams
): Promise<ExecuteRmbgJobResult> {
return trackRuntimeWork(() => runRmbgJob(params));
}
async function runRmbgJob(
params: ExecuteRmbgJobParams
): Promise<ExecuteRmbgJobResult> {
const {
requestId = crypto.randomUUID(),

View File

@ -96,6 +96,7 @@ function rmbgLoader(fetch: typeof globalThis.fetch, timer?: typeof setTimeout) {
"@/lib/db": { db: {} },
"@/lib/db/schema": { generatedImage: {} },
"@/lib/storage/service": { uploadFile: async (name: string) => ({ url: `${cdn}/${name}` }) },
"@/lib/observability/active-work": { trackRuntimeWork: async (execute: () => unknown) => execute() },
fetch,
setTimeout: timer || ((callback: () => void, ms: number) => setTimeout(callback, ms <= 2000 ? 0 : ms)),
}, { NEXT_PUBLIC_CANVAS_CDN_ORIGIN: cdn })("lib/ai/rmbg/service.ts");

View File

@ -28,3 +28,24 @@ test("durable archive handoff is separate from unfinished original generation",
complete(); await original;
expect(records.at(-1)).toMatchObject({ active: 0, durable: 0 });
});
test("direct matting stays visible to release draining until the provider attempt fails", async () => {
const counts: number[] = [];
let rejectProvider!: (error: Error) => void;
let providerStarted!: () => void;
const started = new Promise<void>(resolve => { providerStarted = resolve; });
const service = serverLoader({
"node:fs": { writeFileSync: (_path: string, value: string) => counts.push(JSON.parse(value).active), unlinkSync() {} },
"@/lib/db/queries": { getSystemSetting: async () => ({ value: { provider: "rmbg", apiUrl: "https://provider.example/remove", apiKey: "test" } }) },
"@/lib/db": { db: {} }, "@/lib/db/schema": { generatedImage: {} },
"@/lib/storage/service": {},
fetch: async () => { providerStarted(); return new Promise<Response>((_resolve, reject) => { rejectProvider = reject; }); },
})("lib/ai/rmbg/service.ts");
const pending = service.executeRmbgJob({ userId: "user-a", imageBuffer: Buffer.from("image"), skipGallerySave: true });
const assertion = expect(pending).rejects.toThrow();
await started;
expect(counts).toEqual([1]);
rejectProvider(new Error("provider unavailable"));
await assertion;
expect(counts).toEqual([1, 0]);
});