@abtnode/core 1.16.11-next-a232f5fb → 1.16.11-next-09bc31f8

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.
@@ -38,6 +38,10 @@ const {
38
38
  getRolesFromAuthConfig,
39
39
  isInProgress,
40
40
  isBeforeInstalled,
41
+ getComponentsInternalInfo,
42
+ forEachComponentV2,
43
+ forEachComponentV2Sync,
44
+ findComponentByIdV2,
41
45
  } = require('@blocklet/meta/lib/util');
42
46
  const getComponentProcessId = require('@blocklet/meta/lib/get-component-process-id');
43
47
  const { update: updateMetaFile } = require('@blocklet/meta/lib/file');
@@ -49,6 +53,7 @@ const {
49
53
  BlockletStatus,
50
54
  BlockletSource,
51
55
  BlockletEvents,
56
+ BlockletInternalEvents,
52
57
  BLOCKLET_MODES,
53
58
  BlockletGroup,
54
59
  fromBlockletStatus,
@@ -81,7 +86,6 @@ const {
81
86
  stopBlockletProcess,
82
87
  deleteBlockletProcess,
83
88
  reloadBlockletProcess,
84
- getBlockletStatusFromProcess,
85
89
  checkBlockletProcessHealthy,
86
90
  validateBlocklet,
87
91
  validateBlockletChainInfo,
@@ -104,6 +108,9 @@ const {
104
108
  updateBlockletFallbackLogo,
105
109
  ensureAppLogo,
106
110
  getBlockletDidDomainList,
111
+ getProcessState,
112
+ getBlockletStatus,
113
+ shouldSkipComponent,
107
114
  shouldCleanExpiredBlocklet,
108
115
  } = require('../../util/blocklet');
109
116
  const states = require('../../states');
@@ -133,7 +140,7 @@ const { migrateApplicationToStructV2 } = require('./helper/migrate-application-t
133
140
  const { getBackupFilesUrlFromEndpoint, getBackupEndpoint } = require('../../util/spaces');
134
141
  const { validateAddSpaceGateway, validateUpdateSpaceGateway } = require('../../validators/space-gateway');
135
142
 
136
- const { formatEnvironments, shouldUpdateBlockletStatus, getBlockletMeta, validateOwner } = util;
143
+ const { formatEnvironments, getBlockletMeta, validateOwner } = util;
137
144
 
138
145
  const statusLock = new Lock('blocklet-status-lock');
139
146
 
@@ -239,8 +246,8 @@ class BlockletManager extends BaseBlockletManager {
239
246
  this._rollbackCache = new RollbackCache({ dir: this.dataDirs.tmp });
240
247
 
241
248
  if (daemon) {
242
- blockletPm2Events.on('online', (data) => this._syncPm2Status('online', data.blockletDid));
243
- blockletPm2Events.on('stop', (data) => this._syncPm2Status('stop', data.blockletDid));
249
+ blockletPm2Events.on('online', (data) => this._syncPm2Status('online', data.blockletDid, data.componentDid));
250
+ blockletPm2Events.on('stop', (data) => this._syncPm2Status('stop', data.blockletDid, data.componentDid));
244
251
  }
245
252
  }
246
253
 
@@ -427,8 +434,8 @@ class BlockletManager extends BaseBlockletManager {
427
434
  return UpgradeComponents.check({ did, states });
428
435
  }
429
436
 
430
- async upgradeComponents({ updateId, selectedComponents: selectedComponentDids }, context = {}) {
431
- return UpgradeComponents.upgrade({ updateId, selectedComponentDids, context, states, manager: this });
437
+ async upgradeComponents({ updateId, selectedComponents: componentDids }, context = {}) {
438
+ return UpgradeComponents.upgrade({ updateId, componentDids, context, states, manager: this });
432
439
  }
433
440
 
434
441
  async migrateApplicationToStructV2({ did, appSk, context = {} }) {
@@ -445,8 +452,8 @@ class BlockletManager extends BaseBlockletManager {
445
452
  return { did, isInstalled: !!blocklet, isRunning };
446
453
  }
447
454
 
448
- async start({ did, throwOnError, checkHealthImmediately = false, e2eMode = false }, context) {
449
- logger.info('start blocklet', { did });
455
+ async start({ did, throwOnError, checkHealthImmediately = false, e2eMode = false, componentDids }, context) {
456
+ logger.info('start blocklet', { did, componentDids, throwOnError, checkHealthImmediately, e2eMode });
450
457
  // should check blocklet integrity
451
458
  const blocklet = await this.ensureBlocklet(did, { e2eMode });
452
459
 
@@ -454,7 +461,7 @@ class BlockletManager extends BaseBlockletManager {
454
461
  // blocklet may be manually stopped durning starting
455
462
  // so error message would not be sent if blocklet is stopped
456
463
  // so we need update status first
457
- await states.blocklet.setBlockletStatus(did, BlockletStatus.starting);
464
+ await states.blocklet.setBlockletStatus(did, BlockletStatus.starting, { componentDids });
458
465
  blocklet.status = BlockletStatus.starting;
459
466
 
460
467
  // validate requirement and engine
@@ -507,6 +514,7 @@ class BlockletManager extends BaseBlockletManager {
507
514
  nodeEnvironments,
508
515
  nodeInfo: await states.node.read(),
509
516
  e2eMode,
517
+ componentDids,
510
518
  });
511
519
 
512
520
  // check blocklet healthy
@@ -516,6 +524,7 @@ class BlockletManager extends BaseBlockletManager {
516
524
  context,
517
525
  minConsecutiveTime,
518
526
  timeout: startTimeout,
527
+ componentDids,
519
528
  };
520
529
 
521
530
  if (checkHealthImmediately) {
@@ -548,8 +557,8 @@ class BlockletManager extends BaseBlockletManager {
548
557
  severity: 'error',
549
558
  });
550
559
 
551
- await this.deleteProcess({ did });
552
- const res = await states.blocklet.setBlockletStatus(did, BlockletStatus.error);
560
+ await this.deleteProcess({ did, componentDids });
561
+ const res = await states.blocklet.setBlockletStatus(did, BlockletStatus.error, { componentDids });
553
562
  this.emit(BlockletEvents.startFailed, { ...res, error: { message: error.message } });
554
563
 
555
564
  if (throwOnError) {
@@ -560,14 +569,14 @@ class BlockletManager extends BaseBlockletManager {
560
569
  }
561
570
  }
562
571
 
563
- async stop({ did, updateStatus = true, silent = false }, context) {
564
- logger.info('stop blocklet', { did });
572
+ async stop({ did, updateStatus = true, silent = false, componentDids }, context) {
573
+ logger.info('stop blocklet', { did, componentDids, updateStatus, silent });
565
574
 
566
575
  const blocklet = await this.getBlocklet(did);
567
576
  const { processId } = blocklet.env;
568
577
 
569
578
  if (updateStatus) {
570
- await states.blocklet.setBlockletStatus(did, BlockletStatus.stopping);
579
+ await states.blocklet.setBlockletStatus(did, BlockletStatus.stopping, { componentDids });
571
580
  blocklet.status = BlockletStatus.stopping;
572
581
  this.emit(BlockletEvents.statusChange, blocklet);
573
582
  }
@@ -587,11 +596,12 @@ class BlockletManager extends BaseBlockletManager {
587
596
  silent,
588
597
  ...getHooksOutputFiles(b),
589
598
  }),
599
+ componentDids,
590
600
  });
591
601
  } catch (error) {
592
602
  logger.error('Failed to stop blocklet', { error, did });
593
603
  if (updateStatus) {
594
- const res = await states.blocklet.setBlockletStatus(did, BlockletStatus.error);
604
+ const res = await states.blocklet.setBlockletStatus(did, BlockletStatus.error, { componentDids });
595
605
  this.emit(BlockletEvents.statusChange, res);
596
606
  }
597
607
  throw error;
@@ -600,13 +610,18 @@ class BlockletManager extends BaseBlockletManager {
600
610
  logger.info('blocklet stopped successfully', { processId, did });
601
611
 
602
612
  if (updateStatus) {
603
- const res = await states.blocklet.setBlockletStatus(did, BlockletStatus.stopped);
613
+ const res = await states.blocklet.setBlockletStatus(did, BlockletStatus.stopped, { componentDids });
604
614
  // send notification to websocket channel
605
615
  this.emit(BlockletEvents.statusChange, res);
606
616
 
607
617
  // send notification to wallet
608
618
  this.emit(BlockletEvents.stopped, res);
609
619
 
620
+ this.emit(BlockletInternalEvents.componentsUpdated, {
621
+ appDid: blocklet.appDid,
622
+ components: getComponentsInternalInfo(res),
623
+ });
624
+
610
625
  return res;
611
626
  }
612
627
 
@@ -660,18 +675,25 @@ class BlockletManager extends BaseBlockletManager {
660
675
  * @param {Record<string, any>} context
661
676
  * @returns {import('@abtnode/client').BlockletState}
662
677
  */
663
- async restart({ did }, context) {
678
+ async restart({ did, componentDids }, context) {
664
679
  logger.info('restart blocklet', { did });
665
680
 
666
- await states.blocklet.setBlockletStatus(did, BlockletStatus.stopping);
681
+ await states.blocklet.setBlockletStatus(did, BlockletStatus.stopping, { componentDids });
667
682
  const result = await states.blocklet.getBlocklet(did);
668
683
  this.emit(BlockletEvents.statusChange, result);
669
684
 
670
- const ticket = this.startQueue.push({ entity: 'blocklet', action: 'restart', id: did, did, context });
685
+ const ticket = this.startQueue.push({
686
+ entity: 'blocklet',
687
+ action: 'restart',
688
+ id: did,
689
+ did,
690
+ componentDids,
691
+ context,
692
+ });
671
693
  ticket.on('failed', async (err) => {
672
694
  logger.error('failed to restart blocklet', { did, error: err });
673
695
 
674
- const state = await states.blocklet.setBlockletStatus(did, BlockletStatus.stopped);
696
+ const state = await states.blocklet.setBlockletStatus(did, BlockletStatus.stopped, { componentDids });
675
697
  this.emit(BlockletEvents.statusChange, state);
676
698
 
677
699
  this._createNotification(did, {
@@ -687,16 +709,28 @@ class BlockletManager extends BaseBlockletManager {
687
709
  }
688
710
 
689
711
  // eslint-disable-next-line no-unused-vars
690
- async reload({ did }, context) {
712
+ async reload({ did, componentDids: list }, context) {
691
713
  const blocklet = await this.getBlocklet(did);
692
714
 
693
- await states.blocklet.setBlockletStatus(did, BlockletStatus.stopping);
694
- await reloadBlockletProcess(blocklet);
695
- const res = await states.blocklet.setBlockletStatus(did, BlockletStatus.running);
696
- logger.info('blocklet reload successfully', { did });
715
+ const componentDids = (blocklet.children || [])
716
+ .filter((x) => x.status === BlockletStatus.running)
717
+ .filter((x) => !shouldSkipComponent(x.meta.did, list))
718
+ .map((x) => x.meta.did);
697
719
 
698
- this.emit(BlockletEvents.statusChange, res);
699
- return res;
720
+ if (!componentDids.length) {
721
+ throw new Error('No running component found');
722
+ }
723
+
724
+ try {
725
+ await reloadBlockletProcess(blocklet, { componentDids });
726
+ const res = await states.blocklet.setBlockletStatus(did, BlockletStatus.running, { componentDids });
727
+ logger.info('blocklet reload successfully', { did, componentDids });
728
+ this.emit(BlockletEvents.statusChange, res);
729
+ return res;
730
+ } catch (error) {
731
+ logger.error('Failed to reload blocklet', { error, did, componentDids });
732
+ throw error;
733
+ }
700
734
  }
701
735
 
702
736
  async delete({ did, keepData, keepLogsDir, keepConfigs }, context) {
@@ -755,17 +789,17 @@ class BlockletManager extends BaseBlockletManager {
755
789
 
756
790
  const blocklet = await this.getBlocklet(did);
757
791
 
758
- if (isInProgress(blocklet.status || blocklet.status === BlockletStatus.running)) {
759
- throw new Error('Cannot reset when blocklet is in progress');
760
- }
792
+ if (!childDid) {
793
+ if (isInProgress(blocklet.status || blocklet.status === BlockletStatus.running)) {
794
+ throw new Error('Cannot reset when blocklet is in progress');
795
+ }
761
796
 
762
- try {
763
- await this.deleteProcess({ did }, context);
764
- } catch {
765
- // do nothing
766
- }
797
+ try {
798
+ await this.deleteProcess({ did }, context);
799
+ } catch {
800
+ // do nothing
801
+ }
767
802
 
768
- if (!childDid) {
769
803
  // Cleanup disk storage
770
804
  const { cacheDir, logsDir, dataDir } = blocklet.env;
771
805
  fs.removeSync(cacheDir);
@@ -783,6 +817,16 @@ class BlockletManager extends BaseBlockletManager {
783
817
  throw new Error('Child does not exist');
784
818
  }
785
819
 
820
+ if (isInProgress(child.status || child.status === BlockletStatus.running)) {
821
+ throw new Error('Cannot reset when component is in progress');
822
+ }
823
+
824
+ try {
825
+ await this.deleteProcess({ did, componentDids: [child.meta.did] }, context);
826
+ } catch {
827
+ // do nothing
828
+ }
829
+
786
830
  // Cleanup disk storage
787
831
  const { cacheDir, logsDir, dataDir } = child.env;
788
832
  fs.removeSync(cacheDir);
@@ -864,6 +908,11 @@ class BlockletManager extends BaseBlockletManager {
864
908
  action: `/blocklets/${newBlocklet.meta.did}/components`,
865
909
  });
866
910
 
911
+ this.emit(BlockletInternalEvents.componentsUpdated, {
912
+ appDid: blocklet.appDid,
913
+ components: getComponentsInternalInfo(newBlocklet),
914
+ });
915
+
867
916
  return newBlocklet;
868
917
  }
869
918
 
@@ -922,7 +971,14 @@ class BlockletManager extends BaseBlockletManager {
922
971
  // fallback blocklet status to error
923
972
  const blocklet = await states.blocklet.getBlocklet(inputDid);
924
973
  if (blocklet) {
925
- await states.blocklet.setBlockletStatus(blocklet.meta.did, BlockletStatus.error);
974
+ const componentDids = [];
975
+ forEachComponentV2Sync(blocklet, (x) => {
976
+ if ([BlockletStatus.waiting, BlockletStatus.downloading].includes(x.status)) {
977
+ componentDids.push(x.meta.did);
978
+ }
979
+ });
980
+
981
+ await states.blocklet.setBlockletStatus(blocklet.meta.did, BlockletStatus.error, { componentDids });
926
982
  }
927
983
  statusLock.release();
928
984
  } catch (err) {
@@ -935,15 +991,15 @@ class BlockletManager extends BaseBlockletManager {
935
991
  }
936
992
 
937
993
  // eslint-disable-next-line no-unused-vars
938
- async deleteProcess({ did }, context) {
994
+ async deleteProcess({ did, componentDids }, context) {
939
995
  const blocklet = await this.getBlocklet(did);
940
996
 
941
- logger.info('delete blocklet process', { did });
997
+ logger.info('delete blocklet process', { did, componentDids });
942
998
 
943
- await deleteBlockletProcess(blocklet, context);
999
+ await deleteBlockletProcess(blocklet, { ...context, componentDids });
944
1000
 
945
- const result = await states.blocklet.setBlockletStatus(did, BlockletStatus.stopped);
946
- logger.info('blocklet process deleted successfully', { did });
1001
+ const result = await states.blocklet.setBlockletStatus(did, BlockletStatus.stopped, { componentDids });
1002
+ logger.info('blocklet process deleted successfully', { did, componentDids });
947
1003
  return result;
948
1004
  }
949
1005
 
@@ -1021,19 +1077,18 @@ class BlockletManager extends BaseBlockletManager {
1021
1077
  }
1022
1078
 
1023
1079
  const tmpDids = Array.isArray(did) ? did : [did];
1024
- const [rootDid, ...childDids] = tmpDids;
1080
+ const [rootDid, childDid] = tmpDids;
1025
1081
  const rootMetaDid = await states.blocklet.getBlockletMetaDid(rootDid);
1026
- const dids = [rootMetaDid, ...childDids];
1027
1082
 
1028
- logger.info('config blocklet', { dids });
1083
+ logger.info('config blocklet', { rootDid, rootMetaDid, childDid });
1029
1084
 
1030
1085
  const ancestors = [];
1031
1086
  let blocklet = await this.getBlocklet(rootDid);
1032
- for (const childDid of childDids) {
1087
+ if (childDid) {
1033
1088
  ancestors.push(blocklet);
1034
1089
  blocklet = blocklet.children.find((x) => x.meta.did === childDid);
1035
1090
  if (!blocklet) {
1036
- throw new Error('Child blocklet does not exist', { dids });
1091
+ throw new Error('Child blocklet does not exist', { rootDid, childDid });
1037
1092
  }
1038
1093
  }
1039
1094
 
@@ -1046,8 +1101,8 @@ class BlockletManager extends BaseBlockletManager {
1046
1101
  await environmentNameSchema.validateAsync(x.key);
1047
1102
  } else if (BLOCKLET_CONFIGURABLE_KEY[x.key] && x.key.startsWith('BLOCKLET_')) {
1048
1103
  // app key
1049
- if (childDids.length) {
1050
- logger.error(`Cannot set ${x.key} to child blocklet`, [dids]);
1104
+ if (childDid) {
1105
+ logger.error(`Cannot set ${x.key} to child blocklet`, { rootDid, childDid });
1051
1106
  throw new Error(`Cannot set ${x.key} to child blocklet`);
1052
1107
  }
1053
1108
  await validateAppConfig(x, states);
@@ -1086,7 +1141,7 @@ class BlockletManager extends BaseBlockletManager {
1086
1141
  Object.assign(blocklet.configObj, configObj);
1087
1142
 
1088
1143
  // update db
1089
- await states.blockletExtras.setConfigs(dids, newConfigs);
1144
+ await states.blockletExtras.setConfigs([rootMetaDid, childDid].filter(Boolean), newConfigs);
1090
1145
 
1091
1146
  if (willAppSkChange) {
1092
1147
  const info = await states.node.read();
@@ -1106,7 +1161,7 @@ class BlockletManager extends BaseBlockletManager {
1106
1161
  }
1107
1162
 
1108
1163
  // update blocklet meta
1109
- if (blocklet.structVersion && !childDids.length) {
1164
+ if (blocklet.structVersion && !childDid) {
1110
1165
  const changedTitle = newConfigs.find((x) => x.key === BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_NAME)?.value;
1111
1166
  const changedDescription = newConfigs.find(
1112
1167
  (x) => x.key === BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_DESCRIPTION
@@ -1135,6 +1190,13 @@ class BlockletManager extends BaseBlockletManager {
1135
1190
  await this._updateDidDocument(newState);
1136
1191
  }
1137
1192
 
1193
+ if (!childDid && !newConfigs.some((x) => x.key === BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_SK)) {
1194
+ this.emit(BlockletInternalEvents.appConfigChanged, {
1195
+ appDid: newState.appDid,
1196
+ configs: newConfigs.map((x) => ({ key: x.key, value: x.value })),
1197
+ });
1198
+ }
1199
+
1138
1200
  this.emit(BlockletEvents.updated, newState);
1139
1201
 
1140
1202
  return newState;
@@ -1311,6 +1373,10 @@ class BlockletManager extends BaseBlockletManager {
1311
1373
  await states.blocklet.updateBlocklet(rootDid, { mountPoint: blocklet.mountPoint, children: blocklet.children });
1312
1374
 
1313
1375
  this.emit(BlockletEvents.upgraded, { blocklet, context: { ...context, createAuditLog: false } }); // trigger router refresh
1376
+ this.emit(BlockletInternalEvents.componentsUpdated, {
1377
+ appDid: blocklet.appDid,
1378
+ components: getComponentsInternalInfo(blocklet),
1379
+ });
1314
1380
 
1315
1381
  return this.getBlocklet(rootDid);
1316
1382
  }
@@ -1369,57 +1435,54 @@ class BlockletManager extends BaseBlockletManager {
1369
1435
  return this.getBlocklet(did);
1370
1436
  }
1371
1437
 
1372
- async status(did, { forceSync = false } = {}) {
1373
- const fastReturnOnForceSync = async (blocklet = {}) => {
1374
- const { status } = blocklet;
1375
- const { added, waiting, downloading, installing, installed, upgrading } = BlockletStatus;
1376
-
1377
- if ([added, waiting, downloading, installing, installed, upgrading].includes(status)) {
1378
- return blocklet;
1379
- }
1380
-
1381
- const res = await states.blocklet.setBlockletStatus(did, BlockletStatus.stopped);
1382
- this.emit(BlockletEvents.statusChange, res);
1383
- return res;
1384
- };
1385
-
1438
+ async status(did, { forceSync = false, componentDids } = {}) {
1386
1439
  const blocklet = await this.getBlocklet(did);
1387
1440
 
1388
- let shouldUpdateStatus = forceSync || shouldUpdateBlockletStatus(blocklet.status);
1389
- if (isInProgress(blocklet.status)) {
1390
- const uptime = Date.now() - new Date(blocklet.updatedAt).getTime();
1391
- // FIXME @linchen 在彻底修复 blocklet status 稳定性之后, uptime check 应该去掉. 如果 hook 执行时间很长, uptime check 会影响 hook 执行过程中的 blocklet status
1392
- if (uptime > 120 * 1000) {
1393
- shouldUpdateStatus = true;
1394
- }
1395
- }
1396
-
1397
- if (!shouldUpdateStatus) {
1441
+ // for backward compatibility
1442
+ if (!blocklet.structVersion) {
1398
1443
  return blocklet;
1399
1444
  }
1400
1445
 
1401
- try {
1402
- if (
1403
- blocklet.meta?.group === BlockletGroup.gateway &&
1404
- !blocklet.children?.length &&
1405
- isInProgress(blocklet.status)
1406
- ) {
1407
- const res = await states.blocklet.setBlockletStatus(did, BlockletStatus.stopped);
1408
- this.emit(BlockletEvents.statusChange, res);
1409
- return res;
1410
- }
1446
+ await forEachComponentV2(
1447
+ blocklet,
1448
+ async (component) => {
1449
+ if (!forceSync && !util.shouldUpdateBlockletStatus(component.status)) {
1450
+ return;
1451
+ }
1411
1452
 
1412
- const status = await getBlockletStatusFromProcess(blocklet);
1413
- if (blocklet.status !== status) {
1414
- const res = await states.blocklet.setBlockletStatus(did, status);
1415
- this.emit(BlockletEvents.statusChange, res);
1416
- return res;
1417
- }
1453
+ if (shouldSkipComponent(component.meta.did, componentDids)) {
1454
+ return;
1455
+ }
1418
1456
 
1419
- return blocklet;
1420
- } catch (err) {
1421
- return fastReturnOnForceSync(blocklet);
1422
- }
1457
+ try {
1458
+ const status = await getProcessState(component.env.processId);
1459
+ if (component.status !== status) {
1460
+ component.status = status;
1461
+ await states.blocklet.setBlockletStatus(did, status, { componentDids: [component.meta.did] });
1462
+ }
1463
+ } catch {
1464
+ if (
1465
+ ![
1466
+ BlockletStatus.added,
1467
+ BlockletStatus.waiting,
1468
+ BlockletStatus.downloading,
1469
+ BlockletStatus.installing,
1470
+ BlockletStatus.installed,
1471
+ BlockletStatus.upgrading,
1472
+ ].includes(component.status)
1473
+ ) {
1474
+ const status = BlockletStatus.stopped;
1475
+ component.status = status;
1476
+ await states.blocklet.setBlockletStatus(did, status, { componentDids: [component.meta.did] });
1477
+ }
1478
+ }
1479
+ },
1480
+ { parallel: true }
1481
+ );
1482
+
1483
+ blocklet.status = getBlockletStatus(blocklet);
1484
+
1485
+ return blocklet;
1423
1486
  }
1424
1487
 
1425
1488
  async refreshListCache() {
@@ -1486,6 +1549,7 @@ class BlockletManager extends BaseBlockletManager {
1486
1549
  name: 'sync-blocklet-status',
1487
1550
  time: '*/60 * * * * *', // 60s
1488
1551
  fn: this._syncBlockletStatus.bind(this),
1552
+ options: { runOnInit: false },
1489
1553
  },
1490
1554
  {
1491
1555
  name: 'sync-blocklet-list',
@@ -1636,7 +1700,7 @@ class BlockletManager extends BaseBlockletManager {
1636
1700
  * oldBlocklet: {},
1637
1701
  * throwOnError: Error,
1638
1702
  * skipCheckStatusBeforeDownload: boolean,
1639
- * selectedComponentDids: Array<did>,
1703
+ * componentDids: Array<did>,
1640
1704
  * }} params
1641
1705
  * @return {*}
1642
1706
  * @memberof BlockletManager
@@ -1649,7 +1713,7 @@ class BlockletManager extends BaseBlockletManager {
1649
1713
  oldBlocklet,
1650
1714
  throwOnError,
1651
1715
  skipCheckStatusBeforeDownload,
1652
- selectedComponentDids,
1716
+ componentDids,
1653
1717
  skipCheckIntegrity,
1654
1718
  } = params;
1655
1719
  const { meta } = blocklet;
@@ -1686,8 +1750,8 @@ class BlockletManager extends BaseBlockletManager {
1686
1750
  const blockletForDownload = {
1687
1751
  ...blocklet,
1688
1752
  children: (blocklet.children || []).filter((x) => {
1689
- if (selectedComponentDids?.length) {
1690
- return selectedComponentDids.includes(x.meta.did);
1753
+ if (componentDids?.length) {
1754
+ return componentDids.includes(x.meta.did);
1691
1755
  }
1692
1756
  return x;
1693
1757
  }),
@@ -1758,12 +1822,12 @@ class BlockletManager extends BaseBlockletManager {
1758
1822
  }
1759
1823
 
1760
1824
  if (postAction === 'install') {
1761
- const state = await states.blocklet.setBlockletStatus(did, BlockletStatus.installing);
1825
+ const state = await states.blocklet.setBlockletStatus(did, BlockletStatus.installing, { componentDids });
1762
1826
  this.emit(BlockletEvents.statusChange, state);
1763
1827
  }
1764
1828
 
1765
1829
  if (postAction === 'upgrade') {
1766
- const state = await states.blocklet.setBlockletStatus(did, BlockletStatus.upgrading);
1830
+ const state = await states.blocklet.setBlockletStatus(did, BlockletStatus.upgrading, { componentDids });
1767
1831
  this.emit(BlockletEvents.statusChange, state);
1768
1832
  }
1769
1833
 
@@ -1777,13 +1841,13 @@ class BlockletManager extends BaseBlockletManager {
1777
1841
  try {
1778
1842
  // install blocklet
1779
1843
  if (postAction === 'install') {
1780
- await this._onInstall({ blocklet, context, oldBlocklet });
1844
+ await this._onInstall({ blocklet, componentDids, context, oldBlocklet });
1781
1845
  return;
1782
1846
  }
1783
1847
 
1784
1848
  // upgrade blocklet
1785
1849
  if (postAction === 'upgrade') {
1786
- await this._onUpgrade({ oldBlocklet, newBlocklet: blocklet, context });
1850
+ await this._onUpgrade({ oldBlocklet, componentDids, newBlocklet: blocklet, context });
1787
1851
  }
1788
1852
  } catch (error) {
1789
1853
  if (throwOnError) {
@@ -1792,7 +1856,7 @@ class BlockletManager extends BaseBlockletManager {
1792
1856
  }
1793
1857
  }
1794
1858
 
1795
- async _onInstall({ blocklet, context, oldBlocklet }) {
1859
+ async _onInstall({ blocklet, componentDids, context, oldBlocklet }) {
1796
1860
  const { meta } = blocklet;
1797
1861
  const { did, version } = meta;
1798
1862
  logger.info('do install blocklet', { did, version });
@@ -1800,6 +1864,7 @@ class BlockletManager extends BaseBlockletManager {
1800
1864
  try {
1801
1865
  const installedBlocklet = await this._installBlocklet({
1802
1866
  did,
1867
+ componentDids,
1803
1868
  context,
1804
1869
  oldBlocklet,
1805
1870
  });
@@ -1807,7 +1872,7 @@ class BlockletManager extends BaseBlockletManager {
1807
1872
  if (context.startImmediately && installedBlocklet?.settings.initialized) {
1808
1873
  try {
1809
1874
  logger.info('start blocklet after installed', { did });
1810
- await this.start({ did, checkHealthImmediately: true });
1875
+ await this.start({ did, checkHealthImmediately: true, componentDids });
1811
1876
  } catch (error) {
1812
1877
  logger.warn('attempt to start immediately failed', { did, error });
1813
1878
  }
@@ -1820,7 +1885,7 @@ class BlockletManager extends BaseBlockletManager {
1820
1885
  }
1821
1886
  }
1822
1887
 
1823
- async _onUpgrade({ oldBlocklet, newBlocklet, context }) {
1888
+ async _onUpgrade({ oldBlocklet, newBlocklet, componentDids, context }) {
1824
1889
  const { version, did } = newBlocklet.meta;
1825
1890
  logger.info('do upgrade blocklet', { did, version });
1826
1891
 
@@ -1828,6 +1893,7 @@ class BlockletManager extends BaseBlockletManager {
1828
1893
  await this._upgradeBlocklet({
1829
1894
  newBlocklet,
1830
1895
  oldBlocklet,
1896
+ componentDids,
1831
1897
  context,
1832
1898
  });
1833
1899
  } catch (err) {
@@ -1835,13 +1901,13 @@ class BlockletManager extends BaseBlockletManager {
1835
1901
  }
1836
1902
  }
1837
1903
 
1838
- async _onRestart({ did, context }) {
1839
- await this.stop({ did, updateStatus: false }, context);
1840
- await this.start({ did }, context);
1904
+ async _onRestart({ did, componentDids, context }) {
1905
+ await this.stop({ did, componentDids, updateStatus: false }, context);
1906
+ await this.start({ did, componentDids }, context);
1841
1907
  }
1842
1908
 
1843
1909
  async _onCheckIfStarted(jobInfo, { throwOnError } = {}) {
1844
- const { did, context, minConsecutiveTime = 5000, timeout } = jobInfo;
1910
+ const { did, context, minConsecutiveTime = 5000, timeout, componentDids } = jobInfo;
1845
1911
  const blocklet = await this.getBlocklet(did);
1846
1912
 
1847
1913
  const { meta } = blocklet;
@@ -1849,10 +1915,18 @@ class BlockletManager extends BaseBlockletManager {
1849
1915
 
1850
1916
  try {
1851
1917
  // healthy check
1852
- await checkBlockletProcessHealthy(blocklet, { minConsecutiveTime, timeout });
1918
+ await checkBlockletProcessHealthy(blocklet, { minConsecutiveTime, timeout, componentDids });
1853
1919
 
1854
1920
  // update blocklet status after healthy check
1855
- const res = await this.status(did, { forceSync: true });
1921
+ await states.blocklet.setBlockletStatus(did, BlockletStatus.running, { componentDids });
1922
+
1923
+ const res = await this.getBlocklet(did);
1924
+
1925
+ this.emit(BlockletInternalEvents.componentsUpdated, {
1926
+ appDid: blocklet.appDid,
1927
+ components: getComponentsInternalInfo(res),
1928
+ });
1929
+
1856
1930
  this.emit(BlockletEvents.started, res);
1857
1931
  } catch (error) {
1858
1932
  const status = await states.blocklet.getBlockletStatus(did);
@@ -1864,7 +1938,7 @@ class BlockletManager extends BaseBlockletManager {
1864
1938
  logger.error('check blocklet if started failed', { did, name, context, timeout, error });
1865
1939
 
1866
1940
  await this.deleteProcess({ did }, context);
1867
- await states.blocklet.setBlockletStatus(did, BlockletStatus.error);
1941
+ await states.blocklet.setBlockletStatus(did, BlockletStatus.error, { componentDids });
1868
1942
 
1869
1943
  this._createNotification(did, {
1870
1944
  title: 'Blocklet Start Failed',
@@ -2256,7 +2330,7 @@ class BlockletManager extends BaseBlockletManager {
2256
2330
  * @param {string} opt.did
2257
2331
  * @param {object} opt.context
2258
2332
  */
2259
- async _installBlocklet({ did, oldBlocklet, context, createNotification = true }) {
2333
+ async _installBlocklet({ did, oldBlocklet, componentDids, context, createNotification = true }) {
2260
2334
  try {
2261
2335
  // should ensure blocklet integrity
2262
2336
  let blocklet = await this.ensureBlocklet(did);
@@ -2280,7 +2354,9 @@ class BlockletManager extends BaseBlockletManager {
2280
2354
  // post install
2281
2355
  await this._runPostInstallHook(blocklet, context);
2282
2356
 
2283
- await states.blocklet.setBlockletStatus(did, BlockletStatus.installed);
2357
+ await states.blocklet.setInstalledAt(did);
2358
+
2359
+ await states.blocklet.setBlockletStatus(did, BlockletStatus.installed, { componentDids });
2284
2360
  blocklet = await this.getBlocklet(did);
2285
2361
  logger.info('blocklet installed', { source, did: meta.did });
2286
2362
 
@@ -2369,7 +2445,7 @@ class BlockletManager extends BaseBlockletManager {
2369
2445
  }
2370
2446
  }
2371
2447
 
2372
- async _upgradeBlocklet({ newBlocklet, oldBlocklet, context = {} }) {
2448
+ async _upgradeBlocklet({ newBlocklet, oldBlocklet, componentDids, context = {} }) {
2373
2449
  const { meta, source, deployedFrom, children } = newBlocklet;
2374
2450
  const { did, version, name, title } = meta;
2375
2451
 
@@ -2434,11 +2510,11 @@ class BlockletManager extends BaseBlockletManager {
2434
2510
 
2435
2511
  const status =
2436
2512
  oldBlocklet.status === BlockletStatus.installed ? BlockletStatus.installed : BlockletStatus.stopped;
2437
- await states.blocklet.setBlockletStatus(did, status, { children: 'all' });
2513
+ await states.blocklet.setBlockletStatus(did, status, { componentDids });
2438
2514
 
2439
2515
  // start new process
2440
2516
  if (oldBlocklet.status === BlockletStatus.running) {
2441
- await this.start({ did }, context);
2517
+ await this.start({ did, componentDids }, context);
2442
2518
  logger.info('started blocklet for upgrading', { did, version });
2443
2519
  }
2444
2520
 
@@ -2469,6 +2545,11 @@ class BlockletManager extends BaseBlockletManager {
2469
2545
 
2470
2546
  await this._rollbackCache.remove({ did: blocklet.meta.did });
2471
2547
 
2548
+ this.emit(BlockletInternalEvents.componentsUpdated, {
2549
+ appDid: blocklet.appDid,
2550
+ components: getComponentsInternalInfo(blocklet),
2551
+ });
2552
+
2472
2553
  return blocklet;
2473
2554
  } catch (err) {
2474
2555
  const b = await this._rollback('upgrade', did, oldBlocklet);
@@ -2525,10 +2606,12 @@ class BlockletManager extends BaseBlockletManager {
2525
2606
  ...context,
2526
2607
  preDownload: async ({ downloadComponentIds }) => {
2527
2608
  // update children status
2528
- const blocklet1 = await states.blocklet.setBlockletStatus(did, BlockletStatus.downloading, {
2529
- children: downloadComponentIds,
2530
- });
2531
- this.emit(BlockletEvents.statusChange, blocklet1);
2609
+ if (downloadComponentIds?.length) {
2610
+ const blocklet1 = await states.blocklet.setBlockletStatus(did, BlockletStatus.downloading, {
2611
+ componentDids: downloadComponentIds,
2612
+ });
2613
+ this.emit(BlockletEvents.statusChange, blocklet1);
2614
+ }
2532
2615
  },
2533
2616
  onProgress: async (data) => {
2534
2617
  this.emit(BlockletEvents.downloadBundleProgress, { appDid: appDid || did, meta: { did }, ...data });
@@ -2542,16 +2625,17 @@ class BlockletManager extends BaseBlockletManager {
2542
2625
  });
2543
2626
  }
2544
2627
 
2545
- async _syncPm2Status(pm2Status, did) {
2628
+ async _syncPm2Status(pm2Status, did, componentDid) {
2546
2629
  try {
2547
- const state = await states.blocklet.getBlocklet(did);
2548
- if (state && util.shouldUpdateBlockletStatus(state.status)) {
2630
+ const blocklet = await states.blocklet.getBlocklet(did);
2631
+ const component = findComponentByIdV2(blocklet, componentDid);
2632
+ if (component && util.shouldUpdateBlockletStatus(component.status)) {
2549
2633
  const newStatus = pm2StatusMap[pm2Status];
2550
- await states.blocklet.setBlockletStatus(did, newStatus);
2551
- logger.info('sync pm2 status to blocklet', { did, pm2Status, newStatus });
2634
+ await states.blocklet.setBlockletStatus(did, newStatus, { componentDids: [componentDid] });
2635
+ logger.info('sync pm2 status to blocklet', { did, componentDid, pm2Status, newStatus });
2552
2636
  }
2553
2637
  } catch (error) {
2554
- logger.error('sync pm2 status to blocklet failed', { did, pm2Status, error });
2638
+ logger.error('sync pm2 status to blocklet failed', { did, componentDid, pm2Status, error });
2555
2639
  }
2556
2640
  }
2557
2641