feat(media): add Convex media archive with backfill and mixed-media library

This commit is contained in:
2026-04-10 15:15:44 +02:00
parent ddb2412349
commit a1df097f9c
26 changed files with 2664 additions and 122 deletions

View File

@@ -38,6 +38,8 @@ import {
type VideoPollStatus,
} from "../lib/video-poll-logging";
import { normalizePublicTier } from "../lib/tier-credits";
import { upsertMediaItemByOwnerAndDedupe } from "./media";
import { buildStoredMediaDedupeKey } from "../lib/media-archive";
const MAX_IMAGE_RETRIES = 2;
const MAX_VIDEO_POLL_ATTEMPTS = 30;
@@ -160,6 +162,23 @@ export const finalizeImageSuccess = internalMutation({
},
});
const canvas = await ctx.db.get(existing.canvasId);
if (!canvas) {
throw new Error("Canvas not found");
}
await upsertMediaItemByOwnerAndDedupe(ctx, {
ownerId: canvas.ownerId,
input: {
kind: "image",
source: "ai-image",
dedupeKey: buildStoredMediaDedupeKey(storageId),
storageId,
firstSourceCanvasId: existing.canvasId,
firstSourceNodeId: nodeId,
},
});
return { creditCost };
},
});
@@ -600,6 +619,24 @@ export const finalizeVideoSuccess = internalMutation({
creditCost,
},
});
const canvas = await ctx.db.get(existing.canvasId);
if (!canvas) {
throw new Error("Canvas not found");
}
await upsertMediaItemByOwnerAndDedupe(ctx, {
ownerId: canvas.ownerId,
input: {
kind: "video",
source: "ai-video",
dedupeKey: buildStoredMediaDedupeKey(storageId),
storageId,
durationSeconds,
firstSourceCanvasId: existing.canvasId,
firstSourceNodeId: nodeId,
},
});
},
});