Skip to content

Commit

Permalink
Handle invalid clockspec error and log more when loading cache fails (#…
Browse files Browse the repository at this point in the history
…9709)

* catch any error during reading request graph and log snapshot file in case watchman fails reading it

* log clockspec and other errors separately

* remove redundant if check

* use existing snapshot path

* clean up commit

* extract new logging to function

---------

Co-authored-by: ngrujic <[email protected]>
  • Loading branch information
Nikola-3 and ngrujic authored May 16, 2024
1 parent fa4bb34 commit d58c1ce
Showing 1 changed file with 71 additions and 36 deletions.
107 changes: 71 additions & 36 deletions packages/core/core/src/RequestTracker.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ export const requestGraphEdgeTypes = {
dirname: 7,
};

class FSBailoutError extends Error {
name: string = 'FSBailoutError';
}

export type RequestGraphEdgeType = $Values<typeof requestGraphEdgeTypes>;

type RequestGraphOpts = {|
Expand Down Expand Up @@ -855,7 +859,7 @@ export class RequestGraph extends ContentGraph<
predictedTime,
},
});
throw new Error(
throw new FSBailoutError(
'Responding to file system events exceeded threshold, start with empty cache.',
);
}
Expand Down Expand Up @@ -1543,55 +1547,58 @@ async function loadRequestGraph(options): Async<RequestGraph> {

let cacheKey = getCacheKey(options);
let requestGraphKey = `requestGraph-${cacheKey}`;

let timeout;
const snapshotKey = `snapshot-${cacheKey}`;
const snapshotPath = path.join(options.cacheDir, snapshotKey + '.txt');
if (await options.cache.hasLargeBlob(requestGraphKey)) {
let {requestGraph} = await readAndDeserializeRequestGraph(
options.cache,
requestGraphKey,
cacheKey,
);
try {
let {requestGraph} = await readAndDeserializeRequestGraph(
options.cache,
requestGraphKey,
cacheKey,
);

let opts = getWatcherOptions(options);
let snapshotKey = `snapshot-${cacheKey}`;
let snapshotPath = path.join(options.cacheDir, snapshotKey + '.txt');
let opts = getWatcherOptions(options);

timeout = setTimeout(() => {
logger.warn({
origin: '@parcel/core',
message: `Retrieving file system events since last build...\nThis can take upto a minute after branch changes or npm/yarn installs.`,
});
}, 5000);
let startTime = Date.now();
let events = await options.inputFS.getEventsSince(
options.watchDir,
snapshotPath,
opts,
);
clearTimeout(timeout);

let timeout = setTimeout(() => {
logger.warn({
logger.verbose({
origin: '@parcel/core',
message: `Retrieving file system events since last build...\nThis can take upto a minute after branch changes or npm/yarn installs.`,
message: `File system event count: ${events.length}`,
meta: {
trackableEvent: 'watcher_events_count',
watcherEventCount: events.length,
duration: Date.now() - startTime,
},
});
}, 5000);
let startTime = Date.now();
let events = await options.inputFS.getEventsSince(
options.watchDir,
snapshotPath,
opts,
);
clearTimeout(timeout);

logger.verbose({
origin: '@parcel/core',
message: `File system event count: ${events.length}`,
meta: {
trackableEvent: 'watcher_events_count',
watcherEventCount: events.length,
duration: Date.now() - startTime,
},
});

requestGraph.invalidateUnpredictableNodes();
requestGraph.invalidateOnBuildNodes();
requestGraph.invalidateEnvNodes(options.env);
requestGraph.invalidateOptionNodes(options);
requestGraph.invalidateUnpredictableNodes();
requestGraph.invalidateOnBuildNodes();
requestGraph.invalidateEnvNodes(options.env);
requestGraph.invalidateOptionNodes(options);

try {
await requestGraph.respondToFSEvents(
options.unstableFileInvalidations || events,
options,
10000,
);
return requestGraph;
} catch (e) {
// Prevent logging fs events took too long warning
clearTimeout(timeout);
logErrorOnBailout(options, snapshotPath, e);
// This error means respondToFSEvents timed out handling the invalidation events
// In this case we'll return a fresh RequestGraph
return new RequestGraph();
Expand All @@ -1600,3 +1607,31 @@ async function loadRequestGraph(options): Async<RequestGraph> {

return new RequestGraph();
}
function logErrorOnBailout(
options: ParcelOptions,
snapshotPath: string,
e: Error,
): void {
if (e.message && e.message.includes('invalid clockspec')) {
const snapshotContents = options.inputFS.readFileSync(
snapshotPath,
'utf-8',
);
logger.warn({
origin: '@parcel/core',
message: `Error reading clockspec from snapshot, building with clean cache.`,
meta: {
snapshotContents: snapshotContents,
trackableEvent: 'invalid_clockspec_error',
},
});
} else if (!(e instanceof FSBailoutError)) {
logger.warn({
origin: '@parcel/core',
message: `Unexpected error loading cache from disk, building with clean cache.`,
meta: {
trackableEvent: 'cache_load_error',
},
});
}
}

0 comments on commit d58c1ce

Please sign in to comment.