From 72bbd1ee09fa90d41a3bf598189f7f67038760f3 Mon Sep 17 00:00:00 2001 From: Iris Moini Date: Thu, 30 Nov 2023 13:05:52 -0800 Subject: [PATCH 1/7] Generate initial cache report --- packages/core/core/src/RequestTracker.js | 78 +++++++++++++++++++++--- 1 file changed, 69 insertions(+), 9 deletions(-) diff --git a/packages/core/core/src/RequestTracker.js b/packages/core/core/src/RequestTracker.js index ca3e6d7255b..155e6cde4ee 100644 --- a/packages/core/core/src/RequestTracker.js +++ b/packages/core/core/src/RequestTracker.js @@ -120,6 +120,11 @@ type Request = {| |}; type InvalidateReason = number; +type InvalidationEntry = {| + invalidated: NodeId, + cause?: NodeId, +|}; + type RequestNode = {| id: ContentKey, +type: typeof REQUEST, @@ -233,6 +238,7 @@ export class RequestGraph extends ContentGraph< RequestGraphEdgeType, > { invalidNodeIds: Set = new Set(); + invalidationReport: InvalidationEntry[] = []; incompleteNodeIds: Set = new Set(); incompleteNodePromises: Map> = new Map(); globNodeIds: Set = new Set(); @@ -332,18 +338,19 @@ export class RequestGraph extends ContentGraph< ); } - invalidateNode(nodeId: NodeId, reason: InvalidateReason) { + invalidateNode(nodeId: NodeId, reason: InvalidateReason, cause?: NodeId) { let node = nullthrows(this.getNode(nodeId)); invariant(node.type === REQUEST); node.invalidateReason |= reason; this.invalidNodeIds.add(nodeId); + this.invalidationReport.push({invalidated: nodeId, cause: cause}); let parentNodes = this.getNodeIdsConnectedTo( nodeId, requestGraphEdgeTypes.subrequest, ); for (let parentNode of parentNodes) { - this.invalidateNode(parentNode, reason); + this.invalidateNode(parentNode, reason, nodeId); } } @@ -373,7 +380,7 @@ export class RequestGraph extends ContentGraph< requestGraphEdgeTypes.invalidated_by_update, ); for (let parentNode of parentNodes) { - this.invalidateNode(parentNode, ENV_CHANGE); + this.invalidateNode(parentNode, ENV_CHANGE, nodeId); } } } @@ -391,7 +398,7 @@ export class RequestGraph extends ContentGraph< requestGraphEdgeTypes.invalidated_by_update, ); for (let parentNode of parentNodes) { - this.invalidateNode(parentNode, OPTION_CHANGE); + this.invalidateNode(parentNode, OPTION_CHANGE, nodeId); } } } @@ -710,7 +717,7 @@ export class RequestGraph extends ContentGraph< requestGraphEdgeTypes.invalidated_by_create, ); for (let connectedNode of connectedNodes) { - this.invalidateNode(connectedNode, FILE_CREATE); + this.invalidateNode(connectedNode, FILE_CREATE, matchNodeId); } } } @@ -738,6 +745,58 @@ export class RequestGraph extends ContentGraph< } } + generateInvalidationReport(): void { + let nodes = {}; + let invalidationRelations = {}; + for (let {invalidated, cause} of this.invalidationReport) { + let invalidatedNode = nullthrows(this.getNode(invalidated)); + invariant(invalidatedNode.type === 'request'); + let causeNode = + cause !== undefined ? nullthrows(this.getNode(cause)) : undefined; + + if (invalidatedNode.id === 'Main') { + continue; + } + + if (!invalidationRelations[invalidated]) { + invalidationRelations[invalidated] = []; + } + + if (causeNode && !invalidationRelations[invalidated].includes(cause)) { + invalidationRelations[invalidated].push(cause); + } + + nodes[invalidated] = { + id: invalidatedNode.id, + type: invalidatedNode.type, + requestType: invalidatedNode.requestType, + invalidateReason: invalidatedNode.invalidateReason, + }; + + if (causeNode) { + invariant(cause !== undefined); + let {id, type, requestType, invalidateReason} = causeNode; + nodes[cause] = + requestType !== undefined && invalidateReason !== undefined + ? {id, type, requestType, invalidateReason} + : {id, type}; + } + } + + const fs = require('fs'); + fs.writeFile( + 'cache-invalidation-report.json', + JSON.stringify( + {invalidationRelations: invalidationRelations, nodes: nodes}, + undefined, + 4, + ), + function (err) { + if (err) throw err; + }, + ); + } + respondToFSEvents( events: Array<{|path: ProjectPath, type: EventType|}>, ): boolean { @@ -770,7 +829,7 @@ export class RequestGraph extends ContentGraph< for (let connectedNode of nodes) { didInvalidate = true; - this.invalidateNode(connectedNode, FILE_UPDATE); + this.invalidateNode(connectedNode, FILE_UPDATE, nodeId); } if (type === 'create') { @@ -780,7 +839,7 @@ export class RequestGraph extends ContentGraph< ); for (let connectedNode of nodes) { didInvalidate = true; - this.invalidateNode(connectedNode, FILE_CREATE); + this.invalidateNode(connectedNode, FILE_CREATE, nodeId); } } } else if (type === 'create') { @@ -821,7 +880,7 @@ export class RequestGraph extends ContentGraph< ); for (let connectedNode of connectedNodes) { didInvalidate = true; - this.invalidateNode(connectedNode, FILE_CREATE); + this.invalidateNode(connectedNode, FILE_CREATE, globeNodeId); } } } @@ -832,7 +891,7 @@ export class RequestGraph extends ContentGraph< requestGraphEdgeTypes.invalidated_by_delete, )) { didInvalidate = true; - this.invalidateNode(connectedNode, FILE_DELETE); + this.invalidateNode(connectedNode, FILE_DELETE, nodeId); } // Delete the file node since it doesn't exist anymore. @@ -1229,6 +1288,7 @@ async function loadRequestGraph(options): Async { path: toProjectPath(options.projectRoot, e.path), })), ); + requestGraph.generateInvalidationReport(); return requestGraph; } From 13659313be118054b4fad84863cf3ee93d665266 Mon Sep 17 00:00:00 2001 From: Iris Moini Date: Mon, 4 Dec 2023 14:02:32 -0500 Subject: [PATCH 2/7] Generate cache invalidation report post build --- packages/core/core/src/Parcel.js | 3 +- packages/core/core/src/RequestTracker.js | 120 +++++++++++++---------- 2 files changed, 68 insertions(+), 55 deletions(-) diff --git a/packages/core/core/src/Parcel.js b/packages/core/core/src/Parcel.js index fffb97ae3e6..11e88d94b54 100644 --- a/packages/core/core/src/Parcel.js +++ b/packages/core/core/src/Parcel.js @@ -340,7 +340,6 @@ export default class Parcel { if (this.#watchAbortController) { this.#watchAbortController.abort(); } - this.#watchQueue.add(() => this._startNextBuild()); } @@ -359,6 +358,7 @@ export default class Parcel { createValidationRequest({optionsRef: this.#optionsRef, assetRequests}), {force: assetRequests.length > 0}, ); + this.#requestTracker.generateInvalidationReport(); return event; } catch (e) { if (e instanceof BuildAbortError) { @@ -406,7 +406,6 @@ export default class Parcel { if (this.#watchAbortController) { this.#watchAbortController.abort(); } - this.#watchQueue.add(() => this._startNextBuild()); this.#watchQueue.run(); } diff --git a/packages/core/core/src/RequestTracker.js b/packages/core/core/src/RequestTracker.js index 155e6cde4ee..b71e545821e 100644 --- a/packages/core/core/src/RequestTracker.js +++ b/packages/core/core/src/RequestTracker.js @@ -745,58 +745,6 @@ export class RequestGraph extends ContentGraph< } } - generateInvalidationReport(): void { - let nodes = {}; - let invalidationRelations = {}; - for (let {invalidated, cause} of this.invalidationReport) { - let invalidatedNode = nullthrows(this.getNode(invalidated)); - invariant(invalidatedNode.type === 'request'); - let causeNode = - cause !== undefined ? nullthrows(this.getNode(cause)) : undefined; - - if (invalidatedNode.id === 'Main') { - continue; - } - - if (!invalidationRelations[invalidated]) { - invalidationRelations[invalidated] = []; - } - - if (causeNode && !invalidationRelations[invalidated].includes(cause)) { - invalidationRelations[invalidated].push(cause); - } - - nodes[invalidated] = { - id: invalidatedNode.id, - type: invalidatedNode.type, - requestType: invalidatedNode.requestType, - invalidateReason: invalidatedNode.invalidateReason, - }; - - if (causeNode) { - invariant(cause !== undefined); - let {id, type, requestType, invalidateReason} = causeNode; - nodes[cause] = - requestType !== undefined && invalidateReason !== undefined - ? {id, type, requestType, invalidateReason} - : {id, type}; - } - } - - const fs = require('fs'); - fs.writeFile( - 'cache-invalidation-report.json', - JSON.stringify( - {invalidationRelations: invalidationRelations, nodes: nodes}, - undefined, - 4, - ), - function (err) { - if (err) throw err; - }, - ); - } - respondToFSEvents( events: Array<{|path: ProjectPath, type: EventType|}>, ): boolean { @@ -1167,6 +1115,73 @@ export default class RequestTracker { return {api, subRequestContentKeys}; } + generateInvalidationReport(): void { + let nodes = {}; + let invalidationRelations = {}; + for (let {invalidated, cause} of this.graph.invalidationReport) { + let invalidatedNode = this.graph.getNode(invalidated); + let causeNode = + cause !== undefined ? this.graph.getNode(cause) : undefined; + if ( + invalidatedNode === null || + causeNode === null || + invalidatedNode === undefined || + causeNode === undefined + ) { + continue; + } + + if (invalidatedNode.id !== 'Main') { + if (!invalidationRelations[invalidated]) { + invalidationRelations[invalidated] = []; + } + + if (!invalidationRelations[invalidated].includes(cause)) { + invariant(cause !== undefined); + invalidationRelations[invalidated].push(cause); + } + } + + invariant(invalidatedNode.type === 'request'); + nodes[invalidated] = { + id: invalidatedNode.id, + type: invalidatedNode.type, + requestType: invalidatedNode.requestType, + invalidateReason: invalidatedNode.invalidateReason, + }; + + if ( + causeNode.requestType !== undefined && + causeNode.invalidateReason !== undefined + ) { + nodes[cause] = { + id: causeNode.id, + type: causeNode.type, + requestType: causeNode.requestType, + invalidateReason: causeNode.invalidateReason, + }; + } else { + nodes[cause] = { + id: causeNode.id, + type: causeNode.type, + }; + } + } + + const fs = require('fs'); + fs.writeFile( + 'cache-invalidation-report.json', + JSON.stringify( + {invalidationRelations: invalidationRelations, nodes: nodes}, + undefined, + 4, + ), + function (err) { + if (err) throw err; + }, + ); + } + async writeToCache() { let cacheKey = getCacheKey(this.options); let requestGraphKey = hashString(`${cacheKey}:requestGraph`); @@ -1288,7 +1303,6 @@ async function loadRequestGraph(options): Async { path: toProjectPath(options.projectRoot, e.path), })), ); - requestGraph.generateInvalidationReport(); return requestGraph; } From 95effa3eccacb56e25b60a20e163e4cb28f918b7 Mon Sep 17 00:00:00 2001 From: Iris Moini Date: Wed, 6 Dec 2023 18:41:19 -0500 Subject: [PATCH 3/7] Update generateInvalidationReport for node type check --- packages/core/core/src/RequestTracker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/core/src/RequestTracker.js b/packages/core/core/src/RequestTracker.js index b71e545821e..9ff146b5b49 100644 --- a/packages/core/core/src/RequestTracker.js +++ b/packages/core/core/src/RequestTracker.js @@ -1142,7 +1142,7 @@ export default class RequestTracker { } } - invariant(invalidatedNode.type === 'request'); + invariant(invalidatedNode.type === 1); nodes[invalidated] = { id: invalidatedNode.id, type: invalidatedNode.type, From 88c02d7a909ef65766aed370fddcd6af1fd0b7e6 Mon Sep 17 00:00:00 2001 From: Iris Moini Date: Wed, 6 Dec 2023 18:52:09 -0500 Subject: [PATCH 4/7] Make flow happy --- packages/core/core/src/RequestTracker.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/core/core/src/RequestTracker.js b/packages/core/core/src/RequestTracker.js index 9ff146b5b49..b56432e8578 100644 --- a/packages/core/core/src/RequestTracker.js +++ b/packages/core/core/src/RequestTracker.js @@ -1150,6 +1150,7 @@ export default class RequestTracker { invalidateReason: invalidatedNode.invalidateReason, }; + invariant(cause !== undefined); if ( causeNode.requestType !== undefined && causeNode.invalidateReason !== undefined From dec4823784e3dff937f75299d6d0ee5e3074cb43 Mon Sep 17 00:00:00 2001 From: Iris Moini Date: Wed, 6 Dec 2023 19:12:50 -0500 Subject: [PATCH 5/7] Fix white space --- packages/core/core/src/Parcel.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/core/core/src/Parcel.js b/packages/core/core/src/Parcel.js index 11e88d94b54..a17229a8d6a 100644 --- a/packages/core/core/src/Parcel.js +++ b/packages/core/core/src/Parcel.js @@ -340,6 +340,7 @@ export default class Parcel { if (this.#watchAbortController) { this.#watchAbortController.abort(); } + this.#watchQueue.add(() => this._startNextBuild()); } @@ -406,6 +407,7 @@ export default class Parcel { if (this.#watchAbortController) { this.#watchAbortController.abort(); } + this.#watchQueue.add(() => this._startNextBuild()); this.#watchQueue.run(); } From 0e993c5773261a3c4e0ec95efc29e14bfbe5f1ec Mon Sep 17 00:00:00 2001 From: Iris Moini Date: Thu, 7 Dec 2023 15:46:58 -0500 Subject: [PATCH 6/7] Put invalidation report behind flag --- packages/core/core/src/Parcel.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/core/core/src/Parcel.js b/packages/core/core/src/Parcel.js index a17229a8d6a..a5688c0d1ea 100644 --- a/packages/core/core/src/Parcel.js +++ b/packages/core/core/src/Parcel.js @@ -359,7 +359,9 @@ export default class Parcel { createValidationRequest({optionsRef: this.#optionsRef, assetRequests}), {force: assetRequests.length > 0}, ); - this.#requestTracker.generateInvalidationReport(); + if (process.env.PARCEL_GENERATE_INVALIDATION_REPORT != null) { + this.#requestTracker.generateInvalidationReport(); + } return event; } catch (e) { if (e instanceof BuildAbortError) { From 7194dbc8ed839805a02d8b84b2db8c69429c0942 Mon Sep 17 00:00:00 2001 From: Iris Moini Date: Tue, 12 Dec 2023 19:55:49 -0500 Subject: [PATCH 7/7] Put invalidation report behind flag --- packages/core/core/src/RequestTracker.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/core/core/src/RequestTracker.js b/packages/core/core/src/RequestTracker.js index 161e036331c..9e7552caf85 100644 --- a/packages/core/core/src/RequestTracker.js +++ b/packages/core/core/src/RequestTracker.js @@ -343,7 +343,9 @@ export class RequestGraph extends ContentGraph< invariant(node.type === REQUEST); node.invalidateReason |= reason; this.invalidNodeIds.add(nodeId); - this.invalidationReport.push({invalidated: nodeId, cause: cause}); + if (process.env.PARCEL_GENERATE_INVALIDATION_REPORT != null) { + this.invalidationReport.push({invalidated: nodeId, cause: cause}); + } let parentNodes = this.getNodeIdsConnectedTo( nodeId,