Skip to content

Commit d7ebe8d

Browse files
Group events by extension to reduce triggered builds
1 parent 53e1e4f commit d7ebe8d

File tree

1 file changed

+65
-39
lines changed

1 file changed

+65
-39
lines changed

packages/app/src/cli/services/dev/app-events/app-event-watcher.ts

Lines changed: 65 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -234,48 +234,74 @@ export class AppEventWatcher extends EventEmitter {
234234
* buildForBundle method.
235235
*/
236236
private async buildExtensions(extensionEvents: ExtensionEvent[]) {
237-
const promises = extensionEvents.map(async (extEvent) => {
238-
const ext = extEvent.extension
239-
return useConcurrentOutputContext({outputPrefix: ext.handle, stripAnsi: false}, async () => {
240-
try {
241-
if (this.esbuildManager.contexts?.[ext.uid]?.length) {
242-
await this.esbuildManager.rebuildContext(ext)
243-
this.options.stdout.write(`Build successful`)
244-
} else {
245-
await this.buildExtension(ext)
246-
}
247-
extEvent.buildResult = {status: 'ok', uid: ext.uid}
248-
// eslint-disable-next-line no-catch-all/no-catch-all, @typescript-eslint/no-explicit-any
249-
} catch (error: any) {
250-
// If there is an `errors` array, it's an esbuild error, format it and log it
251-
// If not, just print the error message to stderr.
252-
const errors: Message[] = error.errors ?? []
253-
let errorMessage = error.message
254-
let errorFile: string | undefined
255-
256-
if (errors.length) {
257-
// Use the first error for the main message and file
258-
const firstError = errors[0]
259-
errorMessage = firstError?.text
260-
errorFile = firstError?.location?.file
261-
262-
const formattedErrors = formatMessagesSync(errors, {kind: 'error', color: !isUnitTest()})
263-
formattedErrors.forEach((error) => {
264-
this.options.stderr.write(error)
237+
// Group events by extension to handle multiple events for the same extension
238+
const groupedExtensionEvents = extensionEvents.reduce<{extension: ExtensionInstance; events: ExtensionEvent[]}[]>(
239+
(grouped: {extension: ExtensionInstance; events: ExtensionEvent[]}[], event: ExtensionEvent) => {
240+
const existingGroup = grouped.find((group) => group.extension.uid === event.extension.uid)
241+
if (existingGroup) {
242+
existingGroup.events.push(event)
243+
} else {
244+
grouped.push({
245+
extension: event.extension,
246+
events: [event],
247+
})
248+
}
249+
return grouped
250+
},
251+
[],
252+
)
253+
254+
const promises = groupedExtensionEvents
255+
.filter(({events}) => events.length > 0)
256+
.map(async ({extension: ext, events}) => {
257+
return useConcurrentOutputContext({outputPrefix: ext.handle, stripAnsi: false}, async () => {
258+
try {
259+
if (this.esbuildManager.contexts?.[ext.uid]?.length) {
260+
await this.esbuildManager.rebuildContext(ext)
261+
this.options.stdout.write(`Build successful`)
262+
} else {
263+
await this.buildExtension(ext)
264+
}
265+
// Update all events for this extension with success result
266+
const buildResult = {status: 'ok' as const, uid: ext.uid}
267+
events.forEach((event) => {
268+
event.buildResult = buildResult
269+
})
270+
// eslint-disable-next-line no-catch-all/no-catch-all, @typescript-eslint/no-explicit-any
271+
} catch (error: any) {
272+
// If there is an `errors` array, it's an esbuild error, format it and log it
273+
// If not, just print the error message to stderr.
274+
const errors: Message[] = error.errors ?? []
275+
let errorMessage = error.message
276+
let errorFile: string | undefined
277+
278+
if (errors.length) {
279+
// Use the first error for the main message and file
280+
const firstError = errors[0]
281+
errorMessage = firstError?.text
282+
errorFile = firstError?.location?.file
283+
284+
const formattedErrors = formatMessagesSync(errors, {kind: 'error', color: !isUnitTest()})
285+
formattedErrors.forEach((error) => {
286+
this.options.stderr.write(error)
287+
})
288+
} else {
289+
this.options.stderr.write(error.message)
290+
}
291+
292+
// Update all events for this extension with error result
293+
const buildResult = {
294+
status: 'error' as const,
295+
error: errorMessage,
296+
file: errorFile,
297+
uid: ext.uid,
298+
}
299+
events.forEach((event) => {
300+
event.buildResult = buildResult
265301
})
266-
} else {
267-
this.options.stderr.write(error.message)
268-
}
269-
270-
extEvent.buildResult = {
271-
status: 'error',
272-
error: errorMessage,
273-
file: errorFile,
274-
uid: ext.uid,
275302
}
276-
}
303+
})
277304
})
278-
})
279305
return Promise.all(promises)
280306
}
281307

0 commit comments

Comments
 (0)