Fix memories disappearing + always-processing state
Three bugs fixed:
1. Vision failure was marking memories as 'failed', triggering orphan
cleanup that permanently deleted them. Vision is optional — on error,
now marks 'ready' so the image stays visible without AI captions.
2. Thumbnail failure was blocking vision from running (rejected promise
swallowed the chain). Fixed by catching thumbnail error separately so
processMemoryVision always executes and always sets a final status.
3. /api/img proxy was rejecting thumbnail keys (families/{id}/thumbnails/…)
because 'families/' was not in ALLOWED_PREFIXES. Added it.
Also: replaced the full-bleed 'Processing…' overlay with a small corner
badge so the uploaded photo is visible immediately after upload.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
a3a0ddf3c9
commit
f953963b3b
4 changed files with 10 additions and 6 deletions
|
|
@ -563,9 +563,9 @@ function MemoryTile({ memory, folder, onClick }: { memory: Memory; folder: Folde
|
|||
<span className="text-white text-lg drop-shadow">⤢</span>
|
||||
</div>
|
||||
{memory.processingStatus === "processing" && (
|
||||
<div className="absolute inset-0 bg-black/40 flex items-center justify-center rounded-xl">
|
||||
<span className="text-white text-[9px] bg-black/50 px-1.5 py-0.5 rounded-full">Processing…</span>
|
||||
</div>
|
||||
<span className="absolute top-1 left-1 text-[8px] bg-black/60 text-white px-1.5 py-0.5 rounded-full leading-tight">
|
||||
⏳
|
||||
</span>
|
||||
)}
|
||||
{memory.isPrivate && <span className="absolute top-1 right-1 text-[9px]">🔒</span>}
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
|
||||
const ALLOWED_PREFIXES = ["avatars/", "profiles/", "memories/", "thumbnails/"];
|
||||
const ALLOWED_PREFIXES = ["avatars/", "profiles/", "memories/", "thumbnails/", "families/"];
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const key = req.nextUrl.searchParams.get("key");
|
||||
|
|
|
|||
|
|
@ -84,10 +84,12 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
|
|||
}
|
||||
}
|
||||
|
||||
// Mark as processing and start the media pipeline
|
||||
// Mark as processing and start the media pipeline.
|
||||
// thumbnail failure is non-fatal — always proceed to vision, which marks 'ready'.
|
||||
await sql`UPDATE memories SET processing_status = 'processing', updated_at = now() WHERE id = ${id}`;
|
||||
|
||||
generateThumbnail(id)
|
||||
.catch(e => console.error(`[thumbnail] id=${id}`, e)) // swallow so vision always runs
|
||||
.then(() => processMemoryVision(id))
|
||||
.catch(e => console.error(`[memory pipeline] id=${id}`, e));
|
||||
|
||||
|
|
|
|||
|
|
@ -125,7 +125,9 @@ export async function processMemoryVision(memoryId: string): Promise<void> {
|
|||
`;
|
||||
} catch (e) {
|
||||
console.error(`[vision] Failed for memory ${memoryId}:`, e);
|
||||
await sql`UPDATE memories SET processing_status = 'failed', updated_at = now() WHERE id = ${memoryId}`;
|
||||
// Vision is optional — mark as ready so the image is still visible.
|
||||
// Only the confirm step (HeadObject failure) should mark as 'failed'.
|
||||
await sql`UPDATE memories SET processing_status = 'ready', updated_at = now() WHERE id = ${memoryId}`;
|
||||
await logAudit({
|
||||
action: "vision_processing_failed",
|
||||
metadata: { memoryId, error: String(e) },
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue