@@ -152,14 +152,21 @@ export abstract class Loader {
152
152
else effects . output . write ( faint ( "[stale] " ) ) ;
153
153
} else return effects . output . write ( faint ( "[fresh] " ) ) , outputPath ;
154
154
const tempPath = join ( this . sourceRoot , ".observablehq" , "cache" , `${ this . targetPath } .${ process . pid } ` ) ;
155
+ const errorPath = tempPath + ".err" ;
156
+ const errorStat = await maybeStat ( errorPath ) ;
157
+ if ( errorStat ) {
158
+ if ( errorStat . mtimeMs > loaderStat ! . mtimeMs && errorStat . mtimeMs > - 1000 + Date . now ( ) )
159
+ throw new Error ( "loader skipped due to recent error" ) ;
160
+ else await unlink ( errorPath ) . catch ( ( ) => { } ) ;
161
+ }
155
162
await prepareOutput ( tempPath ) ;
156
163
const tempFd = await open ( tempPath , "w" ) ;
157
164
try {
158
165
await this . exec ( tempFd . createWriteStream ( { highWaterMark : 1024 * 1024 } ) , effects ) ;
159
166
await mkdir ( dirname ( cachePath ) , { recursive : true } ) ;
160
167
await rename ( tempPath , cachePath ) ;
161
168
} catch ( error ) {
162
- await unlink ( tempPath ) ;
169
+ await rename ( tempPath , errorPath ) ;
163
170
throw error ;
164
171
} finally {
165
172
await tempFd . close ( ) ;
@@ -223,7 +230,7 @@ class CommandLoader extends Loader {
223
230
subprocess . on ( "close" , resolve ) ;
224
231
} ) ;
225
232
if ( code !== 0 ) {
226
- throw new Error ( `exited with code ${ code } ` ) ;
233
+ throw new Error ( `loader exited with code ${ code } ` ) ;
227
234
}
228
235
}
229
236
}
0 commit comments