-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
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
fix(watchman): Parallelize Watchman calls in crawler again #5640
Changes from 1 commit
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 |
---|---|---|
|
@@ -51,48 +51,52 @@ module.exports = async function watchmanCrawl( | |
|
||
try { | ||
const watchmanRoots = new Map(); | ||
for (const root of roots) { | ||
const response = await cmd('watch-project', root); | ||
const existing = watchmanRoots.get(response.watch); | ||
// A root can only be filtered if it was never seen with a relative_path before | ||
const canBeFiltered = !existing || existing.length > 0; | ||
await Promise.all( | ||
roots.map(async root => { | ||
const response = await cmd('watch-project', root); | ||
const existing = watchmanRoots.get(response.watch); | ||
// A root can only be filtered if it was never seen with a relative_path before | ||
const canBeFiltered = !existing || existing.length > 0; | ||
|
||
if (canBeFiltered) { | ||
if (response.relative_path) { | ||
watchmanRoots.set( | ||
response.watch, | ||
(existing || []).concat(response.relative_path), | ||
); | ||
} else { | ||
// Make the filter directories an empty array to signal that this root | ||
// was already seen and needs to be watched for all files/directories | ||
watchmanRoots.set(response.watch, []); | ||
if (canBeFiltered) { | ||
if (response.relative_path) { | ||
watchmanRoots.set( | ||
response.watch, | ||
(existing || []).concat(response.relative_path), | ||
); | ||
} else { | ||
// Make the filter directories an empty array to signal that this root | ||
// was already seen and needs to be watched for all files/directories | ||
watchmanRoots.set(response.watch, []); | ||
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. Slightly concerned about race conditions here but it should be fine since the main thread is memory-safe, right? 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. yes, this is completely fine |
||
} | ||
} | ||
} | ||
} | ||
}), | ||
); | ||
|
||
let shouldReset = false; | ||
const watchmanFileResults = new Map(); | ||
for (const [root, directoryFilters] of watchmanRoots) { | ||
const expression = Array.from(defaultWatchExpression); | ||
if (directoryFilters.length > 0) { | ||
expression.push([ | ||
'anyof', | ||
...directoryFilters.map(dir => ['dirname', dir]), | ||
]); | ||
} | ||
const fields = ['name', 'exists', 'mtime_ms']; | ||
await Promise.all( | ||
Array.from(watchmanRoots).map(async ([root, directoryFilters]) => { | ||
const expression = Array.from(defaultWatchExpression); | ||
if (directoryFilters.length > 0) { | ||
expression.push([ | ||
'anyof', | ||
...directoryFilters.map(dir => ['dirname', dir]), | ||
]); | ||
} | ||
const fields = ['name', 'exists', 'mtime_ms']; | ||
|
||
const query = clocks[root] | ||
? // Use the `since` generator if we have a clock available | ||
{expression, fields, since: clocks[root]} | ||
: // Otherwise use the `suffix` generator | ||
{expression, fields, suffix: extensions}; | ||
const query = clocks[root] | ||
? // Use the `since` generator if we have a clock available | ||
{expression, fields, since: clocks[root]} | ||
: // Otherwise use the `suffix` generator | ||
{expression, fields, suffix: extensions}; | ||
|
||
const response = await cmd('query', root, query); | ||
shouldReset = shouldReset || response.is_fresh_instance; | ||
watchmanFileResults.set(root, response); | ||
} | ||
const response = await cmd('query', root, query); | ||
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. Instead of what I did above, I can also just return
That said I still need to loop through responses and determine if
I'm kind of liking this new version but what do you think? 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. I think this is fine tbh |
||
shouldReset = shouldReset || response.is_fresh_instance; | ||
watchmanFileResults.set(root, response); | ||
}), | ||
); | ||
|
||
// Reset the file map if watchman was restarted and sends us a list of files. | ||
if (shouldReset) { | ||
|
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.
a function that you could hoist out :-)