-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create raw data for cache invalidation report #9422
base: v2
Are you sure you want to change the base?
Changes from all commits
72bbd1e
1365931
95effa3
88c02d7
dec4823
cdad594
a919a60
0e993c5
36c24f1
7194dbc
0231d44
b133f00
578ea28
c7d2677
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -120,6 +120,11 @@ type Request<TInput, TResult> = {| | |
|}; | ||
|
||
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<NodeId> = new Set(); | ||
invalidationReport: InvalidationEntry[] = []; | ||
incompleteNodeIds: Set<NodeId> = new Set(); | ||
incompleteNodePromises: Map<NodeId, Promise<boolean>> = new Map(); | ||
globNodeIds: Set<NodeId> = new Set(); | ||
|
@@ -332,18 +338,21 @@ 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); | ||
if (process.env.PARCEL_GENERATE_INVALIDATION_REPORT != null) { | ||
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 +382,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 +400,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 +719,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); | ||
} | ||
} | ||
} | ||
|
@@ -770,7 +779,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 +789,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 +830,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 +841,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. | ||
|
@@ -1108,6 +1117,74 @@ 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 === 1); | ||
nodes[invalidated] = { | ||
id: invalidatedNode.id, | ||
type: invalidatedNode.type, | ||
requestType: invalidatedNode.requestType, | ||
invalidateReason: invalidatedNode.invalidateReason, | ||
}; | ||
|
||
invariant(cause !== undefined); | ||
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'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Parcel has the ability to override the output filesystem which this ignores. Would it be hard to use |
||
fs.writeFile( | ||
'cache-invalidation-report.json', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe should prefix this with |
||
JSON.stringify( | ||
{invalidationRelations: invalidationRelations, nodes: nodes}, | ||
undefined, | ||
4, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe 2? #nitpick 😅 |
||
), | ||
function (err) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is running async via a callback but we're not waiting for completion anywhere. We should be awaiting a promise here instead. If you migrate to |
||
if (err) throw err; | ||
}, | ||
); | ||
} | ||
|
||
async writeToCache() { | ||
let cacheKey = getCacheKey(this.options); | ||
let requestGraphKey = | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The types have been all migrated into numbers now right? Maybe we should map them back to strings for the report?