mirror of
https://github.com/nexu-io/open-design.git
synced 2026-06-01 03:14:35 +07:00
fix(daemon): tolerate coarse artifact mtimes
This commit is contained in:
parent
755d8173df
commit
67396350c8
3 changed files with 13 additions and 3 deletions
|
|
@ -32,10 +32,16 @@ const FORBIDDEN_SEGMENT = /^$|^\.\.?$/;
|
||||||
const RESERVED_PROJECT_FILE_SEGMENTS = new Set(['.live-artifacts']);
|
const RESERVED_PROJECT_FILE_SEGMENTS = new Set(['.live-artifacts']);
|
||||||
const DESIGN_HANDOFF_FILENAME = 'DESIGN-HANDOFF.md';
|
const DESIGN_HANDOFF_FILENAME = 'DESIGN-HANDOFF.md';
|
||||||
const DESIGN_MANIFEST_FILENAME = 'DESIGN-MANIFEST.json';
|
const DESIGN_MANIFEST_FILENAME = 'DESIGN-MANIFEST.json';
|
||||||
|
export const RUN_ARTIFACT_RECONCILE_MTIME_GRACE_MS = 1000;
|
||||||
export const projectFileRenameTestHooks = {
|
export const projectFileRenameTestHooks = {
|
||||||
beforeCommit: null as null | ((paths: { source: string; target: string }) => Promise<void> | void),
|
beforeCommit: null as null | ((paths: { source: string; target: string }) => Promise<void> | void),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function isRunTouchedProjectFile(fileMtimeMs, runStartTimeMs) {
|
||||||
|
if (!Number.isFinite(fileMtimeMs) || !Number.isFinite(runStartTimeMs)) return false;
|
||||||
|
return fileMtimeMs + RUN_ARTIFACT_RECONCILE_MTIME_GRACE_MS >= runStartTimeMs;
|
||||||
|
}
|
||||||
|
|
||||||
export function projectDir(projectsRoot, projectId) {
|
export function projectDir(projectsRoot, projectId) {
|
||||||
if (!isSafeId(projectId)) throw new Error('invalid project id');
|
if (!isSafeId(projectId)) throw new Error('invalid project id');
|
||||||
return path.join(projectsRoot, projectId);
|
return path.join(projectsRoot, projectId);
|
||||||
|
|
|
||||||
|
|
@ -353,6 +353,7 @@ import {
|
||||||
assertSandboxProjectRootAvailable,
|
assertSandboxProjectRootAvailable,
|
||||||
detectEntryFile,
|
detectEntryFile,
|
||||||
ensureProject,
|
ensureProject,
|
||||||
|
isRunTouchedProjectFile,
|
||||||
isSafeId,
|
isSafeId,
|
||||||
listFiles,
|
listFiles,
|
||||||
mimeFor,
|
mimeFor,
|
||||||
|
|
@ -12751,7 +12752,7 @@ export async function startServer({
|
||||||
try {
|
try {
|
||||||
const filePath = path.join(dir, f.name);
|
const filePath = path.join(dir, f.name);
|
||||||
const st = await fs.promises.stat(filePath);
|
const st = await fs.promises.stat(filePath);
|
||||||
if (st.mtimeMs < runStartTimeMs) continue;
|
if (!isRunTouchedProjectFile(st.mtimeMs, runStartTimeMs)) continue;
|
||||||
await reconcileHtmlArtifactManifest(
|
await reconcileHtmlArtifactManifest(
|
||||||
PROJECTS_DIR,
|
PROJECTS_DIR,
|
||||||
run.projectId,
|
run.projectId,
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import fs from 'node:fs';
|
||||||
import os from 'node:os';
|
import os from 'node:os';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { closeDatabase, insertProject, openDatabase } from '../src/db.js';
|
import { closeDatabase, insertProject, openDatabase } from '../src/db.js';
|
||||||
import { reconcileHtmlArtifactManifest, writeProjectFile } from '../src/projects.js';
|
import { isRunTouchedProjectFile, reconcileHtmlArtifactManifest, writeProjectFile } from '../src/projects.js';
|
||||||
|
|
||||||
const PROJECT_ID = 'reconcile-test';
|
const PROJECT_ID = 'reconcile-test';
|
||||||
let tempDir = null;
|
let tempDir = null;
|
||||||
|
|
@ -146,6 +146,9 @@ describe('run-end artifact manifest reconciliation (#2893)', () => {
|
||||||
|
|
||||||
// File written during the run
|
// File written during the run
|
||||||
await writeProjectFile(projectsRoot, PROJECT_ID, 'new-output.html', '<p>new</p>');
|
await writeProjectFile(projectsRoot, PROJECT_ID, 'new-output.html', '<p>new</p>');
|
||||||
|
const newPath = path.join(projectsRoot, PROJECT_ID, 'new-output.html');
|
||||||
|
const coarseFsTime = new Date(runStartTimeMs - 500);
|
||||||
|
fs.utimesSync(newPath, coarseFsTime, coarseFsTime);
|
||||||
|
|
||||||
// Simulate the close-handler reconciliation with mtime filter
|
// Simulate the close-handler reconciliation with mtime filter
|
||||||
const dir = path.join(projectsRoot, PROJECT_ID);
|
const dir = path.join(projectsRoot, PROJECT_ID);
|
||||||
|
|
@ -154,7 +157,7 @@ describe('run-end artifact manifest reconciliation (#2893)', () => {
|
||||||
const ext = path.extname(name).toLowerCase();
|
const ext = path.extname(name).toLowerCase();
|
||||||
if (ext !== '.html' && ext !== '.htm') continue;
|
if (ext !== '.html' && ext !== '.htm') continue;
|
||||||
const st = fs.statSync(path.join(dir, name));
|
const st = fs.statSync(path.join(dir, name));
|
||||||
if (st.mtimeMs < runStartTimeMs) continue;
|
if (!isRunTouchedProjectFile(st.mtimeMs, runStartTimeMs)) continue;
|
||||||
await reconcileHtmlArtifactManifest(projectsRoot, PROJECT_ID, name);
|
await reconcileHtmlArtifactManifest(projectsRoot, PROJECT_ID, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue