Skip to content

Commit

Permalink
Soft refresh, versioned packages only
Browse files Browse the repository at this point in the history
First half of meteor#3213.
  • Loading branch information
glasser committed Dec 2, 2014
1 parent 2f90467 commit a937aa6
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 25 deletions.
67 changes: 51 additions & 16 deletions tools/isopack-cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,31 @@ var watch = require('./watch.js');
exports.IsopackCache = function (options) {
var self = this;
options = options || {};

// cacheDir may be null; in this case, we just don't ever save things to disk.
self.cacheDir = options.cacheDir;

// Defines the versions of packages that we build. Must be set.
self._packageMap = options.packageMap;

// tropohouse may be null; in this case, we can't load versioned packages.
// eg, for building isopackets.
self._tropohouse = options.tropohouse;

// If provided, this is another IsopackCache for the same cache dir; when
// loading Isopacks, if they are definitely unchanged we can load the
// in-memory objects from this cache instead of recompiling.
self._previousIsopackCache = options.previousIsopackCache;
if (self._previousIsopackCache &&
self._previousIsopackCache.cacheDir !== self.cacheDir) {
throw Error("previousIsopackCache has different cacheDir!");
}

// Map from package name to {isopack, pluginProviderPackageMap} object.
// pluginProviderPackageMap is null for isopacks that are loaded from the
// tropohouse, and otherwise is a PackageMap object listing
self._isopacks = {};

self.allLoadedLocalPackagesWatchSet = new watch.WatchSet;
};

Expand Down Expand Up @@ -124,24 +138,37 @@ _.extend(exports.IsopackCache.prototype, {
throw Error("Can't load versioned packages without a tropohouse!");
}

var packagesToLoad;
// Load the isopack from disk.
buildmessage.enterJob(
"loading package " + name + "@" + packageInfo.version,
function () {
var isopackPath = self._tropohouse.packagePath(
name, packageInfo.version);
var isopack = new isopackModule.Isopack();
isopack.initFromPath(name, isopackPath);
self._isopacks[name] = {
isopack: isopack,
pluginProviderPackageMap: null
};
if (buildmessage.jobHasMessages())
return;
var isopack = null, packagesToLoad = [];
if (self._previousIsopackCache
&& _.has(self._previousIsopackCache._isopacks, name)) {
var previousIsopack = self._previousIsopackCache._isopacks[name];
if (previousIsopack.version === packageInfo.version) {
isopack = previousIsopack;
packagesToLoad = isopack.getStrongOrderedUsedAndImpliedPackages();
});
}
}
if (! isopack) {
// Load the isopack from disk.
buildmessage.enterJob(
"loading package " + name + "@" + packageInfo.version,
function () {
var isopackPath = self._tropohouse.packagePath(
name, packageInfo.version);
isopack = new isopackModule.Isopack();
isopack.initFromPath(name, isopackPath);
// If loading the isopack fails, then we don't need to look for more
// packages to load, but we should still recover by putting it in
// self._isopacks.
if (buildmessage.jobHasMessages())
return;
packagesToLoad = isopack.getStrongOrderedUsedAndImpliedPackages();
});
}

self._isopacks[name] = {
isopack: isopack,
pluginProviderPackageMap: null
};
// Also load its dependencies. This is so that if this package is being
// built as part of a plugin, all the transitive dependencies of the
// plugin are loaded.
Expand All @@ -157,6 +184,9 @@ _.extend(exports.IsopackCache.prototype, {
var self = this;
buildmessage.assertInCapture();
buildmessage.enterJob("building package " + name, function () {
// XXX #3213 use _previousIsopackCache here too (which involves moving
// pluginProviderPackageMap into the Isopack object)

// Do we have an up-to-date package on disk?
var isopackBuildInfoJson = self.cacheDir && files.readJSONOrNull(
self._isopackBuildInfoPath(name));
Expand Down Expand Up @@ -231,5 +261,10 @@ _.extend(exports.IsopackCache.prototype, {
_isopackBuildInfoPath: function (packageName) {
var self = this;
return path.join(self._isopackDir(packageName), 'isopack-buildinfo.json');
},

forgetPreviousIsopackCache: function () {
var self = this;
self._previousIsopackCache = null;
}
});
19 changes: 13 additions & 6 deletions tools/project-context.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,13 @@ var STAGE = {
};

_.extend(exports.ProjectContext.prototype, {
reset: function (moreOptions) {
reset: function (moreOptions, resetOptions) {
var self = this;
// Allow overriding some options until the next call to reset; used by
// 'meteor update' code to try various values of releaseForConstraints.
var options = _.extend({}, self.originalOptions, moreOptions);
// This is options that are actually directed at reset itself.
resetOptions = resetOptions || {};

self.projectDir = options.projectDir;
self.tropohouse = options.tropohouse || tropohouse.default;
Expand Down Expand Up @@ -137,11 +139,15 @@ _.extend(exports.ProjectContext.prototype, {
self.packageMap = null;
self.packageMapDelta = null;

if (resetOptions.softRefreshIsopacks && self.isopackCache) {
// Make sure we only hold on to one old isopack cache, not a linked list
// of all of them.
self.isopackCache.forgetPreviousIsopackCache();
self._previousIsopackCache = self.isopackCache;
} else {
self._previousIsopackCache = null;
}
// Initialized by _buildLocalPackages.
// XXX #SoftRefresh Perhaps save the old IsopackCache and try
// to reuse unchanged in-memory Isopack objects?
// Be careful to only save one old IsopackCache, not a
// linked list of them. #3213
self.isopackCache = null;

self._completedStage = STAGE.INITIAL;
Expand Down Expand Up @@ -565,7 +571,8 @@ _.extend(exports.ProjectContext.prototype, {
self.isopackCache = new isopackCacheModule.IsopackCache({
packageMap: self.packageMap,
cacheDir: self.getProjectLocalDirectory('isopacks'),
tropohouse: self.tropohouse
tropohouse: self.tropohouse,
previousIsopackCache: self._previousIsopackCache
});

if (self._forceRebuildPackages) {
Expand Down
4 changes: 1 addition & 3 deletions tools/run-app.js
Original file line number Diff line number Diff line change
Expand Up @@ -405,14 +405,12 @@ _.extend(AppRunner.prototype, {
// If this isn't the first time we've run, we need to reset the project
// context since everything we have cached may have changed.
// XXX We can try to be a little less conservative here:
// - Keep around some in-memory Isopack objects and validate them
// by their buildinfo (we used to call this #SoftRefresh).
// - Don't re-build the whole local catalog if we know which local
// packages have changed. (This one might be a little trickier due
// to how the WatchSets are laid out. Might be possible to avoid
// re-building the local catalog at all if packages didn't change
// at all, though.)
self.projectContext.reset();
self.projectContext.reset({}, { softRefreshIsopacks: true });
var messages = buildmessage.capture(function () {
self.projectContext.readProjectMetadata();
});
Expand Down

0 comments on commit a937aa6

Please sign in to comment.