Enable offline canvas create sync with optimistic ID remapping

This commit is contained in:
Matthias
2026-04-01 10:19:50 +02:00
parent 32bd188d89
commit da576c1400
9 changed files with 904 additions and 57 deletions

View File

@@ -1,6 +1,7 @@
import { query, mutation } from "./_generated/server";
import { v } from "convex/values";
import { requireAuth } from "./helpers";
import type { Id } from "./_generated/dataModel";
// ============================================================================
// Queries
@@ -39,6 +40,7 @@ export const create = mutation({
targetNodeId: v.id("nodes"),
sourceHandle: v.optional(v.string()),
targetHandle: v.optional(v.string()),
clientRequestId: v.optional(v.string()),
},
handler: async (ctx, args) => {
const user = await requireAuth(ctx);
@@ -47,6 +49,31 @@ export const create = mutation({
throw new Error("Canvas not found");
}
const getExistingEdge = async (): Promise<Id<"edges"> | null> => {
const clientRequestId = args.clientRequestId;
if (!clientRequestId) return null;
const existing = await ctx.db
.query("mutationRequests")
.withIndex("by_user_mutation_request", (q) =>
q
.eq("userId", user.userId)
.eq("mutation", "edges.create")
.eq("clientRequestId", clientRequestId),
)
.first();
if (!existing) return null;
if (existing.canvasId && existing.canvasId !== args.canvasId) {
throw new Error("Client request conflict");
}
if (!existing.edgeId) return null;
return existing.edgeId;
};
const existingEdgeId = await getExistingEdge();
if (existingEdgeId) {
return existingEdgeId;
}
// Prüfen ob beide Nodes existieren und zum gleichen Canvas gehören
const source = await ctx.db.get(args.sourceNodeId);
const target = await ctx.db.get(args.targetNodeId);
@@ -71,6 +98,16 @@ export const create = mutation({
});
await ctx.db.patch(args.canvasId, { updatedAt: Date.now() });
if (args.clientRequestId) {
await ctx.db.insert("mutationRequests", {
userId: user.userId,
mutation: "edges.create",
clientRequestId: args.clientRequestId,
canvasId: args.canvasId,
edgeId,
createdAt: Date.now(),
});
}
return edgeId;
},
});