Skip to content

Commit

Permalink
finish implementing new leader protocol
Browse files Browse the repository at this point in the history
  • Loading branch information
ef4 committed Dec 4, 2020
1 parent d0486e3 commit ec85ecc
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 22 deletions.
16 changes: 13 additions & 3 deletions packages/ember-auto-import/ts/auto-import.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,17 @@ import { AddonInstance, AppInstance, findTopmostAddon } from './ember-cli-models

const debugTree = buildDebugCallback('ember-auto-import');

export default class AutoImport {
// This interface must be stable across all versions of ember-auto-import that
// speak the same leader-election protocol. So don't change this unless you know
// what you're doing.
export interface AutoImportSharedAPI {
isPrimary(addonInstance: AddonInstance): boolean;
analyze(tree: Node, addon: AddonInstance): Node;
included(addonInstance: AddonInstance): void;
updateFastBootManifest(manifest: { vendorFiles: string[] }): void;
}

export default class AutoImport implements AutoImportSharedAPI {
private primaryPackage: AddonInstance;
private packages: Set<Package> = new Set();
private env: 'development' | 'test' | 'production';
Expand All @@ -24,7 +34,7 @@ export default class AutoImport {
LeaderChooser.for(addon).register(addon, () => new AutoImport(addon));
}

static lookup(addon: AddonInstance): AutoImport {
static lookup(addon: AddonInstance): AutoImportSharedAPI {
return LeaderChooser.for(addon).leader;
}

Expand Down Expand Up @@ -58,7 +68,7 @@ export default class AutoImport {
return analyzer;
}

makeBundler(allAppTree: Node) {
private makeBundler(allAppTree: Node) {
// The Splitter takes the set of imports from the Analyzer and
// decides which ones to include in which bundles
let splitter = new Splitter({
Expand Down
54 changes: 35 additions & 19 deletions packages/ember-auto-import/ts/leader.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { gt } from "semver";
import type AutoImport from "./auto-import";
import { Project, AddonInstance } from './ember-cli-models';
import { Project, AddonInstance } from "./ember-cli-models";
import { Node } from "broccoli-node-api";

const protocolV1 = "__ember_auto_import_protocol_v1__";
const protocolV2 = "__ember_auto_import_protocol_v2__";
Expand Down Expand Up @@ -49,33 +50,48 @@ export class LeaderChooser {
this.locked = this.tentative.create();
let v1 = g[protocolV1];
if (v1?.isV1Placeholder) {
g[protocolV1] = this.locked;
v1.leader = this.locked;
}
}
return this.locked;
}
}

class V1Placeholder {
isV1Placeholder = true;
leader: AutoImport | undefined;

// we never want v1-speaking copies of ember-auto-import to consider
// themselves primary, so if they're asking here, the answer is no.
isPrimary() {
return false;
}

// this is the only method that is called after isPrimary returns false. So we
// need to implement this one and don't need to implement the other public API
// of AutoImport.
analyze(tree: Node, addon: AddonInstance) {
if (!this.leader) {
throw new Error(
`bug: expected some protcol v2 copy of ember-auto-import to take charge before any v1 copy started trying to analyze trees`
);
}
return this.leader.analyze(tree, addon);
}
}

// at module load time, preempt all earlier versions of ember-auto-import that
// don't use our v2 protocol for deciding which copy is in charge. This ensures
// that the v2 protocol will pick which version is in charge (and it can't pick
// a v1-speaking copy).
// don't use our v2 leadership protocol. This ensures that the v2 protocol will
// pick which version is in charge (and v1-speaking copies won't be eligible).
(function v1ProtocolCompat() {
let v1 = g[protocolV1];
if (v1 && !v1.isV1Placeholder) {
throw new Error(
`bug: an old version of ember-auto-import has already taken over. This is unexpected.`
);
}
g[protocolV1] = {
isV1Placeholder: true,
analyze() {
if (v1) {
if (!v1.isV1Placeholder) {
throw new Error(
`bug: expected some copy of ember-auto-import to take charge before anybody started trying to analyze trees`
`bug: an old version of ember-auto-import has already taken over. This is unexpected.`
);
},
isPrimary() {
return false;
},
};
}
} else {
g[protocolV1] = new V1Placeholder;
}
})();

0 comments on commit ec85ecc

Please sign in to comment.