feat(sync): syncing workflow deletion

This commit is contained in:
Emir Karabeg
2025-02-18 20:02:46 -08:00
parent 0c2439fc9d
commit 666e23fc12
4 changed files with 39 additions and 6 deletions

View File

@@ -1,5 +1,5 @@
import { NextResponse } from 'next/server'
import { eq } from 'drizzle-orm'
import { eq, sql } from 'drizzle-orm'
import { z } from 'zod'
import { getSession } from '@/lib/auth'
import { db } from '@/db'
@@ -16,6 +16,7 @@ const WorkflowSchema = z.object({
// Define the schema for batch sync
const BatchSyncSchema = z.object({
workflows: z.array(WorkflowSchema),
deletedWorkflowIds: z.array(z.string()).optional(),
})
export async function POST(request: Request) {
@@ -26,11 +27,21 @@ export async function POST(request: Request) {
}
const body = await request.json()
const { workflows } = BatchSyncSchema.parse(body)
const { workflows, deletedWorkflowIds } = BatchSyncSchema.parse(body)
const now = new Date()
// Process all workflows in a single transaction
// Process all operations in a single transaction
await db.transaction(async (tx) => {
// Handle deletions first
if (deletedWorkflowIds?.length) {
await tx
.delete(workflow)
.where(
sql`${workflow.id} IN ${deletedWorkflowIds} AND ${workflow.userId} = ${session.user.id}`
)
}
// Handle updates/inserts
for (const workflowData of workflows) {
await tx
.insert(workflow)

View File

@@ -4,7 +4,7 @@ import { useExecutionStore } from './execution/store'
import { useNotificationStore } from './notifications/store'
import { useEnvironmentStore } from './settings/environment/store'
import { useGeneralStore } from './settings/general/store'
import { initializeSyncManager } from './sync-manager'
import { addDeletedWorkflow, initializeSyncManager } from './sync-manager'
import { useWorkflowRegistry } from './workflow/registry/store'
import { useWorkflowStore } from './workflow/store'
@@ -15,8 +15,14 @@ if (typeof window !== 'undefined') {
// Reset all application stores to their initial state
export const resetAllStores = () => {
// Selectively clear localStorage items
// Track all workflow IDs for deletion before clearing
if (typeof window !== 'undefined') {
const workflowRegistry = useWorkflowRegistry.getState().workflows
Object.keys(workflowRegistry).forEach((id) => {
addDeletedWorkflow(id)
})
// Selectively clear localStorage items
const keysToKeep = ['next-favicon']
const keysToRemove = Object.keys(localStorage).filter((key) => !keysToKeep.includes(key))
keysToRemove.forEach((key) => localStorage.removeItem(key))

View File

@@ -8,12 +8,22 @@ interface WorkflowSyncPayload {
state: string
}
// Track deleted workflow IDs until they're synced
const deletedWorkflowIds = new Set<string>()
export function addDeletedWorkflow(id: string) {
deletedWorkflowIds.add(id)
}
async function syncWorkflowsToServer(payloads: WorkflowSyncPayload[]): Promise<boolean> {
try {
const response = await fetch('/api/db/sync', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ workflows: payloads }),
body: JSON.stringify({
workflows: payloads,
deletedWorkflowIds: Array.from(deletedWorkflowIds),
}),
keepalive: true,
})
@@ -25,6 +35,8 @@ async function syncWorkflowsToServer(payloads: WorkflowSyncPayload[]): Promise<b
throw new Error(`Batch sync failed: ${response.statusText}`)
}
// Clear the deleted IDs set after successful sync
deletedWorkflowIds.clear()
console.log('Workflows synced successfully')
return true
} catch (error) {

View File

@@ -1,5 +1,6 @@
import { create } from 'zustand'
import { devtools } from 'zustand/middleware'
import { addDeletedWorkflow } from '../../sync-manager'
import { useWorkflowStore } from '../store'
import { useSubBlockStore } from '../subblock/store'
import { WorkflowMetadata, WorkflowRegistry } from './types'
@@ -231,6 +232,9 @@ export const useWorkflowRegistry = create<WorkflowRegistry>()(
const newWorkflows = { ...state.workflows }
delete newWorkflows[id]
// Track deletion for next sync
addDeletedWorkflow(id)
// Remove workflow state from localStorage
localStorage.removeItem(`workflow-${id}`)