From d9220d2556a6403c558ba7bf5dd8f24f1d0e2b1d Mon Sep 17 00:00:00 2001 From: Simplereally Date: Wed, 11 Mar 2026 23:34:12 +1100 Subject: [PATCH 1/4] fix: finalize convex optimization remediations --- components/debug/limit-tester.tsx | 4 +- .../studio/batch/batch-action-button.test.tsx | 22 +- .../studio/batch/batch-action-button.tsx | 4 + convex-optimization-branch-review.md | 215 +++++++ convex-optimiziations.md | 45 ++ convex/_generated/api.d.ts | 2 + convex/batchGeneration.ts | 132 ++-- convex/batchProcessor.ts | 290 ++++++--- convex/lib/batchGenerationState.test.ts | 112 ++++ convex/lib/batchGenerationState.ts | 121 ++++ convex/schema.ts | 3 + convex/singleGeneration.ts | 34 +- convex/singleGenerationProcessor.ts | 568 ++++++++++++------ hooks/queries/use-generate-image.test.tsx | 16 +- hooks/queries/use-generate-image.ts | 6 +- hooks/use-batch-mode.ts | 1 + 16 files changed, 1223 insertions(+), 352 deletions(-) create mode 100644 convex-optimization-branch-review.md create mode 100644 convex-optimiziations.md create mode 100644 convex/lib/batchGenerationState.test.ts create mode 100644 convex/lib/batchGenerationState.ts diff --git a/components/debug/limit-tester.tsx b/components/debug/limit-tester.tsx index 62abd38..40a2fd6 100644 --- a/components/debug/limit-tester.tsx +++ b/components/debug/limit-tester.tsx @@ -44,7 +44,7 @@ export function LimitTester() { const [naturalDimensions, setNaturalDimensions] = useState<{ w: number; h: number } | null>(null) const startGeneration = useMutation(api.singleGeneration.startGeneration) - const dispatchGeneration = useAction(api.singleGeneration.dispatchGeneration) + const processGeneration = useAction(api.singleGenerationProcessor.processGeneration) // BYOP context for API key const apiKey = usePollenApiKey() @@ -81,7 +81,7 @@ export function LimitTester() { apiKey, }) setCurrentGenId(id) - void Promise.resolve(dispatchGeneration({ generationId: id, apiKey })).catch((dispatchError) => { + void Promise.resolve(processGeneration({ generationId: id, apiKey })).catch((dispatchError) => { console.error("Immediate dispatch failed; recovery path will retry:", dispatchError) }) } catch (error) { diff --git a/components/studio/batch/batch-action-button.test.tsx b/components/studio/batch/batch-action-button.test.tsx index 031ac3b..9ac8774 100644 --- a/components/studio/batch/batch-action-button.test.tsx +++ b/components/studio/batch/batch-action-button.test.tsx @@ -1,5 +1,6 @@ +import "@testing-library/jest-dom/vitest" import { render, screen, fireEvent } from "@testing-library/react" -import { describe, it, expect, vi } from "vitest" +import { beforeEach, describe, expect, it, vi } from "vitest" import { BatchActionButton } from "./batch-action-button" describe("BatchActionButton", () => { @@ -53,6 +54,25 @@ describe("BatchActionButton", () => { expect(onResume).toHaveBeenCalledTimes(1) }) + it("disables resume while paused items are still in flight", () => { + const onResume = vi.fn() + render( + + ) + + const resumeButton = screen.getByRole("button", { name: /resume/i }) + expect(resumeButton).toBeDisabled() + + fireEvent.click(resumeButton) + + expect(onResume).not.toHaveBeenCalled() + }) + it("calls onCancel when cancel button is clicked", () => { const onCancel = vi.fn() render() diff --git a/components/studio/batch/batch-action-button.tsx b/components/studio/batch/batch-action-button.tsx index 854758c..133e484 100644 --- a/components/studio/batch/batch-action-button.tsx +++ b/components/studio/batch/batch-action-button.tsx @@ -45,6 +45,7 @@ export const BatchActionButton = React.memo(function BatchActionButton({ className, }: BatchActionButtonProps) { const progress = totalCount > 0 ? (completedCount / totalCount) * 100 : 0 + const isResumeDisabled = isPaused && inFlightCount > 0 // Show in-flight indicator when paused and items are still processing const showInFlightIndicator = isPaused && inFlightCount > 0 @@ -94,6 +95,7 @@ export const BatchActionButton = React.memo(function BatchActionButton({ {/* The actual button - positioned above progress */}