Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/moody-islands-stare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@workflow/next": patch
---

Validate cached workflows/steps and reduce build debounce
34 changes: 31 additions & 3 deletions packages/next/src/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { constants } from 'node:fs';
import { access, mkdir, readFile, stat, writeFile } from 'node:fs/promises';
import os from 'node:os';
import { join, resolve } from 'node:path';
import { useStepPattern, useWorkflowPattern } from '@workflow/builders';
import type { NextConfig } from 'next';
import {
createSocketServer,
Expand Down Expand Up @@ -67,9 +68,36 @@ export async function getNextBuilder() {
try {
const cacheContent = await readFile(cacheFile, 'utf-8');
const cacheData = JSON.parse(cacheContent);

// Filter workflow files: check they exist and contain "use workflow"
const workflowFiles: string[] = [];
for (const file of cacheData.workflowFiles || []) {
try {
const content = await readFile(file, 'utf-8');
if (useWorkflowPattern.test(content)) {
workflowFiles.push(file);
}
} catch {
// File doesn't exist or can't be read, skip it
}
}

// Filter step files: check they exist and contain "use step"
const stepFiles: string[] = [];
for (const file of cacheData.stepFiles || []) {
try {
const content = await readFile(file, 'utf-8');
if (useStepPattern.test(content)) {
stepFiles.push(file);
}
} catch {
// File doesn't exist or can't be read, skip it
}
}

return {
workflowFiles: cacheData.workflowFiles || [],
stepFiles: cacheData.stepFiles || [],
workflowFiles,
stepFiles,
};
} catch {
// Cache file doesn't exist or is invalid, return null
Expand Down Expand Up @@ -261,7 +289,7 @@ export async function getNextBuilder() {
const stepFiles = new Set<string>();
let debounceTimer: NodeJS.Timeout | null = null;
let buildTriggered = false;
const BUILD_DEBOUNCE_MS = this.isDevServer ? 500 : 2_000;
const BUILD_DEBOUNCE_MS = this.isDevServer ? 250 : 1_000;

// Attempt to load cached workflows/steps from previous build
const cache = await this.readWorkflowsCache();
Expand Down
14 changes: 14 additions & 0 deletions packages/next/src/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,20 @@ async function waitForBuildComplete(): Promise<void> {
socket.on('error', onError);
socket.on('end', onEnd);
socket.on('close', onClose);

const authToken = process.env.WORKFLOW_SOCKET_AUTH;

if (!authToken) {
throw new Error(
`Invariant: no socket auth token provided for workflow loader`
);
}
// we trigger a build here in case no other events trigger
// the build so that we aren't waiting until 60 second timeout
const message: SocketMessage = {
type: 'trigger-build',
};
socket.write(serializeMessage(message, authToken));
});
}

Expand Down
Loading