@finos/legend-graph 32.3.35 → 32.3.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/lib/graph/helpers/DomainHelper.d.ts +3 -0
  2. package/lib/graph/helpers/DomainHelper.d.ts.map +1 -1
  3. package/lib/graph/helpers/DomainHelper.js +3 -0
  4. package/lib/graph/helpers/DomainHelper.js.map +1 -1
  5. package/lib/graph-manager/protocol/pure/v1/V1_PureGraphManager.d.ts +11 -0
  6. package/lib/graph-manager/protocol/pure/v1/V1_PureGraphManager.d.ts.map +1 -1
  7. package/lib/graph-manager/protocol/pure/v1/V1_PureGraphManager.js +76 -43
  8. package/lib/graph-manager/protocol/pure/v1/V1_PureGraphManager.js.map +1 -1
  9. package/lib/graph-manager/protocol/pure/v1/model/packageableElements/ingest/V1_IngestDefinition.d.ts +15 -0
  10. package/lib/graph-manager/protocol/pure/v1/model/packageableElements/ingest/V1_IngestDefinition.d.ts.map +1 -1
  11. package/lib/graph-manager/protocol/pure/v1/model/packageableElements/ingest/V1_IngestDefinition.js.map +1 -1
  12. package/lib/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_PureProtocolSerialization.d.ts.map +1 -1
  13. package/lib/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_PureProtocolSerialization.js +14 -10
  14. package/lib/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_PureProtocolSerialization.js.map +1 -1
  15. package/lib/graph-manager/protocol/pure/v1/transformation/pureProtocol/serializationHelpers/V1_EntitlementSerializationHelper.d.ts +2 -1
  16. package/lib/graph-manager/protocol/pure/v1/transformation/pureProtocol/serializationHelpers/V1_EntitlementSerializationHelper.d.ts.map +1 -1
  17. package/lib/graph-manager/protocol/pure/v1/transformation/pureProtocol/serializationHelpers/V1_EntitlementSerializationHelper.js +20 -5
  18. package/lib/graph-manager/protocol/pure/v1/transformation/pureProtocol/serializationHelpers/V1_EntitlementSerializationHelper.js.map +1 -1
  19. package/lib/index.d.ts +3 -3
  20. package/lib/index.d.ts.map +1 -1
  21. package/lib/index.js +3 -3
  22. package/lib/index.js.map +1 -1
  23. package/lib/package.json +1 -1
  24. package/package.json +3 -3
  25. package/src/graph/helpers/DomainHelper.ts +7 -0
  26. package/src/graph-manager/protocol/pure/v1/V1_PureGraphManager.ts +283 -413
  27. package/src/graph-manager/protocol/pure/v1/model/packageableElements/ingest/V1_IngestDefinition.ts +16 -0
  28. package/src/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_PureProtocolSerialization.ts +21 -23
  29. package/src/graph-manager/protocol/pure/v1/transformation/pureProtocol/serializationHelpers/V1_EntitlementSerializationHelper.ts +36 -5
  30. package/src/index.ts +8 -2
@@ -378,6 +378,12 @@ import {
378
378
  } from './engine/dev-metadata/V1_DevMetadataPushRequest.js';
379
379
  import type { MetadataRequestOptions } from '../../../action/dev-metadata/MetadataRequestOptions.js';
380
380
 
381
+ /**
382
+ * Number of elements to process synchronously before yielding to the event loop.
383
+ * This avoids per-element setTimeout overhead while keeping the UI responsive.
384
+ */
385
+ const GRAPH_BUILDER_BATCH_SIZE = 100;
386
+
381
387
  class V1_PureModelContextDataIndex {
382
388
  elements: V1_PackageableElement[] = [];
383
389
  nativeElements: V1_PackageableElement[] = [];
@@ -1272,46 +1278,37 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1272
1278
  graph.allElements.map((el) => el.path),
1273
1279
  );
1274
1280
 
