Show upload progress and fix credit concurrency user scope
- Replace image upload POST with XHR progress tracking - Keep upload state until Convex sync completes - Pass owner userId through image generation to decrement concurrency correctly
This commit is contained in:
26
convex/ai.ts
26
convex/ai.ts
@@ -346,8 +346,16 @@ export const processImageGeneration = internalAction({
|
||||
aspectRatio: v.optional(v.string()),
|
||||
reservationId: v.optional(v.id("creditTransactions")),
|
||||
shouldDecrementConcurrency: v.boolean(),
|
||||
userId: v.string(),
|
||||
},
|
||||
handler: async (ctx, args) => {
|
||||
console.info("[processImageGeneration] start", {
|
||||
nodeId: args.nodeId,
|
||||
reservationId: args.reservationId ?? null,
|
||||
shouldDecrementConcurrency: args.shouldDecrementConcurrency,
|
||||
userId: args.userId,
|
||||
});
|
||||
|
||||
let retryCount = 0;
|
||||
|
||||
try {
|
||||
@@ -394,7 +402,9 @@ export const processImageGeneration = internalAction({
|
||||
});
|
||||
} finally {
|
||||
if (args.shouldDecrementConcurrency) {
|
||||
await ctx.runMutation(internal.credits.decrementConcurrency, {});
|
||||
await ctx.runMutation(internal.credits.decrementConcurrency, {
|
||||
userId: args.userId,
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -411,6 +421,15 @@ export const generateImage = action({
|
||||
aspectRatio: v.optional(v.string()),
|
||||
},
|
||||
handler: async (ctx, args) => {
|
||||
const canvas = await ctx.runQuery(api.canvases.get, {
|
||||
canvasId: args.canvasId,
|
||||
});
|
||||
if (!canvas) {
|
||||
throw new Error("Canvas not found");
|
||||
}
|
||||
|
||||
const userId = canvas.ownerId;
|
||||
|
||||
const internalCreditsEnabled =
|
||||
process.env.INTERNAL_CREDITS_ENABLED === "true";
|
||||
|
||||
@@ -455,6 +474,7 @@ export const generateImage = action({
|
||||
aspectRatio: args.aspectRatio,
|
||||
reservationId: reservationId ?? undefined,
|
||||
shouldDecrementConcurrency: usageIncremented,
|
||||
userId,
|
||||
});
|
||||
backgroundJobScheduled = true;
|
||||
return { queued: true as const, nodeId: args.nodeId };
|
||||
@@ -478,7 +498,9 @@ export const generateImage = action({
|
||||
throw error;
|
||||
} finally {
|
||||
if (usageIncremented && !backgroundJobScheduled) {
|
||||
await ctx.runMutation(internal.credits.decrementConcurrency, {});
|
||||
await ctx.runMutation(internal.credits.decrementConcurrency, {
|
||||
userId,
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -833,15 +833,18 @@ export const incrementUsage = internalMutation({
|
||||
* (commit/release übernehmen das bei aktivierten Credits).
|
||||
*/
|
||||
export const decrementConcurrency = internalMutation({
|
||||
args: {},
|
||||
handler: async (ctx) => {
|
||||
const user = await requireAuth(ctx);
|
||||
args: {
|
||||
userId: v.optional(v.string()),
|
||||
},
|
||||
handler: async (ctx, args) => {
|
||||
const resolvedUserId =
|
||||
args.userId ?? (await requireAuth(ctx)).userId;
|
||||
const today = new Date().toISOString().split("T")[0];
|
||||
|
||||
const usage = await ctx.db
|
||||
.query("dailyUsage")
|
||||
.withIndex("by_user_date", (q) =>
|
||||
q.eq("userId", user.userId).eq("date", today)
|
||||
q.eq("userId", resolvedUserId).eq("date", today)
|
||||
)
|
||||
.unique();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user