Skip to content
Merged
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
2 changes: 1 addition & 1 deletion src/domain/datastore/user_datastore_loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ export class UserDatastoreLoader {
},
null,
);
if (newestSourceMtime && bundleStat.mtime > newestSourceMtime) {
if (newestSourceMtime && bundleStat.mtime >= newestSourceMtime) {
logger.debug`Using cached datastore bundle for ${relativePath}`;
return await Deno.readTextFile(bundlePath);
}
Expand Down
2 changes: 1 addition & 1 deletion src/domain/drivers/user_driver_loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ export class UserDriverLoader {
},
null,
);
if (newestSourceMtime && bundleStat.mtime > newestSourceMtime) {
if (newestSourceMtime && bundleStat.mtime >= newestSourceMtime) {
logger.debug`Using cached driver bundle for ${relativePath}`;
return await Deno.readTextFile(bundlePath);
}
Expand Down
2 changes: 1 addition & 1 deletion src/domain/models/user_model_loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1156,7 +1156,7 @@ export class UserModelLoader {
},
null,
);
if (newestSourceMtime && bundleStat.mtime > newestSourceMtime) {
if (newestSourceMtime && bundleStat.mtime >= newestSourceMtime) {
logger.debug`Using cached bundle for ${relativePath}`;
return await Deno.readTextFile(bundlePath);
}
Expand Down
66 changes: 66 additions & 0 deletions src/domain/models/user_model_loader_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2539,6 +2539,72 @@ export const model = {
}
});

Deno.test("UserModelLoader bundleWithCache uses cache when source and bundle have equal mtimes", async () => {
const ts = Date.now();
const modelCode = `
import { z } from "npm:zod@4";

export const model = {
type: "@user/equal-mtime-${ts}",
version: "2026.02.09.1",
methods: {
run: {
description: "Run",
arguments: z.object({}),
execute: async () => ({ dataHandles: [] }),
},
},
};
`;

const repoDir = await Deno.makeTempDir({
prefix: "swamp_equal_mtime_repo_",
});
const modelsDir = await Deno.makeTempDir({
prefix: "swamp_equal_mtime_models_",
});

try {
// Write model and load to produce cached bundle
await Deno.writeTextFile(join(modelsDir, "model.ts"), modelCode);
const loader1 = new UserModelLoader(testDenoRuntime, repoDir);
await loader1.loadModels(modelsDir);

const ns = bundleNamespace(modelsDir, repoDir);
const bundlePath = join(repoDir, ".swamp", "bundles", ns, "model.js");
const cachedBundle = await Deno.readTextFile(bundlePath);

// Set source and bundle to the exact same mtime
const sharedMtime = new Date("2026-01-01T00:00:00Z");
await Deno.utime(join(modelsDir, "model.ts"), sharedMtime, sharedMtime);
await Deno.utime(bundlePath, sharedMtime, sharedMtime);

// Load again — should use cached bundle, not rebundle
const loader2 = new UserModelLoader(testDenoRuntime, repoDir);
await loader2.loadModels(modelsDir);

const bundleAfter = await Deno.readTextFile(bundlePath);

// Bundle content should be identical (cache was used, not rebundled)
assertEquals(
cachedBundle,
bundleAfter,
"Bundle content should be unchanged when source and bundle have equal mtimes",
);

// Bundle mtime should still be the shared time (not updated by a rebundle)
const bundleStatAfter = await Deno.stat(bundlePath);
assertEquals(
bundleStatAfter.mtime?.getTime(),
sharedMtime.getTime(),
"Bundle mtime should be unchanged — cache was used, no rebundle occurred",
);
} finally {
await Deno.remove(repoDir, { recursive: true });
await Deno.remove(modelsDir, { recursive: true });
}
});

Deno.test("UserModelLoader: accepts optional DatastorePathResolver", () => {
// Verify the constructor accepts a resolver without errors
const mockResolver = {
Expand Down
2 changes: 1 addition & 1 deletion src/domain/reports/user_report_loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,7 @@ export class UserReportLoader {
},
null,
);
if (newestSourceMtime && bundleStat.mtime > newestSourceMtime) {
if (newestSourceMtime && bundleStat.mtime >= newestSourceMtime) {
logger.debug`Using cached report bundle for ${relativePath}`;
return await Deno.readTextFile(bundlePath);
}
Expand Down
2 changes: 1 addition & 1 deletion src/domain/vaults/user_vault_loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ export class UserVaultLoader {
},
null,
);
if (newestSourceMtime && bundleStat.mtime > newestSourceMtime) {
if (newestSourceMtime && bundleStat.mtime >= newestSourceMtime) {
logger.debug`Using cached vault bundle for ${relativePath}`;
return await Deno.readTextFile(bundlePath);
}
Expand Down
Loading