packager: cleanup build status reporting

Reviewed By: cpojer

Differential Revision: D4521560

fbshipit-source-id: 8943e179192522da5145e4f14f0b648d3548cc36
This commit is contained in:
Jean Lauliac 2017-02-09 04:17:35 -08:00 committed by Facebook Github Bot
parent fc60f5948a
commit 57010d63b6
3 changed files with 89 additions and 93 deletions

View File

@ -544,6 +544,35 @@ class Server {
return JSON.stringify(Object.assign({}, options, { onProgress: null }));
}
/**
* Ensure we properly report the promise of a build that's happening,
* including failed builds. We use that separately for when we update a bundle
* and for when we build for scratch.
*/
_reportBundlePromise(
options: {entryFile: string},
bundlePromise: Promise<Bundle>,
): Promise<Bundle> {
this._reporter.update({
entryFilePath: options.entryFile,
type: 'bundle_build_started',
});
return bundlePromise.then(bundle => {
this._reporter.update({
entryFilePath: options.entryFile,
type: 'bundle_build_done',
});
return bundle;
}, error => {
this._reporter.update({
entryFilePath: options.entryFile,
error,
type: 'bundle_build_failed',
});
return Promise.reject(error);
});
}
_useCachedOrUpdateOrCreateBundle(options: {
entryFile: string,
platform?: string,
@ -567,11 +596,6 @@ class Server {
action_name: 'Updating existing bundle',
outdated_modules: outdated.size,
}));
this._reporter.update({
type: 'bundle_update_existing',
entryFilePath: options.entryFile,
outdatedModuleCount: outdated.size,
});
debug('Attempt to update existing bundle');
@ -644,7 +668,7 @@ class Server {
debug('Failed to update existing bundle, rebuilding...', e.stack || e.message);
return bundleFromScratch();
});
return bundlePromise;
return this._reportBundlePromise(options, bundlePromise);
} else {
debug('Using cached bundle');
return bundle;
@ -652,7 +676,7 @@ class Server {
});
}
return bundleFromScratch();
return this._reportBundlePromise(options, bundleFromScratch());
}
processRequest(
@ -691,10 +715,6 @@ class Server {
}
const options = this._getOptionsFromUrl(req.url);
this._reporter.update({
type: 'bundle_requested',
entryFilePath: options.entryFile,
});
const requestingBundleLogEntry =
log(createActionStartEntry({
action_name: 'Requesting bundle',
@ -724,10 +744,6 @@ class Server {
const building = this._useCachedOrUpdateOrCreateBundle(options);
building.then(
p => {
this._reporter.update({
type: 'bundle_built',
entryFilePath: options.entryFile,
});
if (requestType === 'bundle') {
debug('Generating source code');
const bundleSource = p.getSource({

View File

@ -27,7 +27,6 @@ type BundleProgress = {
transformedFileCount: number,
totalFileCount: number,
ratio: number,
outdatedModuleCount: number,
};
const DARK_BLOCK_CHAR = '\u2593';
@ -48,6 +47,8 @@ export type TerminalReportableEvent = ReportableEvent | {
totalFileCount: number,
};
type BuildPhase = 'in_progress' | 'done' | 'failed';
/**
* We try to print useful information to the terminal for interactive builds.
* This implements the `Reporter` interface from the './reporting' module.
@ -77,49 +78,26 @@ class TerminalReporter {
}
/**
* Return a message looking like this:
* Construct a message that represents the progress of a
* single bundle build, for example:
*
* Transforming files |#### | 34.2% (324/945)...
*
*/
_getFileTransformMessage(
{totalFileCount, transformedFileCount, ratio, outdatedModuleCount}: BundleProgress,
build: 'in_progress' | 'done',
): string {
if (outdatedModuleCount > 0) {
const plural = outdatedModuleCount > 1;
return `Updating ${outdatedModuleCount} ` +
`module${plural ? 's' : ''} in place` +
(build === 'done' ? ', done' : '...');
}
if (totalFileCount === 0) {
return build === 'done'
? 'No module changed.'
: 'Analysing...';
}
return util.format(
'Transforming modules %s%s% (%s/%s)%s',
build === 'done' ? '' : getProgressBar(ratio, 30) + ' ',
(100 * ratio).toFixed(1),
transformedFileCount,
totalFileCount,
build === 'done' ? ', done.' : '...',
);
}
/**
* Construct a message that represent the progress of a single bundle build.
* Bunding `foo.js` |#### | 34.2% (324/945)
*/
_getBundleStatusMessage(
entryFilePath: string,
progress: BundleProgress,
build: 'in_progress' | 'done',
{totalFileCount, transformedFileCount, ratio}: BundleProgress,
phase: BuildPhase,
): string {
const localPath = path.relative('.', entryFilePath);
return [
`Bundling \`${localPath}\``,
' ' + this._getFileTransformMessage(progress, build),
].join('\n');
return util.format(
'Bundling `%s` %s%s% (%s/%s)%s',
localPath,
phase === 'in_progress' ? getProgressBar(ratio, 16) + ' ' : '',
(100 * ratio).toFixed(1),
transformedFileCount,
totalFileCount,
phase === 'done' ? ', done.' : (phase === 'failed' ? ', failed.' : ''),
);
}
_logCacheDisabled(reason: GlobalCacheDisabledReason): void {
@ -134,19 +112,38 @@ class TerminalReporter {
}
}
_logBundleBuildDone(entryFilePath: string) {
const progress = this._activeBundles.get(entryFilePath);
if (progress != null) {
const msg = this._getBundleStatusMessage(entryFilePath, {
...progress,
ratio: 1,
transformedFileCount: progress.totalFileCount,
}, 'done');
terminal.log(msg);
}
}
_logBundleBuildFailed(entryFilePath: string, error: Error) {
reporting.logError(terminal, 'bundling: %s', error.stack);
const progress = this._activeBundles.get(entryFilePath);
if (progress != null) {
const msg = this._getBundleStatusMessage(entryFilePath, progress, 'failed');
terminal.log(msg);
}
}
/**
* This function is only concerned with logging and should not do state
* or terminal status updates.
*/
_log(event: TerminalReportableEvent): void {
switch (event.type) {
case 'bundle_built':
const progress = this._activeBundles.get(event.entryFilePath);
if (progress != null) {
terminal.log(
this._getBundleStatusMessage(event.entryFilePath, progress, 'done'),
);
}
case 'bundle_build_done':
this._logBundleBuildDone(event.entryFilePath);
break;
case 'bundle_build_failed':
this._logBundleBuildFailed(event.entryFilePath, event.error);
break;
case 'dep_graph_loaded':
terminal.log(`${DEP_GRAPH_MESSAGE}, done.`);
@ -187,35 +184,24 @@ class TerminalReporter {
ratio,
transformedFileCount,
totalFileCount,
outdatedModuleCount: 0,
});
}
_updateBundleOutdatedModuleCount(
{entryFilePath, outdatedModuleCount}: {
entryFilePath: string,
outdatedModuleCount: number,
},
) {
const currentProgress = this._activeBundles.get(entryFilePath);
if (currentProgress == null) {
return;
}
currentProgress.outdatedModuleCount = outdatedModuleCount;
}
/**
* This function is exclusively concerned with updating the internal state.
* No logging or status updates should be done at this point.
*/
_updateState(event: TerminalReportableEvent): void {
switch (event.type) {
case 'bundle_requested':
case 'bundle_build_done':
case 'bundle_build_failed':
this._activeBundles.delete(event.entryFilePath);
break;
case 'bundle_build_started':
this._activeBundles.set(event.entryFilePath, {
transformedFileCount: 0,
totalFileCount: 0,
totalFileCount: 1,
ratio: 0,
outdatedModuleCount: 0,
});
break;
case 'bundle_transform_progressed':
@ -229,12 +215,6 @@ class TerminalReporter {
case 'bundle_transform_progressed_throttled':
this._updateBundleProgress(event);
break;
case 'bundle_update_existing':
this._updateBundleOutdatedModuleCount(event);
break;
case 'bundle_built':
this._activeBundles.delete(event.entryFilePath);
break;
case 'dep_graph_loading':
this._dependencyGraphHasLoaded = false;
break;

View File

@ -23,24 +23,24 @@ export type GlobalCacheDisabledReason = 'too_many_errors' | 'too_many_misses';
* report to the tool user.
*/
export type ReportableEvent = {
entryFilePath: string,
type: 'bundle_build_done',
} | {
entryFilePath: string,
error: Error,
type: 'bundle_build_failed',
} | {
entryFilePath: string,
type: 'bundle_build_started',
} | {
type: 'dep_graph_loading',
} | {
type: 'dep_graph_loaded',
} | {
type: 'bundle_requested',
entryFilePath: string,
} | {
type: 'bundle_transform_progressed',
entryFilePath: string,
transformedFileCount: number,
totalFileCount: number,
} | {
entryFilePath: string,
outdatedModuleCount: number,
type: 'bundle_update_existing',
} | {
type: 'bundle_built',
entryFilePath: string,
} | {
type: 'global_cache_error',
error: Error,