Skip to content

Commit 6233816

Browse files
committed
refactor(project): Add perf logging, cleanups
1 parent c5e2ee5 commit 6233816

File tree

11 files changed

+789
-235
lines changed

11 files changed

+789
-235
lines changed

packages/project/lib/build/BuildReader.js

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,32 @@
11
import AbstractReader from "@ui5/fs/AbstractReader";
22

3+
/**
4+
* Reader for accessing build results of multiple projects
5+
*
6+
* Provides efficient resource access by delegating to appropriate project readers
7+
* based on resource paths and namespaces. Supports namespace-based routing to
8+
* minimize unnecessary project searches.
9+
*
10+
* @class
11+
* @extends @ui5/fs/AbstractReader
12+
*/
313
class BuildReader extends AbstractReader {
414
#projects;
515
#projectNames;
616
#namespaces = new Map();
717
#getReaderForProject;
818
#getReaderForProjects;
919

20+
/**
21+
* Creates a new BuildReader instance
22+
*
23+
* @public
24+
* @param {string} name Name of the reader
25+
* @param {Array<@ui5/project/specifications/Project>} projects Array of projects to read from
26+
* @param {Function} getReaderForProject Function that returns a reader for a single project by name
27+
* @param {Function} getReaderForProjects Function that returns a combined reader for multiple project names
28+
* @throws {Error} If multiple projects share the same namespace
29+
*/
1030
constructor(name, projects, getReaderForProject, getReaderForProjects) {
1131
super(name);
1232
this.#projects = projects;
@@ -27,11 +47,31 @@ class BuildReader extends AbstractReader {
2747
}
2848
}
2949

50+
/**
51+
* Locates resources by glob pattern
52+
*
53+
* Retrieves a combined reader for all projects and delegates the glob search to it.
54+
*
55+
* @public
56+
* @param {...*} args Arguments to pass to the underlying reader's byGlob method
57+
* @returns {Promise<Array<@ui5/fs/Resource>>} Promise resolving to list of resources
58+
*/
3059
async byGlob(...args) {
3160
const reader = await this.#getReaderForProjects(this.#projectNames);
3261
return reader.byGlob(...args);
3362
}
3463

64+
/**
65+
* Locates a resource by path
66+
*
67+
* Attempts to determine the appropriate project reader based on the resource path
68+
* and namespace. Falls back to searching all projects if the resource cannot be found.
69+
*
70+
* @public
71+
* @param {string} virPath Virtual path of the resource
72+
* @param {...*} args Additional arguments to pass to the underlying reader's byPath method
73+
* @returns {Promise<@ui5/fs/Resource|null>} Promise resolving to resource or null if not found
74+
*/
3575
async byPath(virPath, ...args) {
3676
const reader = await this._getReaderForResource(virPath);
3777
let res = await reader.byPath(virPath, ...args);
@@ -43,7 +83,16 @@ class BuildReader extends AbstractReader {
4383
return res;
4484
}
4585

46-
86+
/**
87+
* Gets the appropriate reader for a resource at the given path
88+
*
89+
* Determines which project(s) might contain the resource based on namespace matching
90+
* and returns a reader for those projects. For single-project readers, returns that
91+
* project's reader directly.
92+
*
93+
* @param {string} virPath Virtual path of the resource
94+
* @returns {Promise<@ui5/fs/AbstractReader>} Promise resolving to appropriate reader
95+
*/
4796
async _getReaderForResource(virPath) {
4897
let reader;
4998
if (this.#projects.length === 1) {
@@ -65,9 +114,14 @@ class BuildReader extends AbstractReader {
65114
}
66115

67116
/**
68-
* Determine which projects might contain the resource for the given path.
117+
* Determines which projects might contain the resource for the given path
118+
*
119+
* Analyzes the resource path to identify matching project namespaces. Only processes
120+
* paths starting with /resources/ or /test-resources/. Returns project names in order
121+
* from most specific to least specific namespace match.
69122
*
70123
* @param {string} virPath Virtual resource path
124+
* @returns {string[]} Array of project names that might contain the resource
71125
*/
72126
_getProjectsForResourcePath(virPath) {
73127
if (!virPath.startsWith("/resources/") && !virPath.startsWith("/test-resources/")) {

packages/project/lib/build/BuildServer.js

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,27 @@ import {createReaderCollectionPrioritized} from "@ui5/fs/resourceFactory";
33
import BuildReader from "./BuildReader.js";
44
import WatchHandler from "./helpers/WatchHandler.js";
55

6+
/**
7+
* Development server that provides access to built project resources with automatic rebuilding
8+
*
9+
* BuildServer watches project sources for changes and automatically rebuilds affected projects
10+
* on-demand. It provides readers for accessing built resources and emits events for build
11+
* completion and source changes.
12+
*
13+
* The server maintains separate readers for:
14+
* - All projects (root + dependencies)
15+
* - Root project only
16+
* - Dependencies only
17+
*
18+
* Projects are built lazily when their resources are first requested, and rebuilt automatically
19+
* when source files change.
20+
*
21+
* @class
22+
* @extends EventEmitter
23+
* @fires BuildServer#buildFinished
24+
* @fires BuildServer#sourcesChanged
25+
* @fires BuildServer#error
26+
*/
627
class BuildServer extends EventEmitter {
728
#graph;
829
#projectBuilder;
@@ -12,6 +33,18 @@ class BuildServer extends EventEmitter {
1233
#dependenciesReader;
1334
#projectReaders = new Map();
1435

36+
/**
37+
* Creates a new BuildServer instance
38+
*
39+
* Initializes readers for different project combinations, sets up file watching,
40+
* and optionally performs an initial build of specified dependencies.
41+
*
42+
* @public
43+
* @param {@ui5/project/graph/ProjectGraph} graph Project graph containing all projects
44+
* @param {@ui5/project/build/ProjectBuilder} projectBuilder Builder instance for executing builds
45+
* @param {string[]} initialBuildIncludedDependencies Project names to include in initial build
46+
* @param {string[]} initialBuildExcludedDependencies Project names to exclude from initial build
47+
*/
1548
constructor(graph, projectBuilder, initialBuildIncludedDependencies, initialBuildExcludedDependencies) {
1649
super();
1750
this.#graph = graph;
@@ -64,18 +97,57 @@ class BuildServer extends EventEmitter {
6497
});
6598
}
6699

100+
/**
101+
* Gets a reader for all projects (root and dependencies)
102+
*
103+
* Returns a reader that provides access to built resources from all projects in the graph.
104+
* Projects are built on-demand when their resources are requested.
105+
*
106+
* @public
107+
* @returns {BuildReader} Reader for all projects
108+
*/
67109
getReader() {
68110
return this.#allReader;
69111
}
70112

113+
/**
114+
* Gets a reader for the root project only
115+
*
116+
* Returns a reader that provides access to built resources from only the root project,
117+
* excluding all dependencies. The root project is built on-demand when its resources
118+
* are requested.
119+
*
120+
* @public
121+
* @returns {BuildReader} Reader for root project
122+
*/
71123
getRootReader() {
72124
return this.#rootReader;
73125
}
74126

127+
/**
128+
* Gets a reader for dependencies only (excluding root project)
129+
*
130+
* Returns a reader that provides access to built resources from all transitive
131+
* dependencies of the root project. Dependencies are built on-demand when their
132+
* resources are requested.
133+
*
134+
* @public
135+
* @returns {BuildReader} Reader for all dependencies
136+
*/
75137
getDependenciesReader() {
76138
return this.#dependenciesReader;
77139
}
78140

141+
/**
142+
* Gets a reader for a single project, building it if necessary
143+
*
144+
* Checks if the project has already been built and returns its reader from cache.
145+
* If not built, waits for any in-progress build, then triggers a build for the
146+
* requested project.
147+
*
148+
* @param {string} projectName Name of the project to get reader for
149+
* @returns {Promise<@ui5/fs/AbstractReader>} Reader for the built project
150+
*/
79151
async #getReaderForProject(projectName) {
80152
if (this.#projectReaders.has(projectName)) {
81153
return this.#projectReaders.get(projectName);
@@ -101,6 +173,16 @@ class BuildServer extends EventEmitter {
101173
return this.#projectReaders.get(projectName);
102174
}
103175

176+
/**
177+
* Gets a combined reader for multiple projects, building them if necessary
178+
*
179+
* Determines which projects need to be built, waits for any in-progress build,
180+
* then triggers a build for any missing projects. Returns a prioritized collection
181+
* reader combining all requested projects.
182+
*
183+
* @param {string[]} projectNames Array of project names to get readers for
184+
* @returns {Promise<@ui5/fs/ReaderCollection>} Combined reader for all requested projects
185+
*/
104186
async #getReaderForProjects(projectNames) {
105187
let projectsRequiringBuild = [];
106188
for (const projectName of projectNames) {
@@ -140,6 +222,15 @@ class BuildServer extends EventEmitter {
140222
return this.#getReaderForCachedProjects(projectNames);
141223
}
142224

225+
/**
226+
* Creates a combined reader for already-built projects
227+
*
228+
* Retrieves readers from the cache for the specified projects and combines them
229+
* into a prioritized reader collection.
230+
*
231+
* @param {string[]} projectNames Array of project names to combine
232+
* @returns {@ui5/fs/ReaderCollection} Combined reader for cached projects
233+
*/
143234
#getReaderForCachedProjects(projectNames) {
144235
const readers = [];
145236
for (const projectName of projectNames) {
@@ -181,6 +272,15 @@ class BuildServer extends EventEmitter {
181272
// return this.#allProjectsReader;
182273
// }
183274

275+
/**
276+
* Handles completion of a project build
277+
*
278+
* Caches readers for all built projects and emits the buildFinished event
279+
* with the list of project names that were built.
280+
*
281+
* @param {string[]} projectNames Array of project names that were built
282+
* @fires BuildServer#buildFinished
283+
*/
184284
#projectBuildFinished(projectNames) {
185285
for (const projectName of projectNames) {
186286
this.#projectReaders.set(projectName,
@@ -190,5 +290,32 @@ class BuildServer extends EventEmitter {
190290
}
191291
}
192292

293+
/**
294+
* Build finished event
295+
*
296+
* Emitted when one or more projects have finished building.
297+
*
298+
* @event BuildServer#buildFinished
299+
* @param {string[]} projectNames Array of project names that were built
300+
*/
301+
302+
/**
303+
* Sources changed event
304+
*
305+
* Emitted when source files have changed and affected projects have been invalidated.
306+
*
307+
* @event BuildServer#sourcesChanged
308+
* @param {string[]} changedResourcePaths Array of changed resource paths
309+
*/
310+
311+
/**
312+
* Error event
313+
*
314+
* Emitted when an error occurs during watching or building.
315+
*
316+
* @event BuildServer#error
317+
* @param {Error} error The error that occurred
318+
*/
319+
193320

194321
export default BuildServer;

0 commit comments

Comments
 (0)