Commit 03db072
committed
fix(windows): retry ENOENT errors and add delays to prevent file access race conditions
Windows file operations are asynchronous at the OS level. After writeFile()
completes, the filesystem may not immediately make the file accessible, causing
ENOENT errors when attempting to read files immediately after writing.
Root Cause Analysis:
The issue manifested in two places:
1. Production code: retryWrite() only retried EPERM/EBUSY, missing ENOENT
2. Test code: Tests read files immediately after save() without waiting for
filesystem to stabilize
Solution:
Production Code (src/json/edit.ts):
- Add ENOENT to retriable error codes (critical fix)
- Implement progressive retry strategy:
* Initial 50ms delay after write for OS flush
* Up to 5 access verification attempts with exponential backoff
(20ms, 40ms, 60ms, 80ms, 100ms)
* 10ms stabilization delay after successful access
* Maximum total wait: 360ms (50 + 300 + 10)
Test Code (test/unit/json.test.ts):
- Add waitForFile() helper function
- Calls sleep(50ms) on Windows after save operations
- Applied to three tests that were racing against filesystem:
* "should preserve line endings"
* "should support sort option"
* "should use default 2-space indent for new files"
The delays are calibrated for Windows CI runners which exhibit significantly
slower filesystem operations than local development environments. The
combination of production retry logic and test delays provides comprehensive
protection against Windows filesystem timing issues.
Technical Details:
- Platform-specific: Windows only (process.platform === 'win32')
- No performance impact on non-Windows platforms
- Tests pass reliably on macOS, Linux, and Windows CI1 parent 1fb817e commit 03db072
2 files changed
+45
-5
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
| 6 | + | |
5 | 7 | | |
6 | 8 | | |
7 | 9 | | |
| |||
58 | 60 | | |
59 | 61 | | |
60 | 62 | | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
61 | 90 | | |
62 | 91 | | |
63 | 92 | | |
64 | | - | |
| 93 | + | |
65 | 94 | | |
66 | 95 | | |
67 | | - | |
| 96 | + | |
68 | 97 | | |
69 | | - | |
70 | | - | |
| 98 | + | |
| 99 | + | |
71 | 100 | | |
72 | 101 | | |
73 | 102 | | |
74 | 103 | | |
75 | 104 | | |
76 | 105 | | |
77 | | - | |
| 106 | + | |
78 | 107 | | |
79 | 108 | | |
80 | 109 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
761 | 761 | | |
762 | 762 | | |
763 | 763 | | |
| 764 | + | |
| 765 | + | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
764 | 772 | | |
765 | 773 | | |
766 | 774 | | |
| |||
1070 | 1078 | | |
1071 | 1079 | | |
1072 | 1080 | | |
| 1081 | + | |
1073 | 1082 | | |
1074 | 1083 | | |
1075 | 1084 | | |
| |||
1091 | 1100 | | |
1092 | 1101 | | |
1093 | 1102 | | |
| 1103 | + | |
1094 | 1104 | | |
1095 | 1105 | | |
1096 | 1106 | | |
| |||
1116 | 1126 | | |
1117 | 1127 | | |
1118 | 1128 | | |
| 1129 | + | |
1119 | 1130 | | |
1120 | 1131 | | |
1121 | 1132 | | |
| |||
0 commit comments