@abtnode/core 1.16.11-next-a232f5fb → 1.16.11-next-3d2b39f7

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,40 @@ 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 || !isInProgress(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
+ await states.blocklet.setBlockletStatus(did, status, { componentDids: [component.meta.did] });
1461
+ }
1462
+ } catch {
1463
+ // do nothing
1464
+ }
1465
+ },
1466
+ { parallel: true }
1467
+ );
1468
+
1469
+ blocklet.status = getBlockletStatus(blocklet);
1470
+
1471
+ return blocklet;
1423
1472
  }
1424
1473
 
1425
1474
  async refreshListCache() {
@@ -1636,7 +1685,7 @@ class BlockletManager extends BaseBlockletManager {
1636
1685
  * oldBlocklet: {},
1637
1686
  * throwOnError: Error,
1638
1687
  * skipCheckStatusBeforeDownload: boolean,
1639
- * selectedComponentDids: Array<did>,
1688
+ * componentDids: Array<did>,
1640
1689
  * }} params
1641
1690
  * @return {*}
1642
1691
  * @memberof BlockletManager
@@ -1649,7 +1698,7 @@ class BlockletManager extends BaseBlockletManager {
1649
1698
  oldBlocklet,
1650
1699
  throwOnError,
1651
1700
  skipCheckStatusBeforeDownload,
1652
- selectedComponentDids,
1701
+ componentDids,
1653
1702
  skipCheckIntegrity,
1654
1703
  } = params;
1655
1704
  const { meta } = blocklet;