1275
- await Promise.all(
1276
- inputs.flatMap(async (input) => {
1277
- // create the package cache
1278
- const packageCache = new Map<string, Package>();
1279
- await Promise.all(
1280
- input.data.nativeElements.map((element) => {
1281
- return this.visitWithGraphBuilderErrorHandling(
1282
- element,
1283
- new V1_ElementFirstPassBuilder(
1284
- this.getBuilderContext(graph, input.model, element, options),
1285
- packageCache,
1286
- elementPathCache,
1287
- ),
1288
- );
1289
- }),
1281
+ for (const input of inputs) {
1282
+ const packageCache = new Map<string, Package>();
1283
+ const createFirstPassBuilder = (
1284
+ element: V1_PackageableElement,
1285
+ ): V1_ElementFirstPassBuilder =>
1286
+ new V1_ElementFirstPassBuilder(
1287
+ this.getBuilderContext(graph, input.model, element, options),
1288
+ packageCache,
1289
+ elementPathCache,
1290
1290
  );
1291
- await Promise.all(
1292
- this.graphBuilderExtensions.sortedExtraElementBuilders.flatMap(
1293
- (builder) =>
1294
- (input.data.otherElementsByBuilder.get(builder) ?? []).map(
1295
- (element) => {
1296
- return this.visitWithGraphBuilderErrorHandling(
1297
- element,
1298
- new V1_ElementFirstPassBuilder(
1299
- this.getBuilderContext(
1300
- graph,
1301
- input.model,
1302
- element,
1303
- options,
1304
- ),
1305
- packageCache,
1306
- elementPathCache,
1307
- ),
1308
- );
1309
- },
1310
- ),
1311
- ),
1291
+
1292
+ // index native elements
1293
+ await this.runBatchedLoop(input.data.nativeElements, (element) =>
1294
+ this.visitWithGraphBuilderErrorHandling(
1295
+ element,
1296
+ createFirstPassBuilder(element),
1297
+ ),
1298
+ );
1299
+
1300
+ // index other (plugin-contributed) elements
1301
+ const otherElements =
1302
+ this.graphBuilderExtensions.sortedExtraElementBuilders.flatMap(
1303
+ (builder) => input.data.otherElementsByBuilder.get(builder) ?? [],
1312
1304
  );
1313
- }),
1314
- );
1305
+ await this.runBatchedLoop(otherElements, (element) =>
1306
+ this.visitWithGraphBuilderErrorHandling(
1307
+ element,
1308
+ createFirstPassBuilder(element),
1309
+ ),
1310
+ );
1311
+ }
1315
1312
  }
1316
1313
 
1317
1314
  private async buildTypes(
@@ -1320,128 +1317,78 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1320
1317
  options?: GraphBuilderOptions,
1321
1318
  ): Promise<void> {
1322
1319
  // Second pass
1323
- await Promise.all(
1324
- inputs.flatMap((input) =>
1325
- input.data.profiles.map((element) =>
1326
- this.visitWithGraphBuilderErrorHandling(
1327
- element,
1328
- new V1_ElementSecondPassBuilder(
1329
- this.getBuilderContext(graph, input.model, element, options),
1330
- ),
1331
- ),
1332
- ),
1333
- ),
1320
+ await this.processElementsInBatches(
1321
+ graph,
1322
+ inputs,
1323
+ (data) => data.profiles,
1324
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1325
+ options,
1334
1326
  );
1335
- await Promise.all(
1336
- inputs.flatMap((input) =>
1337
- input.data.classes.map((element) =>
1338
- this.visitWithGraphBuilderErrorHandling(
1339
- element,
1340
- new V1_ElementSecondPassBuilder(
1341
- this.getBuilderContext(graph, input.model, element, options),
1342
- ),
1343
- ),
1344
- ),
1345
- ),
1327
+ await this.processElementsInBatches(
1328
+ graph,
1329
+ inputs,
1330
+ (data) => data.classes,
1331
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1332
+ options,
1346
1333
  );
1347
- await Promise.all(
1348
- inputs.flatMap((input) =>
1349
- input.data.enumerations.map((element) =>
1350
- this.visitWithGraphBuilderErrorHandling(
1351
- element,
1352
- new V1_ElementSecondPassBuilder(
1353
- this.getBuilderContext(graph, input.model, element, options),
1354
- ),
1355
- ),
1356
- ),
1357
- ),
1334
+ await this.processElementsInBatches(
1335
+ graph,
1336
+ inputs,
1337
+ (data) => data.enumerations,
1338
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1339
+ options,
1358
1340
  );
1359
- await Promise.all(
1360
- inputs.flatMap((input) =>
1361
- input.data.measures.map((element) =>
1362
- this.visitWithGraphBuilderErrorHandling(
1363
- element,
1364
- new V1_ElementSecondPassBuilder(
1365
- this.getBuilderContext(graph, input.model, element, options),
1366
- ),
1367
- ),
1368
- ),
1369
- ),
1341
+ await this.processElementsInBatches(
1342
+ graph,
1343
+ inputs,
1344
+ (data) => data.measures,
1345
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1346
+ options,
1370
1347
  );
1371
- await Promise.all(
1372
- inputs.flatMap((input) =>
1373
- input.data.functions.map((element) =>
1374
- this.visitWithGraphBuilderErrorHandling(
1375
- element,
1376
- new V1_ElementSecondPassBuilder(
1377
- this.getBuilderContext(graph, input.model, element, options),
1378
- ),
1379
- ),
1380
- ),
1381
- ),
1348
+ await this.processElementsInBatches(
1349
+ graph,
1350
+ inputs,
1351
+ (data) => data.functions,
1352
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1353
+ options,
1382
1354
  );
1383
1355
  // Third pass
1384
- await Promise.all(
1385
- inputs.flatMap((input) =>
1386
- input.data.classes.map((element) =>
1387
- this.visitWithGraphBuilderErrorHandling(
1388
- element,
1389
- new V1_ElementThirdPassBuilder(
1390
- this.getBuilderContext(graph, input.model, element, options),
1391
- ),
1392
- ),
1393
- ),
1394
- ),
1356
+ await this.processElementsInBatches(
1357
+ graph,
1358
+ inputs,
1359
+ (data) => data.classes,
1360
+ (ctx) => new V1_ElementThirdPassBuilder(ctx),
1361
+ options,
1395
1362
  );
1396
- await Promise.all(
1397
- inputs.flatMap((input) =>
1398
- input.data.associations.map((element) =>
1399
- this.visitWithGraphBuilderErrorHandling(
1400
- element,
1401
- new V1_ElementThirdPassBuilder(
1402
- this.getBuilderContext(graph, input.model, element, options),
1403
- ),
1404
- ),
1405
- ),
1406
- ),
1363
+ await this.processElementsInBatches(
1364
+ graph,
1365
+ inputs,
1366
+ (data) => data.associations,
1367
+ (ctx) => new V1_ElementThirdPassBuilder(ctx),
1368
+ options,
1407
1369
  );
1408
1370
  // Fourth Pass
1409
- await Promise.all(
1410
- inputs.flatMap((input) =>
1411
- input.data.classes.map((element) =>
1412
- this.visitWithGraphBuilderErrorHandling(
1413
- element,
1414
- new V1_ElementFourthPassBuilder(
1415
- this.getBuilderContext(graph, input.model, element, options),
1416
- ),
1417
- ),
1418
- ),
1419
- ),
1371
+ await this.processElementsInBatches(
1372
+ graph,
1373
+ inputs,
1374
+ (data) => data.classes,
1375
+ (ctx) => new V1_ElementFourthPassBuilder(ctx),
1376
+ options,
1420
1377
  );
1421
- await Promise.all(
1422
- inputs.flatMap((input) =>
1423
- input.data.associations.map((element) =>
1424
- this.visitWithGraphBuilderErrorHandling(
1425
- element,
1426
- new V1_ElementFourthPassBuilder(
1427
- this.getBuilderContext(graph, input.model, element, options),
1428
- ),
1429
- ),
1430
- ),
1431
- ),
1378
+ await this.processElementsInBatches(
1379
+ graph,
1380
+ inputs,
1381
+ (data) => data.associations,
1382
+ (ctx) => new V1_ElementFourthPassBuilder(ctx),
1383
+ options,
1432
1384
  );
1433
1385
  // Fifth pass
1434
- await Promise.all(
1435
- inputs.flatMap((input) =>
1436
- input.data.classes.map((element) =>
1437
- this.visitWithGraphBuilderErrorHandling(
1438
- element,
1439
- new V1_ElementFifthPassBuilder(
1440
- this.getBuilderContext(graph, input.model, element, options),
1441
- ),
1442
- ),
1443
- ),
1444
- ),
1386
+ await this.processElementsInBatches(
1387
+ graph,
1388
+ inputs,
1389
+ (data) => data.classes,
1390
+ (ctx) => new V1_ElementFifthPassBuilder(ctx),
1391
+ options,
1445
1392
  );
1446
1393
  }
1447
1394
 
@@ -1450,17 +1397,12 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1450
1397
  inputs: V1_PureGraphBuilderInput[],
1451
1398
  options?: GraphBuilderOptions,
1452
1399
  ): Promise<void> {
1453
- await Promise.all(
1454
- inputs.flatMap((input) =>
1455
- input.data.functionActivators.map((element) =>
1456
- this.visitWithGraphBuilderErrorHandling(
1457
- element,
1458
- new V1_ElementSecondPassBuilder(
1459
- this.getBuilderContext(graph, input.model, element, options),
1460
- ),
1461
- ),
1462
- ),
1463
- ),
1400
+ await this.processElementsInBatches(
1401
+ graph,
1402
+ inputs,
1403
+ (data) => data.functionActivators,
1404
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1405
+ options,
1464
1406
  );
1465
1407
  }
1466
1408
 
@@ -1469,53 +1411,33 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1469
1411
  inputs: V1_PureGraphBuilderInput[],
1470
1412
  options?: GraphBuilderOptions,
1471
1413
  ): Promise<void> {
1472
- await Promise.all(
1473
- inputs.flatMap((input) =>
1474
- input.data.stores.map((element) =>
1475
- this.visitWithGraphBuilderErrorHandling(
1476
- element,
1477
- new V1_ElementSecondPassBuilder(
1478
- this.getBuilderContext(graph, input.model, element, options),
1479
- ),
1480
- ),
1481
- ),
1482
- ),
1414
+ await this.processElementsInBatches(
1415
+ graph,
1416
+ inputs,
1417
+ (data) => data.stores,
1418
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1419
+ options,
1483
1420
  );
1484
- await Promise.all(
1485
- inputs.flatMap((input) =>
1486
- input.data.stores.map((element) =>
1487
- this.visitWithGraphBuilderErrorHandling(
1488
- element,
1489
- new V1_ElementThirdPassBuilder(
1490
- this.getBuilderContext(graph, input.model, element, options),
1491
- ),
1492
- ),
1493
- ),
1494
- ),
1421
+ await this.processElementsInBatches(
1422
+ graph,
1423
+ inputs,
1424
+ (data) => data.stores,
1425
+ (ctx) => new V1_ElementThirdPassBuilder(ctx),
1426
+ options,
1495
1427
  );
1496
- await Promise.all(
1497
- inputs.flatMap((input) =>
1498
- input.data.stores.map((element) =>
1499
- this.visitWithGraphBuilderErrorHandling(
1500
- element,
1501
- new V1_ElementFourthPassBuilder(
1502
- this.getBuilderContext(graph, input.model, element, options),
1503
- ),
1504
- ),
1505
- ),
1506
- ),
1428
+ await this.processElementsInBatches(
1429
+ graph,
1430
+ inputs,
1431
+ (data) => data.stores,
1432
+ (ctx) => new V1_ElementFourthPassBuilder(ctx),
1433
+ options,
1507
1434
  );
1508
- await Promise.all(
1509
- inputs.flatMap((input) =>
1510
- input.data.stores.map((element) =>
1511
- this.visitWithGraphBuilderErrorHandling(
1512
- element,
1513
- new V1_ElementFifthPassBuilder(
1514
- this.getBuilderContext(graph, input.model, element, options),
1515
- ),
1516
- ),
1517
- ),
1518
- ),
1435
+ await this.processElementsInBatches(
1436
+ graph,
1437
+ inputs,
1438
+ (data) => data.stores,
1439
+ (ctx) => new V1_ElementFifthPassBuilder(ctx),
1440
+ options,
1519
1441
  );
1520
1442
  }
1521
1443
 
@@ -1524,41 +1446,26 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1524
1446
  inputs: V1_PureGraphBuilderInput[],
1525
1447
  options?: GraphBuilderOptions,
1526
1448
  ): Promise<void> {
1527
- await Promise.all(
1528
- inputs.flatMap((input) =>
1529
- input.data.mappings.map((element) =>
1530
- this.visitWithGraphBuilderErrorHandling(
1531
- element,
1532
- new V1_ElementSecondPassBuilder(
1533
- this.getBuilderContext(graph, input.model, element, options),
1534
- ),
1535
- ),
1536
- ),
1537
- ),
1449
+ await this.processElementsInBatches(
1450
+ graph,
1451
+ inputs,
1452
+ (data) => data.mappings,
1453
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1454
+ options,
1538
1455
  );
1539
- await Promise.all(
1540
- inputs.flatMap((input) =>
1541
- input.data.mappings.map((element) =>
1542
- this.visitWithGraphBuilderErrorHandling(
1543
- element,
1544
- new V1_ElementThirdPassBuilder(
1545
- this.getBuilderContext(graph, input.model, element, options),
1546
- ),
1547
- ),
1548
- ),
1549
- ),
1456
+ await this.processElementsInBatches(
1457
+ graph,
1458
+ inputs,
1459
+ (data) => data.mappings,
1460
+ (ctx) => new V1_ElementThirdPassBuilder(ctx),
1461
+ options,
1550
1462
  );
1551
- await Promise.all(
1552
- inputs.flatMap((input) =>
1553
- input.data.mappings.map((element) =>
1554
- this.visitWithGraphBuilderErrorHandling(
1555
- element,
1556
- new V1_ElementFourthPassBuilder(
1557
- this.getBuilderContext(graph, input.model, element, options),
1558
- ),
1559
- ),
1560
- ),
1561
- ),
1463
+ await this.processElementsInBatches(
1464
+ graph,
1465
+ inputs,
1466
+ (data) => data.mappings,
1467
+ (ctx) => new V1_ElementFourthPassBuilder(ctx),
1468
+ options,
1562
1469
  );
1563
1470
  }
1564
1471
 
@@ -1568,29 +1475,19 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1568
1475
  options?: GraphBuilderOptions,
1569
1476
  ): Promise<void> {
1570
1477
  // NOTE: connections must be built before runtimes
1571
- await Promise.all(
1572
- inputs.flatMap((input) =>
1573
- input.data.connections.map((element) =>
1574
- this.visitWithGraphBuilderErrorHandling(
1575
- element,
1576
- new V1_ElementSecondPassBuilder(
1577
- this.getBuilderContext(graph, input.model, element, options),
1578
- ),
1579
- ),
1580
- ),
1581
- ),
1478
+ await this.processElementsInBatches(
1479
+ graph,
1480
+ inputs,
1481
+ (data) => data.connections,
1482
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1483
+ options,
1582
1484
  );
1583
- await Promise.all(
1584
- inputs.flatMap((input) =>
1585
- input.data.runtimes.map((element) =>
1586
- this.visitWithGraphBuilderErrorHandling(
1587
- element,
1588
- new V1_ElementSecondPassBuilder(
1589
- this.getBuilderContext(graph, input.model, element, options),
1590
- ),
1591
- ),
1592
- ),
1593
- ),
1485
+ await this.processElementsInBatches(
1486
+ graph,
1487
+ inputs,
1488
+ (data) => data.runtimes,
1489
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1490
+ options,
1594
1491
  );
1595
1492
  }
1596
1493
 
@@ -1599,29 +1496,19 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1599
1496
  inputs: V1_PureGraphBuilderInput[],
1600
1497
  options?: GraphBuilderOptions,
1601
1498
  ): Promise<void> {
1602
- await Promise.all(
1603
- inputs.flatMap((input) =>
1604
- input.data.services.map((element) =>
1605
- this.visitWithGraphBuilderErrorHandling(
1606
- element,
1607
- new V1_ElementSecondPassBuilder(
1608
- this.getBuilderContext(graph, input.model, element, options),
1609
- ),
1610
- ),
1611
- ),
1612
- ),
1499
+ await this.processElementsInBatches(
1500
+ graph,
1501
+ inputs,
1502
+ (data) => data.services,
1503
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1504
+ options,
1613
1505
  );
1614
- await Promise.all(
1615
- inputs.flatMap((input) =>
1616
- input.data.executionEnvironments.map((element) =>
1617
- this.visitWithGraphBuilderErrorHandling(
1618
- element,
1619
- new V1_ElementSecondPassBuilder(
1620
- this.getBuilderContext(graph, input.model, element, options),
1621
- ),
1622
- ),
1623
- ),
1624
- ),
1506
+ await this.processElementsInBatches(
1507
+ graph,
1508
+ inputs,
1509
+ (data) => data.executionEnvironments,
1510
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1511
+ options,
1625
1512
  );
1626
1513
  }
1627
1514
 
@@ -1630,17 +1517,12 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1630
1517
  inputs: V1_PureGraphBuilderInput[],
1631
1518
  options?: GraphBuilderOptions,
1632
1519
  ): Promise<void> {
1633
- await Promise.all(
1634
- inputs.flatMap((input) =>
1635
- input.data.dataElements.map((element) =>
1636
- this.visitWithGraphBuilderErrorHandling(
1637
- element,
1638
- new V1_ElementSecondPassBuilder(
1639
- this.getBuilderContext(graph, input.model, element, options),
1640
- ),
1641
- ),
1642
- ),
1643
- ),
1520
+ await this.processElementsInBatches(
1521
+ graph,
1522
+ inputs,
1523
+ (data) => data.dataElements,
1524
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1525
+ options,
1644
1526
  );
1645
1527
  }
1646
1528
 
@@ -1649,17 +1531,12 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1649
1531
  inputs: V1_PureGraphBuilderInput[],
1650
1532
  options?: GraphBuilderOptions,
1651
1533
  ): Promise<void> {
1652
- await Promise.all(
1653
- inputs.flatMap((input) =>
1654
- input.data.products.map((element) =>
1655
- this.visitWithGraphBuilderErrorHandling(
1656
- element,
1657
- new V1_ElementSecondPassBuilder(
1658
- this.getBuilderContext(graph, input.model, element, options),
1659
- ),
1660
- ),
1661
- ),
1662
- ),
1534
+ await this.processElementsInBatches(
1535
+ graph,
1536
+ inputs,
1537
+ (data) => data.products,
1538
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1539
+ options,
1663
1540
  );
1664
1541
  }
1665
1542
 
@@ -1668,17 +1545,12 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1668
1545
  inputs: V1_PureGraphBuilderInput[],
1669
1546
  options?: GraphBuilderOptions,
1670
1547
  ): Promise<void> {
1671
- await Promise.all(
1672
- inputs.flatMap((input) =>
1673
- input.data.fileGenerations.map((element) =>
1674
- this.visitWithGraphBuilderErrorHandling(
1675
- element,
1676
- new V1_ElementSecondPassBuilder(
1677
- this.getBuilderContext(graph, input.model, element, options),
1678
- ),
1679
- ),
1680
- ),
1681
- ),
1548
+ await this.processElementsInBatches(
1549
+ graph,
1550
+ inputs,
1551
+ (data) => data.fileGenerations,
1552
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1553
+ options,
1682
1554
  );
1683
1555
  }
1684
1556
 
@@ -1687,17 +1559,12 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1687
1559
  inputs: V1_PureGraphBuilderInput[],
1688
1560
  options?: GraphBuilderOptions,
1689
1561
  ): Promise<void> {
1690
- await Promise.all(
1691
- inputs.flatMap((input) =>
1692
- input.data.generationSpecifications.map((element) =>
1693
- this.visitWithGraphBuilderErrorHandling(
1694
- element,
1695
- new V1_ElementSecondPassBuilder(
1696
- this.getBuilderContext(graph, input.model, element, options),
1697
- ),
1698
- ),
1699
- ),
1700
- ),
1562
+ await this.processElementsInBatches(
1563
+ graph,
1564
+ inputs,
1565
+ (data) => data.generationSpecifications,
1566
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1567
+ options,
1701
1568
  );
1702
1569
  }
1703
1570
 
@@ -1706,17 +1573,12 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1706
1573
  inputs: V1_PureGraphBuilderInput[],
1707
1574
  options?: GraphBuilderOptions,
1708
1575
  ): Promise<void> {
1709
- await Promise.all(
1710
- inputs.flatMap((input) =>
1711
- input.data.sectionIndices.map((element) =>
1712
- this.visitWithGraphBuilderErrorHandling(
1713
- element,
1714
- new V1_ElementSecondPassBuilder(
1715
- this.getBuilderContext(graph, input.model, element, options),
1716
- ),
1717
- ),
1718
- ),
1719
- ),
1576
+ await this.processElementsInBatches(
1577
+ graph,
1578
+ inputs,
1579
+ (data) => data.sectionIndices,
1580
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1581
+ options,
1720
1582
  );
1721
1583
  }
1722
1584
 
@@ -1725,82 +1587,90 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1725
1587
  inputs: V1_PureGraphBuilderInput[],
1726
1588
  options?: GraphBuilderOptions,
1727
1589
  ): Promise<void> {
1728
- await Promise.all(
1729
- this.graphBuilderExtensions.sortedExtraElementBuilders.map(
1730
- async (builder) => {
1731
- await Promise.all(
1732
- inputs.flatMap((input) =>
1733
- (input.data.otherElementsByBuilder.get(builder) ?? []).map(
1734
- (element) =>
1735
- this.visitWithGraphBuilderErrorHandling(
1736
- element,
1737
- new V1_ElementSecondPassBuilder(
1738
- this.getBuilderContext(
1739
- graph,
1740
- input.model,
1741
- element,
1742
- options,
1743
- ),
1744
- ),
1745
- ),
1746
- ),
1747
- ),
1748
- );
1749
- await Promise.all(
1750
- inputs.flatMap((input) =>
1751
- (input.data.otherElementsByBuilder.get(builder) ?? []).map(
1752
- (element) =>
1753
- this.visitWithGraphBuilderErrorHandling(
1754
- element,
1755
- new V1_ElementThirdPassBuilder(
1756
- this.getBuilderContext(
1757
- graph,
1758
- input.model,
1759
- element,
1760
- options,
1761
- ),
1762
- ),
1763
- ),
1764
- ),
1765
- ),
1766
- );
1767
- await Promise.all(
1768
- inputs.flatMap((input) =>
1769
- (input.data.otherElementsByBuilder.get(builder) ?? []).map(
1770
- (element) =>
1771
- this.visitWithGraphBuilderErrorHandling(
1772
- element,
1773
- new V1_ElementFourthPassBuilder(
1774
- this.getBuilderContext(
1775
- graph,
1776
- input.model,
1777
- element,
1778
- options,
1779
- ),
1780
- ),
1781
- ),
1782
- ),
1783
- ),
1784
- );
1785
- await Promise.all(
1786
- inputs.flatMap((input) =>
1787
- (input.data.otherElementsByBuilder.get(builder) ?? []).map(
1788
- (element) =>
1789
- this.visitWithGraphBuilderErrorHandling(
1790
- element,
1791
- new V1_ElementFifthPassBuilder(
1792
- this.getBuilderContext(
1793
- graph,
1794
- input.model,
1795
- element,
1796
- options,
1797
- ),
1798
- ),
1799
- ),
1800
- ),
1801
- ),
1802
- );
1803
- },
1590
+ for (const builder of this.graphBuilderExtensions
1591
+ .sortedExtraElementBuilders) {
1592
+ const getElements = (
1593
+ data: V1_PureModelContextDataIndex,
1594
+ ): V1_PackageableElement[] =>
1595
+ data.otherElementsByBuilder.get(builder) ?? [];
1596
+ await this.processElementsInBatches(
1597
+ graph,
1598
+ inputs,
1599
+ getElements,
1600
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1601
+ options,
1602
+ );
1603
+ await this.processElementsInBatches(
1604
+ graph,
1605
+ inputs,
1606
+ getElements,
1607
+ (ctx) => new V1_ElementThirdPassBuilder(ctx),
1608
+ options,
1609
+ );
1610
+ await this.processElementsInBatches(
1611
+ graph,
1612
+ inputs,
1613
+ getElements,
1614
+ (ctx) => new V1_ElementFourthPassBuilder(ctx),
1615
+ options,
1616
+ );
1617
+ await this.processElementsInBatches(
1618
+ graph,
1619
+ inputs,
1620
+ getElements,
1621
+ (ctx) => new V1_ElementFifthPassBuilder(ctx),
1622
+ options,
1623
+ );
1624
+ }
1625
+ }
1626
+
1627
+ /**
1628
+ * Run a callback for each item in the array, processing items in batches
1629
+ * of {@link GRAPH_BUILDER_BATCH_SIZE} and yielding to the event loop between
1630
+ * batches to keep the UI responsive.
1631
+ */
1632
+ private async runBatchedLoop<T>(
1633
+ items: T[],
1634
+ process: (item: T) => void,
1635
+ ): Promise<void> {
1636
+ for (let i = 0; i < items.length; i += GRAPH_BUILDER_BATCH_SIZE) {
1637
+ if (i > 0) {
1638
+ await new Promise<void>((resolve) => setTimeout(resolve, 0));
1639
+ }
1640
+ const end = Math.min(i + GRAPH_BUILDER_BATCH_SIZE, items.length);
1641
+ for (let j = i; j < end; j++) {
1642
+ process(guaranteeNonNullable(items[j]));
1643
+ }
1644
+ }
1645
+ }
1646
+
1647
+ /**
1648
+ * Process elements from inputs in batches, yielding to the event loop
1649
+ * between batches to keep the UI responsive.
1650
+ */
1651
+ private async processElementsInBatches(
1652
+ graph: PureModel,
1653
+ inputs: V1_PureGraphBuilderInput[],
1654
+ getElements: (
1655
+ data: V1_PureModelContextDataIndex,
1656
+ ) => V1_PackageableElement[],
1657
+ createVisitor: (
1658
+ ctx: V1_GraphBuilderContext,
1659
+ ) => V1_PackageableElementVisitor<unknown>,
1660
+ options?: GraphBuilderOptions,
1661
+ ): Promise<void> {
1662
+ const allItems = inputs.flatMap((input) =>
1663
+ getElements(input.data).map((element) => ({
1664
+ element,
1665
+ model: input.model,
1666
+ })),
1667
+ );
1668
+ await this.runBatchedLoop(allItems, (item) =>
1669
+ this.visitWithGraphBuilderErrorHandling(
1670
+ item.element,
1671
+ createVisitor(
1672
+ this.getBuilderContext(graph, item.model, item.element, options),
1673
+ ),
1804
1674
  ),
1805
1675
  );
1806
1676
  }
@@ -1808,9 +1678,9 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1808
1678
  private visitWithGraphBuilderErrorHandling<T>(
1809
1679
  element: V1_PackageableElement,
1810
1680
  visitor: V1_PackageableElementVisitor<T>,
1811
- ): Promise<T> {
1681
+ ): T {
1812
1682
  try {
1813
- return promisify(() => element.accept_PackageableElementVisitor(visitor));
1683
+ return element.accept_PackageableElementVisitor(visitor);
1814
1684
  } catch (err) {
1815
1685
  assertErrorThrown(err);
1816
1686
  const error =