@@ -222,50 +222,61 @@ export async function performCreateWorkflowTransition(
222222 params : PerformCreateWorkflowParams
223223) : Promise < PerformCreateWorkflowResult > {
224224 const requestId = params . requestId ?? generateRequestId ( )
225+ const workflowId = params . id || generateId ( )
225226 const folderId = params . folderId || null
226227
227228 if ( ! ( await isFolderInWorkspace ( folderId , params . workspaceId ) ) ) {
228229 return { success : false , error : 'Target folder not found' , errorCode : 'validation' }
229230 }
230231
232+ let name = params . name
233+
231234 if ( ! params . deduplicate ) {
232235 const duplicate = await workflowNameExistsInFolder ( {
233236 workspaceId : params . workspaceId ,
234- name : params . name ,
237+ name,
235238 folderId,
236239 } )
237240 if ( duplicate ) {
238241 return {
239242 success : false ,
240- error : `A workflow named "${ params . name } " already exists in this folder` ,
243+ error : `A workflow named "${ name } " already exists in this folder` ,
241244 errorCode : 'conflict' ,
242245 }
243246 }
244247 }
245248
246- const row = await buildNewWorkflowRow ( db , {
247- id : params . id || generateId ( ) ,
248- userId : params . userId ,
249- workspaceId : params . workspaceId ,
250- folderId,
251- name : params . name ,
252- description : params . description ?? null ,
253- sortOrder : params . sortOrder ?? ( await nextWorkflowSortOrder ( params . workspaceId , folderId ) ) ,
254- } )
249+ const sortOrder =
250+ params . sortOrder !== undefined
251+ ? params . sortOrder
252+ : await nextWorkflowSortOrder ( params . workspaceId , folderId )
253+ const now = new Date ( )
255254 const { workflowState, subBlockValues, startBlockId } = buildDefaultWorkflowArtifacts ( )
256255
257256 const maxAttempts = params . deduplicate ? WORKFLOW_NAME_DEDUPLICATION_ATTEMPTS : 1
258257 for ( let attempt = 0 ; attempt < maxAttempts ; attempt += 1 ) {
259258 if ( params . deduplicate ) {
260- row . name = await deduplicateWorkflowName ( params . name , params . workspaceId , folderId )
259+ name = await deduplicateWorkflowName ( params . name , params . workspaceId , folderId )
261260 }
262261
263262 try {
264263 await db . transaction ( async ( tx ) => {
264+ // Built per attempt inside the insert transaction, so the fork-sync policy is read
265+ // with the write rather than carried across retries.
266+ const row = await buildNewWorkflowRow ( tx , {
267+ id : workflowId ,
268+ userId : params . userId ,
269+ workspaceId : params . workspaceId ,
270+ folderId,
271+ name,
272+ description : params . description ?? null ,
273+ sortOrder,
274+ now,
275+ } )
265276 await tx . insert ( workflow ) . values ( row )
266277
267278 await saveWorkflowToNormalizedTables (
268- row . id ,
279+ workflowId ,
269280 workflowState ,
270281 {
271282 /**
@@ -297,31 +308,31 @@ export async function performCreateWorkflowTransition(
297308 if ( ! params . deduplicate || attempt === maxAttempts - 1 ) {
298309 return {
299310 success : false ,
300- error : `A workflow named "${ row . name } " already exists in this folder` ,
311+ error : `A workflow named "${ name } " already exists in this folder` ,
301312 errorCode : 'conflict' ,
302313 }
303314 }
304315
305316 logger . warn ( `[${ requestId } ] Workflow name was claimed during creation; retrying` , {
306- name : row . name ,
317+ name,
307318 attempt : attempt + 1 ,
308319 } )
309320 }
310321 }
311322
312- logger . info ( `[${ requestId } ] Successfully created workflow ${ row . id } ` )
323+ logger . info ( `[${ requestId } ] Successfully created workflow ${ workflowId } ` )
313324
314325 return {
315326 success : true ,
316327 workflow : {
317- id : row . id ,
318- name : row . name ,
328+ id : workflowId ,
329+ name,
319330 description : params . description ,
320331 workspaceId : params . workspaceId ,
321332 folderId,
322- sortOrder : row . sortOrder ,
323- createdAt : row . createdAt ,
324- updatedAt : row . updatedAt ,
333+ sortOrder,
334+ createdAt : now ,
335+ updatedAt : now ,
325336 startBlockId,
326337 subBlockValues,
327338 } ,
0 commit comments