@abtnode/core 1.17.3-beta-20251120-052956-035abea6 → 1.17.3-beta-20251123-232619-53258789

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.
@@ -259,13 +259,13 @@ const { formatEnvironments, getBlockletMeta, validateOwner, isCLI } = util;
259
259
 
260
260
  const statusLock = new DBCache(() => ({
261
261
  prefix: 'blocklet-status-lock',
262
- ttl: 1000 * 60,
262
+ ttl: 120_000,
263
263
  ...getAbtNodeRedisAndSQLiteUrl(),
264
264
  }));
265
265
 
266
266
  const startLock = new DBCache(() => ({
267
267
  prefix: 'blocklet-start-lock',
268
- ttl: process.env.NODE_ENV === 'test' ? 100 : 1000 * 60,
268
+ ttl: process.env.NODE_ENV === 'test' ? 1_000 : 120_000,
269
269
  ...getAbtNodeRedisAndSQLiteUrl(),
270
270
  }));
271
271
 
@@ -740,6 +740,8 @@ class DiskBlockletManager extends BaseBlockletManager {
740
740
  e2eMode,
741
741
  context,
742
742
  atomic,
743
+ onStarted,
744
+ onError,
743
745
  }) {
744
746
  if (!blocklet.children) {
745
747
  return componentDids;
@@ -771,11 +773,17 @@ class DiskBlockletManager extends BaseBlockletManager {
771
773
  // start by dependency
772
774
  for (const dids of requiredDidsLayers) {
773
775
  if (atomic) {
774
- await this._start({ blocklet, throwOnError, checkHealthImmediately, e2eMode, componentDids: dids }, context);
776
+ await this._start(
777
+ { blocklet, throwOnError, checkHealthImmediately, e2eMode, componentDids: dids, onStarted, onError },
778
+ context
779
+ );
775
780
  } else {
776
781
  const tasks = dids.map(
777
782
  (x) => () =>
778
- this._start({ blocklet, throwOnError, checkHealthImmediately, e2eMode, componentDids: [x] }, context)
783
+ this._start(
784
+ { blocklet, throwOnError, checkHealthImmediately, e2eMode, componentDids: [x], onStarted, onError },
785
+ context
786
+ )
779
787
  );
780
788
  await pAll(tasks, { concurrency: 4 }).catch((err) => {
781
789
  throw new Error(err.errors ? err.errors.join(', ') : err);
@@ -801,8 +809,8 @@ class DiskBlockletManager extends BaseBlockletManager {
801
809
  },
802
810
  context
803
811
  ) {
804
- const lockName = `start-not-input-component-dids-${did}`;
805
- const shouldLock = !inputComponentDids?.length;
812
+ const lockName = `${did}-start`;
813
+ const shouldLock = inputComponentDids?.length === 0;
806
814
 
807
815
  if (shouldLock) {
808
816
  await startLock.acquire(lockName);
@@ -814,8 +822,16 @@ class DiskBlockletManager extends BaseBlockletManager {
814
822
  inputComponentDids?.length ? inputComponentDids : blocklet.children.map((x) => x.meta.did)
815
823
  );
816
824
 
825
+ try {
826
+ await this.deleteProcess({ did, componentDids: baseComponentDids, isGreen: true });
827
+ } catch (error) {
828
+ logger.warn('Failed to delete process; this warning can be safely ignored.', { error });
829
+ }
830
+
831
+ await this.checkControllerStatus(blocklet, 'start');
832
+
817
833
  // 优先启动资源型组件
818
- let componentDids = [];
834
+ const componentDids = [];
819
835
  const nonEntryComponentIds = [];
820
836
  for (const b of blocklet.children) {
821
837
  if (!b?.meta?.did) {
@@ -844,7 +860,6 @@ class DiskBlockletManager extends BaseBlockletManager {
844
860
  operator,
845
861
  });
846
862
  }
847
-
848
863
  // sync component config before at first to ensure resource component config is ready
849
864
  const serverSk = (await states.node.read()).sk;
850
865
  await Promise.all(
@@ -853,7 +868,16 @@ class DiskBlockletManager extends BaseBlockletManager {
853
868
  )
854
869
  );
855
870
 
856
- componentDids = await this.startRequiredComponents({
871
+ const doc1 = await states.blocklet.setBlockletStatus(did, BlockletStatus.starting, {
872
+ componentDids,
873
+ operator,
874
+ });
875
+
876
+ this.emit(BlockletEvents.statusChange, doc1);
877
+ const startedBlockletDids = [];
878
+ const errorBlockletDids = [];
879
+
880
+ const notStartedComponentDids = await this.startRequiredComponents({
857
881
  componentDids,
858
882
  inputComponentDids,
859
883
  blocklet,
@@ -862,26 +886,15 @@ class DiskBlockletManager extends BaseBlockletManager {
862
886
  e2eMode,
863
887
  context,
864
888
  atomic,
889
+ onStarted: (subDid) => {
890
+ startedBlockletDids.push({ did: subDid });
891
+ },
892
+ onError: (subDid, error) => {
893
+ errorBlockletDids.push({ did: subDid, error });
894
+ },
865
895
  });
866
896
 
867
- if (atomic || !blocklet.structVersion) {
868
- const nextBlocklet = await this._start(
869
- { blocklet, throwOnError, checkHealthImmediately, e2eMode, componentDids, operator },
870
- context
871
- );
872
-
873
- // 根据情况更新 route table, 会判断只有包含多 interfaces 的 DID 才会更新 route table
874
- if (!['true', '1'].includes(process.env.ABT_NODE_DISABLE_BLUE_GREEN)) {
875
- this.emit(BlockletEvents.blurOrGreenStarted, {
876
- blocklet: nextBlocklet,
877
- componentDids: inputComponentDids,
878
- context,
879
- });
880
- }
881
- return nextBlocklet;
882
- }
883
-
884
- const tasks = componentDids.map(
897
+ const tasks = notStartedComponentDids.map(
885
898
  (componentDid) => () =>
886
899
  this._start(
887
900
  {
@@ -891,25 +904,104 @@ class DiskBlockletManager extends BaseBlockletManager {
891
904
  e2eMode,
892
905
  componentDids: [componentDid],
893
906
  operator,
907
+ onStarted: (subDid) => {
908
+ startedBlockletDids.push({ did: subDid });
909
+ },
910
+ onError: (subDid, error) => {
911
+ errorBlockletDids.push({ did: subDid, error });
912
+ },
894
913
  },
895
914
  context
896
915
  )
897
916
  );
898
917
 
899
- const rest = await pAll(tasks, { concurrency: 1 });
918
+ await pAll(tasks, { concurrency: 6 });
900
919
 
901
920
  const nextBlocklet = await this.ensureBlocklet(did, { e2eMode });
921
+ let errorDescription = '';
922
+ let resultBlocklet = nextBlocklet;
923
+
924
+ if (startedBlockletDids.length) {
925
+ await states.blocklet.setBlockletStatus(did, BlockletStatus.running, {
926
+ componentDids: startedBlockletDids.map((x) => x.did),
927
+ operator,
928
+ });
929
+
930
+ const finalBlocklet = await this.getBlocklet(did);
931
+ resultBlocklet = finalBlocklet;
932
+
933
+ await this.configSynchronizer.throttledSyncAppConfig(finalBlocklet);
934
+ const componentsInfo = getComponentsInternalInfo(finalBlocklet);
935
+ this.emit(BlockletInternalEvents.componentUpdated, {
936
+ appDid: blocklet.appDid,
937
+ components: componentsInfo,
938
+ });
939
+ this.emit(BlockletInternalEvents.componentStarted, {
940
+ appDid: blocklet.appDid,
941
+ components: (componentDids || []).map((x) => ({ did: x })),
942
+ });
943
+
944
+ this.emit(BlockletEvents.statusChange, finalBlocklet);
945
+ this.emit(BlockletEvents.started, { ...finalBlocklet, componentDids });
946
+
947
+ launcher.notifyBlockletStarted(finalBlocklet);
948
+ }
949
+
950
+ if (errorBlockletDids.length) {
951
+ const error = errorBlockletDids[0];
952
+ for (const item of errorBlockletDids) {
953
+ logger.error('Failed to start blocklet', {
954
+ error: item.error,
955
+ title: nextBlocklet.meta.title,
956
+ name: getComponentNamesWithVersion(nextBlocklet, [item.did]),
957
+ });
958
+ }
959
+
960
+ errorDescription = `${getComponentNamesWithVersion(
961
+ nextBlocklet,
962
+ errorBlockletDids.map((x) => x.did)
963
+ )} start failed for ${getDisplayName(nextBlocklet)}: ${errorBlockletDids.map((x) => x.error.message).join('. ')}`;
964
+ this._createNotification(did, {
965
+ title: 'Component start failed',
966
+ description: errorDescription,
967
+ entityType: 'blocklet',
968
+ entityId: did,
969
+ severity: 'error',
970
+ });
971
+
972
+ await this.deleteProcess({
973
+ did,
974
+ componentDids: errorBlockletDids.map((x) => x.did),
975
+ shouldUpdateBlockletStatus: false,
976
+ });
977
+ await states.blocklet.setBlockletStatus(did, BlockletStatus.error, {
978
+ componentDids: errorBlockletDids.map((x) => x.did),
979
+ operator,
980
+ });
981
+ const finalBlocklet = await this.getBlocklet(did);
982
+ resultBlocklet = finalBlocklet;
983
+ this.emit(BlockletEvents.startFailed, {
984
+ ...finalBlocklet,
985
+ componentDids: errorBlockletDids.map((x) => x.did),
986
+ error: { message: error.message },
987
+ });
988
+ this.emit(BlockletEvents.statusChange, { ...finalBlocklet, error: { message: error.message } });
989
+ }
902
990
 
903
991
  // 根据情况更新 route table, 会判断只有包含多 interfaces 的 DID 才会更新 route table
904
992
  if (!['true', '1'].includes(process.env.ABT_NODE_DISABLE_BLUE_GREEN)) {
905
993
  this.emit(BlockletEvents.blurOrGreenStarted, {
906
- blocklet: nextBlocklet,
994
+ blocklet: resultBlocklet,
907
995
  componentDids: inputComponentDids,
908
996
  context,
909
997
  });
910
998
  }
911
999
 
912
- return rest[0];
1000
+ if (throwOnError && errorDescription) {
1001
+ throw new Error(errorDescription);
1002
+ }
1003
+
1004
+ return resultBlocklet;
913
1005
  } finally {
914
1006
  if (shouldLock) {
915
1007
  await startLock.releaseLock(lockName);
@@ -926,17 +1018,13 @@ class DiskBlockletManager extends BaseBlockletManager {
926
1018
  e2eMode = false,
927
1019
  componentDids,
928
1020
  operator: _operator,
1021
+ onStarted,
1022
+ onError,
929
1023
  },
930
1024
  context
931
1025
  ) {
932
1026
  const operator = _operator || context?.user?.did;
933
1027
 
934
- try {
935
- await this.deleteProcess({ did, componentDids, isGreen: true });
936
- } catch {
937
- // do nothing
938
- }
939
-
940
1028
  logger.info('start blocklet', {
941
1029
  did: did || inputBlocklet.meta.did,
942
1030
  componentDids,
@@ -960,7 +1048,6 @@ class DiskBlockletManager extends BaseBlockletManager {
960
1048
 
961
1049
  const entryComponentIds = [];
962
1050
  const nonEntryComponentIds = [];
963
- let nonEntryComponentRes;
964
1051
  const componentDidsSet = new Set(componentDids);
965
1052
  try {
966
1053
  await forEachBlocklet(
@@ -996,18 +1083,9 @@ class DiskBlockletManager extends BaseBlockletManager {
996
1083
  { parallel: true, concurrencyLimit: 4 }
997
1084
  );
998
1085
  if (nonEntryComponentIds.length) {
999
- const params = {
1000
- did,
1001
- context,
1002
- minConsecutiveTime: 3000,
1003
- timeout: 5000,
1004
- componentDids: nonEntryComponentIds,
1005
- };
1006
- nonEntryComponentRes = await this._onCheckIfStarted(params, {
1007
- throwOnError,
1008
- skipRunningCheck: true,
1009
- needUpdateBlueStatus: false,
1010
- });
1086
+ for (const subDid of nonEntryComponentIds) {
1087
+ onStarted?.(subDid);
1088
+ }
1011
1089
  }
1012
1090
  } catch (err) {
1013
1091
  logger.error('Failed to categorize components into entry and non-entry types', { error: err.message });
@@ -1015,7 +1093,7 @@ class DiskBlockletManager extends BaseBlockletManager {
1015
1093
  }
1016
1094
 
1017
1095
  if (!entryComponentIds.length) {
1018
- return nonEntryComponentRes;
1096
+ return;
1019
1097
  }
1020
1098
 
1021
1099
  try {
@@ -1036,13 +1114,7 @@ class DiskBlockletManager extends BaseBlockletManager {
1036
1114
  }
1037
1115
  }
1038
1116
 
1039
- const doc1 = await states.blocklet.setBlockletStatus(did, BlockletStatus.starting, {
1040
- componentDids: entryComponentIds,
1041
- operator,
1042
- });
1043
-
1044
1117
  blocklet1.status = BlockletStatus.starting;
1045
- this.emit(BlockletEvents.statusChange, doc1);
1046
1118
  const blocklet = await ensureAppPortsNotOccupied({
1047
1119
  blocklet: blocklet1,
1048
1120
  componentDids: entryComponentIds,
@@ -1097,8 +1169,6 @@ class DiskBlockletManager extends BaseBlockletManager {
1097
1169
  });
1098
1170
  };
1099
1171
 
1100
- await this.configSynchronizer.syncAppConfig(blocklet);
1101
-
1102
1172
  await startBlockletProcess(blocklet, {
1103
1173
  ...context,
1104
1174
  preFlight: getHookFn('preFlight'),
@@ -1116,6 +1186,7 @@ class DiskBlockletManager extends BaseBlockletManager {
1116
1186
  checkHealthImmediately,
1117
1187
  componentDids,
1118
1188
  });
1189
+
1119
1190
  const params = {
1120
1191
  did,
1121
1192
  context,
@@ -1124,47 +1195,19 @@ class DiskBlockletManager extends BaseBlockletManager {
1124
1195
  componentDids: entryComponentIds,
1125
1196
  };
1126
1197
 
1127
- await this._onCheckIfStarted(params, { throwOnError, needUpdateBlueStatus: false });
1128
- blocklet.status = BlockletStatus.running;
1198
+ await this._onCheckIfStarted(params, { throwOnError });
1129
1199
 
1130
- return blocklet;
1200
+ for (const subDid of entryComponentIds) {
1201
+ onStarted?.(subDid);
1202
+ }
1131
1203
  } catch (err) {
1132
1204
  const status = await states.blocklet.getBlockletStatus(did);
1133
1205
  if ([BlockletStatus.stopping, BlockletStatus.stopped].includes(status)) {
1134
1206
  logger.info('Failed to start blocklet maybe due to manually stopped');
1135
- return states.blocklet.getBlocklet(did);
1136
1207
  }
1137
-
1138
- const error = Array.isArray(err) ? err[0] : err;
1139
- logger.error('Failed to start blocklet', { error, did, title: blocklet1.meta.title });
1140
- const description = `${getComponentNamesWithVersion(blocklet1, entryComponentIds)} start failed for ${getDisplayName(
1141
- blocklet1
1142
- )}: ${error.message}`;
1143
- this._createNotification(did, {
1144
- title: 'Component start failed',
1145
- description,
1146
- entityType: 'blocklet',
1147
- entityId: did,
1148
- severity: 'error',
1149
- });
1150
-
1151
- await this.deleteProcess({ did, componentDids: entryComponentIds });
1152
- const res = await states.blocklet.setBlockletStatus(did, BlockletStatus.error, {
1153
- componentDids: entryComponentIds,
1154
- operator,
1155
- });
1156
- this.emit(BlockletEvents.startFailed, {
1157
- ...res,
1158
- componentDids: entryComponentIds,
1159
- error: { message: error.message },
1160
- });
1161
- this.emit(BlockletEvents.statusChange, { ...res, error: { message: error.message } });
1162
-
1163
- if (throwOnError) {
1164
- throw new Error(description);
1208
+ for (const subDid of entryComponentIds) {
1209
+ onError?.(subDid, err);
1165
1210
  }
1166
-
1167
- return res;
1168
1211
  }
1169
1212
  }
1170
1213
 
@@ -1471,13 +1514,19 @@ class DiskBlockletManager extends BaseBlockletManager {
1471
1514
  });
1472
1515
 
1473
1516
  const doc = await this._deleteBlocklet({ did, keepData, keepLogsDir, keepConfigs }, context);
1474
- this._createNotification(doc.meta.did, {
1475
- title: 'Blocklet Deleted',
1476
- description: `Blocklet ${getDisplayName(blocklet)} is deleted.`,
1477
- entityType: 'blocklet',
1478
- entityId: doc.meta.did,
1479
- severity: 'success',
1480
- });
1517
+ this._createNotification(
1518
+ doc.meta.did,
1519
+ {
1520
+ title: 'Blocklet Deleted',
1521
+ description: `Blocklet ${getDisplayName(blocklet)} is deleted.`,
1522
+ entityType: 'blocklet',
1523
+ entityId: doc.meta.did,
1524
+ severity: 'success',
1525
+ },
1526
+ {
1527
+ skipGetBlocklet: true,
1528
+ }
1529
+ );
1481
1530
  await removeDockerNetwork(parseDockerName(did, 'docker-network'));
1482
1531
  return doc;
1483
1532
  } catch (error) {
@@ -1486,13 +1535,19 @@ class DiskBlockletManager extends BaseBlockletManager {
1486
1535
  const doc = await this._deleteBlocklet({ did, keepData, keepLogsDir, keepConfigs }, context);
1487
1536
  await removeDockerNetwork(parseDockerName(did, 'docker-network'));
1488
1537
 
1489
- this._createNotification(doc.meta.did, {
1490
- title: 'Blocklet Deleted',
1491
- description: `Blocklet ${getDisplayName(blocklet)} is deleted.`,
1492
- entityType: 'blocklet',
1493
- entityId: doc.meta.did,
1494
- severity: 'success',
1495
- });
1538
+ this._createNotification(
1539
+ doc.meta.did,
1540
+ {
1541
+ title: 'Blocklet Deleted',
1542
+ description: `Blocklet ${getDisplayName(blocklet)} is deleted.`,
1543
+ entityType: 'blocklet',
1544
+ entityId: doc.meta.did,
1545
+ severity: 'success',
1546
+ },
1547
+ {
1548
+ skipGetBlocklet: true,
1549
+ }
1550
+ );
1496
1551
 
1497
1552
  return doc;
1498
1553
  }
@@ -3590,141 +3645,24 @@ class DiskBlockletManager extends BaseBlockletManager {
3590
3645
  await blueGreenStartBlocklet({ did, componentDids, operator }, context, this, states);
3591
3646
  }
3592
3647
 
3593
- _onCheckIfStarted = async (
3594
- jobInfo,
3595
- { throwOnError, skipRunningCheck = false, isGreen = false, needUpdateBlueStatus = true } = {}
3596
- ) => {
3597
- const startedAt = Date.now();
3598
- const { did, context, minConsecutiveTime = 2000, timeout, componentDids } = jobInfo;
3599
- const nodeInfo = await states.node.read();
3648
+ _onCheckIfStarted = async (jobInfo, { skipRunningCheck = false, isGreen = false } = {}) => {
3649
+ const { did, minConsecutiveTime = 2000, timeout, componentDids } = jobInfo;
3600
3650
  const blocklet = await this.getBlocklet(did);
3601
3651
 
3602
- const { meta } = blocklet;
3603
- const { name } = meta;
3604
-
3605
- const successBlockletIds = new Set();
3606
-
3607
- try {
3608
- if (!skipRunningCheck) {
3609
- await checkBlockletProcessHealthy(blocklet, {
3610
- minConsecutiveTime,
3611
- timeout,
3612
- componentDids,
3613
- isGreen,
3614
- appDid: did,
3615
- enableDocker: nodeInfo.enableDocker,
3616
- getBlocklet: () => {
3617
- return this.getBlocklet(did);
3618
- },
3619
- setBlockletRunning: async (componentDid) => {
3620
- successBlockletIds.add(componentDid);
3621
- await states.blocklet.setBlockletStatus(did, BlockletStatus.running, {
3622
- componentDids: [componentDid],
3623
- isGreen,
3624
- });
3625
- },
3626
- });
3627
- }
3652
+ const nodeInfo = await states.node.read();
3628
3653
 
3629
- const runningRes = await states.blocklet.setBlockletStatus(did, BlockletStatus.running, {
3630
- componentDids: successBlockletIds.size > 0 ? Array.from(successBlockletIds) : componentDids,
3654
+ if (!skipRunningCheck) {
3655
+ await checkBlockletProcessHealthy(blocklet, {
3656
+ minConsecutiveTime,
3657
+ timeout,
3658
+ componentDids,
3631
3659
  isGreen,
3660
+ appDid: did,
3661
+ enableDocker: nodeInfo.enableDocker,
3662
+ getBlocklet: () => {
3663
+ return this.getBlocklet(did);
3664
+ },
3632
3665
  });
3633
-
3634
- if (needUpdateBlueStatus) {
3635
- await states.blocklet.setBlockletStatus(did, BlockletStatus.stopped, {
3636
- componentDids,
3637
- isGreen: !isGreen,
3638
- });
3639
- }
3640
-
3641
- const nextBlocklet = await this.getBlocklet(did);
3642
-
3643
- await this.configSynchronizer.throttledSyncAppConfig(nextBlocklet);
3644
- const componentsInfo = getComponentsInternalInfo(nextBlocklet);
3645
- this.emit(BlockletInternalEvents.componentUpdated, {
3646
- appDid: blocklet.appDid,
3647
- components: componentsInfo,
3648
- });
3649
- this.emit(BlockletInternalEvents.componentStarted, {
3650
- appDid: blocklet.appDid,
3651
- components: (componentDids || []).map((x) => ({ did: x })),
3652
- });
3653
-
3654
- this.emit(BlockletEvents.statusChange, nextBlocklet);
3655
- this.emit(BlockletEvents.started, { ...nextBlocklet, componentDids });
3656
-
3657
- launcher.notifyBlockletStarted(blocklet);
3658
-
3659
- logger.info('blocklet healthy', { did, name, time: Date.now() - startedAt });
3660
-
3661
- if (needUpdateBlueStatus) {
3662
- try {
3663
- await this.deleteProcess({ did, componentDids, isGreen: !isGreen }, context);
3664
- } catch {
3665
- logger.error('delete process failed', { did, componentDids, isGreen });
3666
- }
3667
- }
3668
-
3669
- return runningRes;
3670
- } catch (error) {
3671
- const errorBlockletIds = [];
3672
- for (const componentDid of componentDids) {
3673
- if (!successBlockletIds.has(componentDid)) {
3674
- errorBlockletIds.push(componentDid);
3675
- }
3676
- }
3677
- if (errorBlockletIds.length === 0) {
3678
- return this.getBlocklet(did);
3679
- }
3680
-
3681
- const status = await states.blocklet.getBlockletStatus(did);
3682
- if ([BlockletStatus.stopping, BlockletStatus.stopped].includes(status)) {
3683
- logger.info(`Check blocklet healthy failing because blocklet is ${fromBlockletStatus(status)}`);
3684
- return {};
3685
- }
3686
-
3687
- logger.error('check blocklet if started failed', { did, name, context, timeout, error });
3688
-
3689
- await this.deleteProcess({ did, componentDids: errorBlockletIds, isGreen }, context);
3690
-
3691
- let doc;
3692
- if (isGreen) {
3693
- doc = await states.blocklet.setBlockletStatus(did, BlockletStatus.stopped, {
3694
- componentDids: errorBlockletIds,
3695
- isGreen,
3696
- });
3697
- } else {
3698
- doc = await states.blocklet.setBlockletStatus(did, BlockletStatus.error, { componentDids: errorBlockletIds });
3699
- }
3700
-
3701
- const componentNames = getComponentNamesWithVersion(blocklet, errorBlockletIds);
3702
- const description = componentNames
3703
- ? `${getComponentNamesWithVersion(blocklet, errorBlockletIds)} start failed for ${getDisplayName(blocklet)}: ${
3704
- error.message
3705
- }`
3706
- : `${blocklet.meta.title} start failed: ${error.message}`;
3707
-
3708
- this._createNotification(did, {
3709
- title: 'Component start failed',
3710
- description,
3711
- entityType: 'blocklet',
3712
- entityId: did,
3713
- severity: 'error',
3714
- });
3715
-
3716
- this.emit(BlockletEvents.startFailed, {
3717
- ...doc,
3718
- componentDids: errorBlockletIds,
3719
- error: { message: error.message },
3720
- });
3721
- this.emit(BlockletEvents.statusChange, { ...doc, error });
3722
-
3723
- if (throwOnError) {
3724
- throw error;
3725
- }
3726
-
3727
- return doc;
3728
3666
  }
3729
3667
  };
3730
3668
 
@@ -5185,7 +5123,7 @@ class DiskBlockletManager extends BaseBlockletManager {
5185
5123
  }
5186
5124
 
5187
5125
  // 目前:Blocklet 的安装消息都会聚合在这里。
5188
- async _createNotification(did, notification) {
5126
+ async _createNotification(did, notification, { skipGetBlocklet = false } = {}) {
5189
5127
  if (isCLI()) {
5190
5128
  return undefined;
5191
5129
  }
@@ -5194,7 +5132,7 @@ class DiskBlockletManager extends BaseBlockletManager {
5194
5132
  let blockletUrl;
5195
5133
  let blocklet;
5196
5134
  try {
5197
- blocklet = await this.getBlocklet(did);
5135
+ blocklet = skipGetBlocklet ? null : await this.getBlocklet(did);
5198
5136
  if (blocklet) {
5199
5137
  const urls = blocklet.site?.domainAliases || [];
5200
5138
  const customUrl = urls.find((x) => !x.isProtected)?.value;