Skip to content

Commit 02054d6

Browse files
committed
simplify bundle system
1 parent 1363ceb commit 02054d6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+317
-428
lines changed

modules/bundler/bundleSystem.ts

Lines changed: 60 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,109 +1,95 @@
1-
type BagOfPlugins = Set<Bundle<any, any>>;
21

32
export class BundleSystem {
43

5-
plugins: BagOfPlugins = new Set();
6-
waitingQueue: BagOfPlugins = new Set();
74
globalContext: any;
5+
activatedBundles = new Set<string>();
6+
waitingQueue = new Set<Bundle<any>>();
7+
perfectLoad = true;
88

9-
constructor(globalContext: any) {
9+
constructor(globalContext) {
1010
this.globalContext = globalContext;
1111
}
1212

13-
load(plugin: Bundle<any, any>) {
14-
this.waitingQueue.add(plugin);
13+
activate(bundle: Bundle<any>) {
14+
15+
if (!bundle.BundleName) {
16+
console.error("BundleName is not provided for the bundle");
17+
bundle.BundleName = "@Unknown_" + (UNKNOWNS_COUNTER++);
18+
}
19+
20+
if (this.activatedBundles.has(bundle.BundleName)) {
21+
throw `Bundle ${bundle.BundleName} has already activated. Possible name collision`;
22+
}
23+
24+
if (!this.readinessCheck(bundle)) {
25+
this.perfectLoad = false;
26+
this.waitingQueue.add(bundle);
27+
return;
28+
}
29+
30+
this.doActivate(bundle);
31+
1532
this.processWaitingQueue();
1633
}
1734

35+
private doActivate(bundle) {
36+
bundle.activate(this.globalContext);
37+
this.activatedBundles.add(bundle.BundleName);
38+
}
39+
1840
processWaitingQueue() {
19-
let needPass = true;
20-
while (needPass) {
21-
needPass = false;
22-
this.waitingQueue.forEach(plugin => {
23-
const ready = readiness(plugin, this.globalContext);
24-
if (ready) {
25-
try {
26-
plugin.activate(this.globalContext);
27-
checkActivation(plugin, this.globalContext);
28-
needPass = true;
29-
this.plugins.add(plugin);
30-
} catch (error) {
31-
console.error(error);
32-
} finally {
33-
this.waitingQueue.delete(plugin)
34-
}
35-
}
36-
})
41+
for (let bundle of this.waitingQueue) {
42+
if (this.readinessCheck(bundle)) {
43+
this.waitingQueue.delete(bundle);
44+
this.doActivate(bundle);
45+
}
3746
}
3847
}
3948

40-
unload(plugin: Bundle<any, any>) {
41-
this.waitingQueue.delete(plugin);
42-
this.plugins.delete(plugin);
43-
try {
44-
if (plugin.deactivate) {
45-
plugin.deactivate(this.globalContext);
46-
}
47-
} catch (error) {
48-
console.error(error);
49+
readinessCheck(bundle) {
50+
51+
if (!bundle.activationDependencies) {
52+
return true;
4953
}
5054

51-
let needPass = true;
52-
while (needPass) {
53-
needPass = false;
54-
this.plugins.forEach(plugin => {
55-
if (!plugin.deactivate) {
56-
return;
57-
}
58-
const isReady = readiness(plugin, this.globalContext);
59-
if (!isReady) {
60-
try {
61-
plugin.deactivate(this.globalContext);
62-
this.plugins.delete(plugin);
63-
this.waitingQueue.add(plugin);
64-
needPass = true;
65-
} catch (error) {
66-
console.error(error);
67-
}
68-
}
69-
})
55+
for (let dep of bundle.activationDependencies) {
56+
if (!this.activatedBundles.has(dep)) {
57+
return false;
58+
}
7059
}
60+
return true;
7161
}
72-
}
7362

74-
function readiness(plugin: Bundle<any, any>, globalContext: any) {
75-
const specKeys = Object.keys(plugin.inputContextSpec);
76-
for (let key of specKeys) {
77-
if (!globalContext[key] && plugin.inputContextSpec[key] === 'required') {
78-
return false;
79-
}
63+
checkDanglingBundles() {
64+
this.waitingQueue.forEach(dangling => {
65+
const unsatisfied = new Set(dangling.activationDependencies);
66+
this.activatedBundles.forEach(activated => unsatisfied.delete(activated));
67+
console.error('Bundle', dangling.BundleName, 'was never activated because of unsatisfied dependencies: ', Array.from(unsatisfied).join(', '));
68+
})
8069
}
81-
return true;
82-
}
8370

84-
function checkActivation(plugin: Bundle<any, any>, globalContext: any) {
85-
const specKeys = Object.keys(plugin.outputContextSpec);
86-
for (let key of specKeys) {
87-
if (!globalContext[key] && plugin.outputContextSpec[key] === 'required') {
88-
console.error("declared service was never activated: " + key);
71+
checkPerfectLoad() {
72+
if (!this.perfectLoad) {
73+
console.warn("Bundle activation wasn't perfect. Consider reordering bundles to following:");
74+
console.info(Array.from(this.activatedBundles));
8975
}
9076
}
9177
}
9278

93-
export type Spec = 'required' | 'optional';
94-
79+
export type Spec = 'required';
9580
export type ContextSpec<T> = {
9681
[Property in keyof T]: Spec;
9782
};
9883

99-
export interface Bundle<InputContext, OutputContext, WorkingContext = InputContext&OutputContext> {
84+
export interface Bundle<WorkingContext> {
10085

101-
inputContextSpec: ContextSpec<InputContext>;
86+
activationDependencies?: string[];
10287

103-
outputContextSpec: ContextSpec<OutputContext>;
88+
runtimeDependencies?: string[];
10489

105-
activate(ctx: InputContext&OutputContext);
106-
107-
deactivate?(ctx: InputContext&OutputContext);
90+
activate(ctx: WorkingContext);
10891

92+
BundleName: string,
10993
}
94+
95+
let UNKNOWNS_COUNTER = 0;

modules/bundler/bundlerContext.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
3+
4+
export function createBundlerContext() {
5+
6+
}

test/coreTests/subjects/modellerTPI.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {
33
ALL_EXCLUDING_SOLID_KINDS,
44
PICK_KIND,
55
traversePickResults
6-
} from '../../../web/app/cad/scene/controls/pickControlPlugin';
6+
} from 'cad/scene/controls/pickControlBundle';
77
import {Vector3} from "three";
88

99
function waitFor(checkFn) {

web/app/cad/actions/actionSystemBundle.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import {state, StateStream, Stream} from 'lstream';
44
import {LOG_FLAGS} from '../logFlags';
55
import {ApplicationContext} from "cad/context";
66
import {IconType} from "react-icons";
7-
import {ContextSpec} from "bundler/bundleSystem";
87

98
export function activate(context: ApplicationContext) {
109

@@ -160,7 +159,6 @@ export interface ActionSystemBundleContext {
160159
actionService: ActionService;
161160
}
162161

163-
export const outputContextSpec: ContextSpec<ActionSystemBundleContext> = {
164-
actionService: 'required'
165-
}
162+
export const BundleName = "@ActionSystem";
163+
166164

web/app/cad/assembly/assemblyBundle.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {AssemblyView} from "./ui/AssemblyView";
99
import {IoMdConstruct} from "react-icons/io";
1010
import {AssemblyConstraintDefinition} from "./assemblyConstraint";
1111
import {AssemblyConstraintsSchemas} from "./assemblySchemas";
12-
import {ContextSpec} from "bundler/bundleSystem";
1312

1413

1514
export function activate(ctx: ApplicationContext) {
@@ -105,6 +104,4 @@ export interface AssemblyBundleContext {
105104
assemblyService: AssemblyService;
106105
}
107106

108-
export const outputContextSpec: ContextSpec<AssemblyBundleContext> = {
109-
assemblyService: 'required'
110-
}
107+
export const BundleName = "@Assembly";

web/app/cad/attributes/attributesBundle.ts

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,22 @@ import {Bundle} from "bundler/bundleSystem";
22
import {AttributesService} from "cad/attributes/attributesService";
33
import {contributeComponent} from "cad/dom/components/ContributedComponents";
44
import {DisplayOptionsDialogManager} from "cad/attributes/ui/DisplayOptionsDialog";
5-
import {ActionSystemBundleContext} from "cad/actions/actionSystemBundle";
65
import {RequiresAnyModelSelection} from "cad/actions/actionHelpers";
76
import {IoColorPalette} from "react-icons/io5";
87
import {FaTable} from "react-icons/fa";
98
import {ApplicationContext} from "cad/context";
109

11-
type AttributesPluginInputContext = ActionSystemBundleContext;
12-
13-
export interface AttributesPluginContext {
10+
export interface AttributesBundleContext {
1411
attributesService: AttributesService;
1512
}
1613

17-
type AttributesPluginWorkingContext = AttributesPluginInputContext&AttributesPluginContext;
18-
19-
export const AttributesBundle: Bundle<AttributesPluginInputContext, AttributesPluginContext, AttributesPluginWorkingContext> = {
14+
export const AttributesBundle: Bundle<ApplicationContext> = {
2015

21-
inputContextSpec: {
22-
actionService: 'required',
23-
},
24-
25-
outputContextSpec: {
26-
attributesService: 'required',
27-
},
16+
activationDependencies: [
17+
'@ActionSystem'
18+
],
2819

29-
activate(ctx: AttributesPluginWorkingContext) {
20+
activate(ctx: ApplicationContext) {
3021
ctx.attributesService = new AttributesService();
3122
contributeComponent(DisplayOptionsDialogManager);
3223

@@ -55,6 +46,7 @@ export const AttributesBundle: Bundle<AttributesPluginInputContext, AttributesPl
5546
])
5647
},
5748

49+
BundleName: "@Attributes",
5850
}
5951

6052

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import {Bundle} from "bundler/bundleSystem";
2+
import {ApplicationContext} from "cad/context";
3+
4+
5+
export interface LegacyStructureBundleContext {
6+
services: any,
7+
streams: any
8+
}
9+
10+
11+
export const LegacyStructureBundle: Bundle<ApplicationContext> = {
12+
13+
activate(ctx: ApplicationContext) {
14+
ctx.services = {};
15+
ctx.streams = {};
16+
},
17+
18+
BundleName: "@Legacy",
19+
20+
}
21+
22+

web/app/cad/context/index.ts

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,48 @@
11
import {ProjectBundleContext} from "cad/projectBundle";
22
import {ActionSystemBundleContext} from "cad/actions/actionSystemBundle";
33
import {AssemblyBundleContext} from "cad/assembly/assemblyBundle";
4-
import {AttributesPluginContext} from "cad/attributes/attributesBundle";
4+
import {AttributesBundleContext} from "cad/attributes/attributesBundle";
55
import {CadRegistryBundleContext} from "cad/craft/cadRegistryBundle";
66
import {CraftBundleContext} from "cad/craft/craftBundle";
77
import {OperationBundleContext} from "cad/craft/operationBundle";
88
import {OCCBundleContext} from "cad/craft/e0/occtBundle";
9-
import {WizardPluginContext} from "cad/craft/wizard/wizardBundle";
9+
import {WizardBundleContext} from "cad/craft/wizard/wizardBundle";
1010
import {AppTabsBundleContext} from "cad/dom/appTabsBundle";
11-
import {DomPluginContext} from "cad/dom/domBundle";
11+
import {DomBundleContext} from "cad/dom/domBundle";
1212
import {UIBundleContext} from "cad/dom/uiBundle";
1313
import {ExpressionBundleContext} from "cad/expressions/expressionsBundle";
1414
import {LocationBundleContext} from "cad/location/LocationBundle";
1515
import {RemotePartsBundleContext} from "cad/partImport/remotePartsBundle";
1616
import {ProjectManagerBundleContext} from "cad/projectManager/projectManagerBundle";
1717
import {EntityContextBundleContext} from "cad/scene/entityContextBundle";
18-
import {HighlightPluginContext} from "cad/scene/highlightBundle";
18+
import {HighlightBundleContext} from "cad/scene/highlightBundle";
1919
import {SceneBundleContext} from "cad/scene/sceneBundle";
2020
import {SketcherBundleContext} from "cad/sketch/sketcherBundle";
2121
import {SketchStorageBundleContext} from "cad/sketch/sketchStorageBundle";
2222
import {StorageBundleContext} from "cad/storage/storageBundle";
2323
import {WorkbenchBundleContext} from "cad/workbench/workbenchBundle";
24-
25-
export interface LegacyContext {
26-
services: any,
27-
streams: any,
28-
}
24+
import {LegacyStructureBundleContext} from "cad/context/LegacyStructureBundle";
2925

3026
export interface ApplicationContext extends
31-
LegacyContext,
27+
LegacyStructureBundleContext,
3228
ProjectBundleContext,
3329
ActionSystemBundleContext,
3430
AssemblyBundleContext,
35-
AttributesPluginContext,
31+
AttributesBundleContext,
3632
CadRegistryBundleContext,
3733
CraftBundleContext,
3834
OperationBundleContext,
3935
OCCBundleContext,
40-
WizardPluginContext,
36+
WizardBundleContext,
4137
AppTabsBundleContext,
42-
DomPluginContext,
38+
DomBundleContext,
4339
UIBundleContext,
4440
ExpressionBundleContext,
4541
LocationBundleContext,
4642
RemotePartsBundleContext,
4743
ProjectManagerBundleContext,
4844
EntityContextBundleContext,
49-
HighlightPluginContext,
45+
HighlightBundleContext,
5046
SceneBundleContext,
5147
SketcherBundleContext,
5248
SketchStorageBundleContext,
@@ -56,10 +52,5 @@ export interface ApplicationContext extends
5652

5753
export type CoreContext = ApplicationContext;
5854

59-
export default {
60-
61-
services: {},
62-
streams: {}
63-
64-
} as ApplicationContext;
55+
export default {} as ApplicationContext;
6556

web/app/cad/craft/cadRegistryBundle.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,4 @@ export interface CadRegistryBundleContext {
114114
cadRegistry: CadRegistry;
115115
}
116116

117-
export const outputContextSpec: ContextSpec<CadRegistryBundleContext> = {
118-
cadRegistry: 'required'
119-
}
117+
export const BundleName = "@CadRegistry";

web/app/cad/craft/craftBundle.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,4 @@ export interface CraftBundleContext {
297297
craftService: CraftService;
298298
}
299299

300-
export const outputContextSpec: ContextSpec<CraftBundleContext> = {
301-
craftService: 'required'
302-
}
300+
export const BundleName = "@Craft";

0 commit comments

Comments
 (0)