@@ -1686,8 +1735,8 @@ class BlockletManager extends BaseBlockletManager {
1686
1735
  const blockletForDownload = {
1687
1736
  ...blocklet,
1688
1737
  children: (blocklet.children || []).filter((x) => {
1689
- if (selectedComponentDids?.length) {
1690
- return selectedComponentDids.includes(x.meta.did);
1738
+ if (componentDids?.length) {
1739
+ return componentDids.includes(x.meta.did);
1691
1740
  }
1692
1741
  return x;
1693
1742
  }),
@@ -1758,12 +1807,12 @@ class BlockletManager extends BaseBlockletManager {
1758
1807
  }
1759
1808
 
1760
1809
  if (postAction === 'install') {
1761
- const state = await states.blocklet.setBlockletStatus(did, BlockletStatus.installing);
1810
+ const state = await states.blocklet.setBlockletStatus(did, BlockletStatus.installing, { componentDids });
1762
1811
  this.emit(BlockletEvents.statusChange, state);
1763
1812
  }
1764
1813
 
1765
1814
  if (postAction === 'upgrade') {
1766
- const state = await states.blocklet.setBlockletStatus(did, BlockletStatus.upgrading);
1815
+ const state = await states.blocklet.setBlockletStatus(did, BlockletStatus.upgrading, { componentDids });
1767
1816
  this.emit(BlockletEvents.statusChange, state);
1768
1817
  }
1769
1818
 
@@ -1777,13 +1826,13 @@ class BlockletManager extends BaseBlockletManager {
1777
1826
  try {
1778
1827
  // install blocklet
1779
1828
  if (postAction === 'install') {
1780
- await this._onInstall({ blocklet, context, oldBlocklet });
1829
+ await this._onInstall({ blocklet, componentDids, context, oldBlocklet });
1781
1830
  return;
1782
1831
  }
1783
1832
 
1784
1833
  // upgrade blocklet
1785
1834
  if (postAction === 'upgrade') {
1786
- await this._onUpgrade({ oldBlocklet, newBlocklet: blocklet, context });
1835
+ await this._onUpgrade({ oldBlocklet, componentDids, newBlocklet: blocklet, context });
1787
1836
  }
1788
1837
  } catch (error) {
1789
1838
  if (throwOnError) {
@@ -1792,7 +1841,7 @@ class BlockletManager extends BaseBlockletManager {
1792
1841
  }
1793
1842
  }
1794
1843
 
1795
- async _onInstall({ blocklet, context, oldBlocklet }) {
1844
+ async _onInstall({ blocklet, componentDids, context, oldBlocklet }) {
1796
1845
  const { meta } = blocklet;
1797
1846
  const { did, version } = meta;
1798
1847
  logger.info('do install blocklet', { did, version });
@@ -1800,6 +1849,7 @@ class BlockletManager extends BaseBlockletManager {
1800
1849
  try {
1801
1850
  const installedBlocklet = await this._installBlocklet({
1802
1851
  did,
1852
+ componentDids,
1803
1853
  context,
1804
1854
  oldBlocklet,
1805
1855
  });
@@ -1807,7 +1857,7 @@ class BlockletManager extends BaseBlockletManager {
1807
1857
  if (context.startImmediately && installedBlocklet?.settings.initialized) {
1808
1858
  try {
1809
1859
  logger.info('start blocklet after installed', { did });
1810
- await this.start({ did, checkHealthImmediately: true });
1860
+ await this.start({ did, checkHealthImmediately: true, componentDids });
1811
1861
  } catch (error) {
1812
1862
  logger.warn('attempt to start immediately failed', { did, error });
1813
1863
  }
@@ -1820,7 +1870,7 @@ class BlockletManager extends BaseBlockletManager {
1820
1870
  }
1821
1871
  }
1822
1872
 
1823
- async _onUpgrade({ oldBlocklet, newBlocklet, context }) {
1873
+ async _onUpgrade({ oldBlocklet, newBlocklet, componentDids, context }) {
1824
1874
  const { version, did } = newBlocklet.meta;
1825
1875
  logger.info('do upgrade blocklet', { did, version });
1826
1876
 
@@ -1828,6 +1878,7 @@ class BlockletManager extends BaseBlockletManager {
1828
1878
  await this._upgradeBlocklet({
1829
1879
  newBlocklet,
1830
1880
  oldBlocklet,
1881
+ componentDids,
1831
1882
  context,
1832
1883
  });
1833
1884
  } catch (err) {
@@ -1835,13 +1886,13 @@ class BlockletManager extends BaseBlockletManager {
1835
1886
  }
1836
1887
  }
1837
1888
 
1838
- async _onRestart({ did, context }) {
1839
- await this.stop({ did, updateStatus: false }, context);
1840
- await this.start({ did }, context);
1889
+ async _onRestart({ did, componentDids, context }) {
1890
+ await this.stop({ did, componentDids, updateStatus: false }, context);
1891
+ await this.start({ did, componentDids }, context);
1841
1892
  }
1842
1893
 
1843
1894
  async _onCheckIfStarted(jobInfo, { throwOnError } = {}) {
1844
- const { did, context, minConsecutiveTime = 5000, timeout } = jobInfo;
1895
+ const { did, context, minConsecutiveTime = 5000, timeout, componentDids } = jobInfo;
1845
1896
  const blocklet = await this.getBlocklet(did);
1846
1897
 
1847
1898
  const { meta } = blocklet;
@@ -1849,10 +1900,18 @@ class BlockletManager extends BaseBlockletManager {
1849
1900
 
1850
1901
  try {
1851
1902
  // healthy check
1852
- await checkBlockletProcessHealthy(blocklet, { minConsecutiveTime, timeout });
1903
+ await checkBlockletProcessHealthy(blocklet, { minConsecutiveTime, timeout, componentDids });
1853
1904
 
1854
1905
  // update blocklet status after healthy check
1855
- const res = await this.status(did, { forceSync: true });
1906
+ await states.blocklet.setBlockletStatus(did, BlockletStatus.running, { componentDids });
1907
+
1908
+ const res = await this.getBlocklet(did);
1909
+
1910
+ this.emit(BlockletInternalEvents.componentsUpdated, {
1911
+ appDid: blocklet.appDid,
1912
+ components: getComponentsInternalInfo(res),
1913
+ });
1914
+
1856
1915
  this.emit(BlockletEvents.started, res);
1857
1916
  } catch (error) {
1858
1917
  const status = await states.blocklet.getBlockletStatus(did);
@@ -1864,7 +1923,7 @@ class BlockletManager extends BaseBlockletManager {
1864
1923
  logger.error('check blocklet if started failed', { did, name, context, timeout, error });
1865
1924
 
1866
1925
  await this.deleteProcess({ did }, context);
1867
- await states.blocklet.setBlockletStatus(did, BlockletStatus.error);
1926
+ await states.blocklet.setBlockletStatus(did, BlockletStatus.error, { componentDids });
1868
1927
 
1869
1928
  this._createNotification(did, {
1870
1929
  title: 'Blocklet Start Failed',
@@ -2256,7 +2315,7 @@ class BlockletManager extends BaseBlockletManager {
2256
2315
  * @param {string} opt.did
2257
2316
  * @param {object} opt.context
2258
2317
  */
2259
- async _installBlocklet({ did, oldBlocklet, context, createNotification = true }) {
2318
+ async _installBlocklet({ did, oldBlocklet, componentDids, context, createNotification = true }) {
2260
2319
  try {
2261
2320
  // should ensure blocklet integrity
2262
2321
  let blocklet = await this.ensureBlocklet(did);
@@ -2280,7 +2339,9 @@ class BlockletManager extends BaseBlockletManager {
2280
2339
  // post install
2281
2340
  await this._runPostInstallHook(blocklet, context);
2282
2341
 
2283
- await states.blocklet.setBlockletStatus(did, BlockletStatus.installed);
2342
+ await states.blocklet.setInstalledAt(did);
2343
+
2344
+ await states.blocklet.setBlockletStatus(did, BlockletStatus.installed, { componentDids });
2284
2345
  blocklet = await this.getBlocklet(did);
2285
2346
  logger.info('blocklet installed', { source, did: meta.did });
2286
2347
 
@@ -2369,7 +2430,7 @@ class BlockletManager extends BaseBlockletManager {
2369
2430
  }
2370
2431
  }
2371
2432
 
2372
- async _upgradeBlocklet({ newBlocklet, oldBlocklet, context = {} }) {
2433
+ async _upgradeBlocklet({ newBlocklet, oldBlocklet, componentDids, context = {} }) {
2373
2434
  const { meta, source, deployedFrom, children } = newBlocklet;
2374
2435
  const { did, version, name, title } = meta;
2375
2436
 
@@ -2434,11 +2495,11 @@ class BlockletManager extends BaseBlockletManager {
2434
2495
 
2435
2496
  const status =
2436
2497
  oldBlocklet.status === BlockletStatus.installed ? BlockletStatus.installed : BlockletStatus.stopped;
2437
- await states.blocklet.setBlockletStatus(did, status, { children: 'all' });
2498
+ await states.blocklet.setBlockletStatus(did, status, { componentDids });
2438
2499
 
2439
2500
  // start new process
2440
2501
  if (oldBlocklet.status === BlockletStatus.running) {
2441
- await this.start({ did }, context);
2502
+ await this.start({ did, componentDids }, context);
2442
2503
  logger.info('started blocklet for upgrading', { did, version });
2443
2504
  }
2444
2505
 
@@ -2469,6 +2530,11 @@ class BlockletManager extends BaseBlockletManager {
2469
2530
 
2470
2531
  await this._rollbackCache.remove({ did: blocklet.meta.did });
2471
2532
 
2533
+ this.emit(BlockletInternalEvents.componentsUpdated, {
2534
+ appDid: blocklet.appDid,
2535
+ components: getComponentsInternalInfo(blocklet),
2536
+ });
2537
+
2472
2538
  return blocklet;
2473
2539
  } catch (err) {
2474
2540
  const b = await this._rollback('upgrade', did, oldBlocklet);
@@ -2525,10 +2591,12 @@ class BlockletManager extends BaseBlockletManager {
2525
2591
  ...context,
2526
2592
  preDownload: async ({ downloadComponentIds }) => {
2527
2593
  // update children status
2528
- const blocklet1 = await states.blocklet.setBlockletStatus(did, BlockletStatus.downloading, {
2529
- children: downloadComponentIds,
2530
- });
2531
- this.emit(BlockletEvents.statusChange, blocklet1);
2594
+ if (downloadComponentIds?.length) {
2595
+ const blocklet1 = await states.blocklet.setBlockletStatus(did, BlockletStatus.downloading, {
2596
+ componentDids: downloadComponentIds,
2597
+ });
2598
+ this.emit(BlockletEvents.statusChange, blocklet1);
2599
+ }
2532
2600
  },
2533
2601
  onProgress: async (data) => {
2534
2602
  this.emit(BlockletEvents.downloadBundleProgress, { appDid: appDid || did, meta: { did }, ...data });
@@ -2542,16 +2610,17 @@ class BlockletManager extends BaseBlockletManager {
2542
2610
  });
2543
2611
  }
2544
2612
 
2545
- async _syncPm2Status(pm2Status, did) {
2613
+ async _syncPm2Status(pm2Status, did, componentDid) {
2546
2614
  try {
2547
- const state = await states.blocklet.getBlocklet(did);
2548
- if (state && util.shouldUpdateBlockletStatus(state.status)) {
2615
+ const blocklet = await states.blocklet.getBlocklet(did);
2616
+ const component = findComponentByIdV2(blocklet, componentDid);
2617
+ if (component && util.shouldUpdateBlockletStatus(component.status)) {
2549
2618
  const newStatus = pm2StatusMap[pm2Status];
2550
- await states.blocklet.setBlockletStatus(did, newStatus);
2551
- logger.info('sync pm2 status to blocklet', { did, pm2Status, newStatus });
2619
+ await states.blocklet.setBlockletStatus(did, newStatus, { componentDids: [componentDid] });
2620
+ logger.info('sync pm2 status to blocklet', { did, componentDid, pm2Status, newStatus });
2552
2621
  }
2553
2622
  } catch (error) {
2554
- logger.error('sync pm2 status to blocklet failed', { did, pm2Status, error });
2623
+ logger.error('sync pm2 status to blocklet failed', { did, componentDid, pm2Status, error });
2555
2624
  }
2556
2625
  }
2557
2626