Skip to content

Commit 5e47385

Browse files
authored
Fix watcher cleanup, empty-reload guard, and stale README (#43)
## Summary Post-merge follow-up to PR #40. Addresses 3 findings from code review: - Watcher error handler now clears debounce timer and closes FSWatcher to avoid indeterminate state after fs.watch errors - Reload guards against replacing fixtures with empty array on parse failure, preserving previous working fixtures - Update README Future Direction to reflect that `--validate-on-load` and `validateFixtures()` now exist ## Test plan - [x] All 565 existing tests pass - [ ] Manually verify watcher error recovery (kill the watched file's filesystem) - [ ] Verify reload with invalid JSON preserves previous fixtures
2 parents fb0b56b + b6d756f commit 5e47385

2 files changed

Lines changed: 15 additions & 1 deletion

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -691,7 +691,7 @@ Areas where llmock could grow, and explicit non-goals for the current scope.
691691

692692
- **Request metadata in predicates**: Predicate functions receive only the `ChatCompletionRequest`, not HTTP headers, method, or URL.
693693
- **Multi-turn conversation state**: Fixtures are stateless — there is no built-in way to sequence responses across multiple requests in a conversation.
694-
- **Validation on load**: Fixture files are not schema-validated at load time; malformed fixtures surface as runtime errors.
694+
- **Validation on load**: Schema validation is available via `--validate-on-load` (CLI) and `validateFixtures()` (programmatic API), but it is opt-in and not enabled by default.
695695
- **Inheritance and aliasing**: No `$ref` or `extends` mechanism for fixture reuse across files.
696696

697697
### Testing

src/watcher.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ export function watchFixtures(
3030
return;
3131
}
3232

33+
if (newFixtures.length === 0 && fixtures.length > 0) {
34+
logger.warn(
35+
"Reload produced 0 fixtures — keeping previous fixtures. Check fixture file for errors.",
36+
);
37+
return;
38+
}
39+
3340
if (validate && validateFn) {
3441
const results = validateFn(newFixtures);
3542
const errors = results.filter((r) => r.severity === "error");
@@ -60,6 +67,13 @@ export function watchFixtures(
6067
});
6168

6269
watcher.on("error", (err: Error) => {
70+
if (debounceTimer) clearTimeout(debounceTimer);
71+
debounceTimer = null;
72+
try {
73+
watcher.close();
74+
} catch {
75+
/* already dead */
76+
}
6377
logger.error(`File watcher error on ${fixturePath}: ${err.message}`);
6478
logger.error("Fixture auto-reload is no longer active. Restart the server to resume watching.");
6579
});

0 commit comments

Comments
 (0)