@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.
@@ -56,7 +56,6 @@ const installComponentFromDev = async ({ folder, meta, rootDid, mountPoint, mana
56
56
  const newBlocklet = await states.blocklet.getBlocklet(rootDid);
57
57
  await validateBlocklet(newBlocklet);
58
58
  await manager._downloadBlocklet(newBlocklet);
59
- await states.blocklet.setBlockletStatus(rootDid, BlockletStatus.stopped);
60
59
 
61
60
  // Add Config
62
61
  await manager._setConfigsFromMeta(rootDid);
@@ -13,6 +13,7 @@ const {
13
13
  ensureMeta,
14
14
  checkStructVersion,
15
15
  checkVersionCompatibility,
16
+ getBlockletStatus,
16
17
  } = require('../../../util/blocklet');
17
18
  const { resolveDownload, resolveDiffDownload, downloadFromUpload } = require('../../downloader/resolve-download');
18
19
 
@@ -39,9 +40,10 @@ const installComponentFromUpload = async ({
39
40
  // download
40
41
  const { tarFile } = await downloadFromUpload(file, { downloadDir: path.join(manager.dataDirs.tmp, 'download') });
41
42
 
42
- if (isInProgress(oldBlocklet.status)) {
43
- logger.error(`Can not deploy blocklet when it is ${fromBlockletStatus(oldBlocklet.status)}`);
44
- throw new Error(`Can not deploy blocklet when it is ${fromBlockletStatus(oldBlocklet.status)}`);
43
+ const appStatus = getBlockletStatus(oldBlocklet);
44
+ if (isInProgress(appStatus)) {
45
+ logger.error(`Can not deploy blocklet when it is ${fromBlockletStatus(appStatus)}`);
46
+ throw new Error(`Can not deploy blocklet when it is ${fromBlockletStatus(appStatus)}`);
45
47
  }
46
48
 
47
49
  let meta;
@@ -105,6 +107,8 @@ const installComponentFromUpload = async ({
105
107
  const action = 'upgrade';
106
108
  await manager._rollbackCache.backup({ did: newBlocklet.meta.did, action, oldBlocklet });
107
109
 
110
+ const componentDids = [newChild.meta.did, ...newChildren.map((x) => x.meta.did)];
111
+
108
112
  await manager._downloadAndInstall({
109
113
  blocklet: newBlocklet,
110
114
  oldBlocklet,
@@ -112,7 +116,7 @@ const installComponentFromUpload = async ({
112
116
  throwOnError: true,
113
117
  postAction: action,
114
118
  skipCheckStatusBeforeDownload: true,
115
- selectedComponentDids: newChildren.map((x) => x.meta.did),
119
+ componentDids,
116
120
  });
117
121
  return manager.getBlocklet(newBlocklet.meta.did);
118
122
  };
@@ -127,8 +127,10 @@ const installComponentFromUrl = async ({
127
127
  throw err;
128
128
  }
129
129
 
130
+ const componentDids = [newChild.meta.did, ...newChildren.map((x) => x.meta.did)];
131
+
130
132
  // new blocklet
131
- const newBlocklet = await states.blocklet.setBlockletStatus(rootDid, BlockletStatus.waiting);
133
+ const newBlocklet = await states.blocklet.setBlockletStatus(rootDid, BlockletStatus.waiting, { componentDids });
132
134
 
133
135
  newBlocklet.children = blocklet.children;
134
136
  await validateBlocklet(newBlocklet);
@@ -138,7 +140,7 @@ const installComponentFromUrl = async ({
138
140
  const downloadParams = {
139
141
  oldBlocklet: { ...oldBlocklet },
140
142
  blocklet: { ...newBlocklet },
141
- selectedComponentDids: [newChild.meta.did, ...newChildren.map((x) => x.meta.did)],
143
+ componentDids,
142
144
  context,
143
145
  postAction: action,
144
146
  };
@@ -73,8 +73,8 @@ const check = async ({ did, states }) => {
73
73
  };
74
74
  };
75
75
 
76
- const upgrade = async ({ updateId, selectedComponentDids, context, states, manager }) => {
77
- if (!selectedComponentDids?.length) {
76
+ const upgrade = async ({ updateId, componentDids, context, states, manager }) => {
77
+ if (!componentDids?.length) {
78
78
  throw new Error('At least one component needs to be selected');
79
79
  }
80
80
 
@@ -87,7 +87,7 @@ const upgrade = async ({ updateId, selectedComponentDids, context, states, manag
87
87
  let dynamicComponents = [];
88
88
  const children = cloneDeep(oldBlocklet.children).map((oldComponent) => {
89
89
  const newComponent = sessionData.children.find((x) => x.meta.did === oldComponent.meta.did);
90
- if (newComponent && selectedComponentDids.includes(newComponent.meta.did)) {
90
+ if (newComponent && componentDids.includes(newComponent.meta.did)) {
91
91
  dynamicComponents.push(...(newComponent._dynamicComponents || []));
92
92
  delete newComponent._dynamicComponents;
93
93
  return newComponent;
@@ -97,8 +97,8 @@ const upgrade = async ({ updateId, selectedComponentDids, context, states, manag
97
97
  dynamicComponents = filterDuplicateComponents(dynamicComponents, children);
98
98
  children.push(...dynamicComponents);
99
99
 
100
- // selectedComponentDids
101
- selectedComponentDids.push(...dynamicComponents.map((x) => x.meta.did));
100
+ // componentDids
101
+ componentDids.push(...dynamicComponents.map((x) => x.meta.did));
102
102
 
103
103
  checkVersionCompatibility(children);
104
104
 
@@ -108,7 +108,7 @@ const upgrade = async ({ updateId, selectedComponentDids, context, states, manag
108
108
  });
109
109
 
110
110
  // new blocklet
111
- const newBlocklet = await states.blocklet.setBlockletStatus(did, BlockletStatus.waiting);
111
+ const newBlocklet = await states.blocklet.setBlockletStatus(did, BlockletStatus.waiting, { componentDids });
112
112
 
113
113
  newBlocklet.children = children;
114
114
  await validateBlocklet(newBlocklet);
@@ -128,7 +128,7 @@ const upgrade = async ({ updateId, selectedComponentDids, context, states, manag
128
128
  id: did,
129
129
  oldBlocklet: { ...oldBlocklet },
130
130
  blocklet: { ...newBlocklet },
131
- selectedComponentDids: selectedComponentDids || [],
131
+ componentDids: componentDids || [],
132
132
  context,
133
133
  postAction: action,
134
134
  },
@@ -27,10 +27,10 @@ class BlockletPm2Events extends EventEmitter {
27
27
  if (actualPm2Home !== expectedPm2Home) {
28
28
  return;
29
29
  }
30
- const { BLOCKLET_DID: blockletDid } = details.process || {};
31
- logger.debug('listen pm2 event', { name, blockletDid });
30
+ const { BLOCKLET_DID: blockletDid, BLOCKLET_COMPONENT_DID: componentDid } = details.process || {};
31
+ logger.debug('listen pm2 event', { name, blockletDid, componentDid });
32
32
  if (blockletDid) {
33
- this.emit(name, { blockletDid });
33
+ this.emit(name, { blockletDid, componentDid });
34
34
  }
35
35
  })
36
36
  .error((error) => {
package/lib/event.js CHANGED
@@ -3,7 +3,13 @@ const cloneDeep = require('lodash/cloneDeep');
3
3
  const { EventEmitter } = require('events');
4
4
  const { wipeSensitiveData } = require('@blocklet/meta/lib/util');
5
5
  const logger = require('@abtnode/logger')('@abtnode/core:event');
6
- const { BLOCKLET_MODES, BlockletStatus, BlockletSource, BlockletEvents } = require('@blocklet/constant');
6
+ const {
7
+ BLOCKLET_MODES,
8
+ BlockletStatus,
9
+ BlockletSource,
10
+ BlockletEvents,
11
+ BlockletInternalEvents,
12
+ } = require('@blocklet/constant');
7
13
  const { EVENTS } = require('@abtnode/constant');
8
14
  const { NodeMonitSender } = require('./monitor/node-monit-sender');
9
15
  const handleInstanceInStore = require('./util/public-to-store');
@@ -375,6 +381,10 @@ module.exports = ({
375
381
  listen(blockletManager, eventName, handleBlockletEvent);
376
382
  });
377
383
 
384
+ [BlockletInternalEvents.componentsUpdated, BlockletInternalEvents.appConfigChanged].forEach((eventName) => {
385
+ listen(blockletManager, eventName, onEvent);
386
+ });
387
+
378
388
  listen(notificationState, EVENTS.NOTIFICATION_CREATE, onEvent);
379
389
 
380
390
  listen(nodeState, BlockletEvents.purchaseChange, onEvent);
package/lib/index.js CHANGED
@@ -268,7 +268,6 @@ function ABTNode(options) {
268
268
  // For diagnose purpose
269
269
  syncBlockletStatus: blockletManager.status.bind(blockletManager),
270
270
  ensureBlockletIntegrity: blockletManager.ensureBlocklet.bind(blockletManager),
271
- updateBlockletStatus: states.blocklet.setBlockletStatus.bind(states.blocklet),
272
271
 
273
272
  getBlocklets: blockletManager.list.bind(blockletManager),
274
273
  getBlockletsFromBackup: blockletManager.listBackups.bind(blockletManager),
@@ -0,0 +1,22 @@
1
+ /* eslint-disable no-await-in-loop */
2
+ /* eslint-disable no-continue */
3
+
4
+ module.exports = async ({ states, printInfo }) => {
5
+ printInfo('Try to update component status...');
6
+
7
+ const apps = await states.blocklet.find({});
8
+
9
+ for (const app of apps || []) {
10
+ const appStatus = app.status;
11
+ let shouldUpdate = false;
12
+ for (const component of app.children || []) {
13
+ shouldUpdate = true;
14
+ component.status = appStatus;
15
+ }
16
+
17
+ if (shouldUpdate) {
18
+ await states.blocklet.update({ id: app.id }, { $set: { children: app.children } });
19
+ printInfo(`Blocklet in blocklet.db updated: ${app.meta?.title}. status: ${appStatus}`);
20
+ }
21
+ }
22
+ };
@@ -116,7 +116,7 @@ class BlockletRuntimeMonitor extends EventEmitter {
116
116
  await forEachBlocklet(
117
117
  blocklet,
118
118
  async (component, { id: componentId, ancestors }) => {
119
- if (component.meta.group !== BlockletGroup.gateway) {
119
+ if (component.meta.group !== BlockletGroup.gateway && component.status === BlockletStatus.running) {
120
120
  const processId = getComponentProcessId(component, ancestors);
121
121
  try {
122
122
  const runtimeInfo = await getRuntimeInfo(processId);
@@ -130,8 +130,13 @@ class BlockletRuntimeMonitor extends EventEmitter {
130
130
  appCpu += runtimeInfo.cpuUsage || 0;
131
131
  appMem += runtimeInfo.memoryUsage || 0;
132
132
  } catch (err) {
133
- this.logger.error('failed to get blocklet runtime info', { processId, error: err });
133
+ // component status in db may not sync with pm2 when server has just started
134
+ if (err.code !== 'BLOCKLET_PROCESS_404') {
135
+ this.logger.error('failed to get blocklet runtime info', { processId, error: err });
136
+ }
134
137
  }
138
+ } else {
139
+ delete this.data[blockletDid][componentId];
135
140
  }
136
141
  },
137
142
  { parallel: true }
@@ -2,6 +2,7 @@
2
2
  /* eslint-disable no-await-in-loop */
3
3
  /* eslint-disable function-paren-newline */
4
4
  /* eslint-disable no-underscore-dangle */
5
+ const pick = require('lodash/pick');
5
6
  const omit = require('lodash/omit');
6
7
  const uniq = require('lodash/uniq');
7
8
  const cloneDeep = require('lodash/cloneDeep');
@@ -13,17 +14,23 @@ const {
13
14
  getDisplayName,
14
15
  forEachBlocklet,
15
16
  forEachBlockletSync,
16
- forEachChildSync,
17
+ forEachComponentV2Sync,
17
18
  getBlockletServices,
18
19
  } = require('@blocklet/meta/lib/util');
19
- const { BlockletStatus, BlockletSource, BLOCKLET_MODES, BLOCKLET_DEFAULT_PORT_NAME } = require('@blocklet/constant');
20
+ const {
21
+ BlockletStatus,
22
+ BlockletSource,
23
+ BLOCKLET_MODES,
24
+ BLOCKLET_DEFAULT_PORT_NAME,
25
+ BlockletGroup,
26
+ } = require('@blocklet/constant');
20
27
  const { APP_STRUCT_VERSION } = require('@abtnode/constant');
21
28
 
22
29
  const logger = require('@abtnode/logger')('@abtnode/core:states:blocklet');
23
30
 
24
31
  const BaseState = require('./base');
25
32
  const { checkDuplicateComponents, ensureMeta } = require('../util/blocklet');
26
- const { validateBlockletMeta } = require('../util/blocklet');
33
+ const { validateBlockletMeta, getBlockletStatus, shouldSkipComponent } = require('../util/blocklet');
27
34
 
28
35
  const lock = new Lock('blocklet-port-assign-lock');
29
36
 
@@ -37,6 +44,10 @@ const getExternalPortsFromMeta = (meta) =>
37
44
  (meta.interfaces || []).map((x) => x.port && x.port.external).filter(Boolean);
38
45
 
39
46
  const formatBlocklet = (blocklet, phase, dek) => {
47
+ if (phase === 'onRead') {
48
+ blocklet.status = getBlockletStatus(blocklet);
49
+ }
50
+
40
51
  forEachBlockletSync(blocklet, (b) => {
41
52
  if (b.meta) {
42
53
  fixPerson(b.meta);
@@ -273,6 +284,9 @@ class BlockletState extends BaseState {
273
284
 
274
285
  const formatted = formatBlocklet(cloneDeep(updates), 'onUpdate', this.config.dek);
275
286
  const [, [updated]] = await this.update({ id: doc.id }, { $set: formatted });
287
+
288
+ updated.status = getBlockletStatus(updated);
289
+
276
290
  return updated;
277
291
  }
278
292
 
@@ -480,62 +494,55 @@ class BlockletState extends BaseState {
480
494
  }
481
495
 
482
496
  /**
483
- * @param {String} did blocklet did
497
+ * @param {Did} did blocklet did
484
498
  * @param {BlockletStatus} status blocklet status
485
- *
486
- * children status only different with parent before blocklet installation
487
- * @param {Array<componentId>} children
499
+ * @param {{
500
+ * componentDids?: Array<Did>
501
+ * }}
488
502
  */
489
- async setBlockletStatus(did, status, { children } = {}) {
503
+ async setBlockletStatus(did, status, { componentDids } = {}) {
490
504
  if (typeof status === 'undefined') {
491
505
  throw new Error('Unsupported blocklet status');
492
506
  }
493
507
 
494
508
  const doc = await this.getBlocklet(did);
495
- if (doc.status === status && !children) {
496
- return formatBlocklet(doc, 'onRead', this.config.dek);
497
- }
498
509
 
499
- const updates = { status, startedAt: null, stoppedAt: null };
500
- if (status === BlockletStatus.running) {
501
- updates.startedAt = new Date();
502
- }
503
- if (status === BlockletStatus.installed) {
504
- updates.installedAt = new Date();
510
+ if (doc.meta?.group === BlockletGroup.gateway && !doc.children?.length) {
511
+ return this.updateBlocklet(did, { status });
505
512
  }
506
- if (status === BlockletStatus.stopped) {
507
- updates.stoppedAt = new Date();
513
+
514
+ // for backward compatibility
515
+ if (!doc.structVersion && !doc.children?.length) {
516
+ return this.updateBlocklet(did, { status });
508
517
  }
509
518
 
510
519
  // update children status
511
- forEachChildSync(doc, (child, { id }) => {
512
- if (children === 'all') {
513
- child.status = status;
520
+ forEachComponentV2Sync(doc, (component) => {
521
+ if (component.meta.group === BlockletGroup.gateway) {
514
522
  return;
515
523
  }
516
524
 
517
- if (!children) {
518
- if (
519
- ![
520
- BlockletStatus.waiting,
521
- BlockletStatus.upgrading,
522
- BlockletStatus.installing,
523
- BlockletStatus.starting,
524
- ].includes(status)
525
- ) {
526
- child.status = status;
527
- }
528
-
525
+ if (shouldSkipComponent(component.meta.did, componentDids)) {
529
526
  return;
530
527
  }
531
528
 
532
- if (children.includes(id)) {
533
- child.status = status;
529
+ component.status = status;
530
+ if (status === BlockletStatus.running) {
531
+ component.startedAt = new Date();
532
+ component.stoppedAt = null;
533
+ }
534
+ if (status === BlockletStatus.stopped) {
535
+ component.startedAt = null;
536
+ component.stoppedAt = new Date();
534
537
  }
535
538
  });
536
539
 
537
- updates.children = doc.children;
538
- return this.updateBlocklet(did, updates);
540
+ return this.updateBlocklet(did, pick(doc, ['status', 'children']));
541
+ }
542
+
543
+ async setInstalledAt(did) {
544
+ logger.info('setInstalledAt', { did });
545
+ return this.updateBlocklet(did, { installedAt: new Date() });
539
546
  }
540
547
 
541
548
  async fillChildrenPorts(children, { defaultPort = 0, oldChildren, returnMaxPort } = {}) {
@@ -253,6 +253,7 @@ class NodeState extends BaseState {
253
253
  async getEnvironments() {
254
254
  return this.read().then((info) => ({
255
255
  ABT_NODE: info.version,
256
+ ABT_NODE_VERSION: info.version,
256
257
  ABT_NODE_DID: info.did,
257
258
  ABT_NODE_SK: info.sk,
258
259
  ABT_NODE_PK: info.pk,
@@ -74,6 +74,7 @@ const {
74
74
  findWebInterface,
75
75
  forEachBlockletSync,
76
76
  forEachChildSync,
77
+ forEachComponentV2Sync,
77
78
  isComponentBlocklet,
78
79
  getSharedConfigObj,
79
80
  getComponentName,
@@ -81,6 +82,8 @@ const {
81
82
  getBlockletAppIdList,
82
83
  isBeforeInstalled,
83
84
  getChainInfo,
85
+ isInProgress,
86
+ isRunning,
84
87
  } = require('@blocklet/meta/lib/util');
85
88
  const toBlockletDid = require('@blocklet/meta/lib/did');
86
89
  const { titleSchema, descriptionSchema, logoSchema } = require('@blocklet/meta/lib/schema');
@@ -368,8 +371,9 @@ const getComponentSystemEnvironments = (blocklet) => {
368
371
  }
369
372
 
370
373
  return {
371
- BLOCKLET_REAL_DID: blocklet.env.id,
374
+ BLOCKLET_REAL_DID: blocklet.env.id, // <appDid>/componentDid> e.g. xxxxx/xxxxx
372
375
  BLOCKLET_REAL_NAME: blocklet.env.name,
376
+ BLOCKLET_COMPONENT_DID: blocklet.meta.did, // component meta did e.g. xxxxxx
373
377
  BLOCKLET_DATA_DIR: blocklet.env.dataDir,
374
378
  BLOCKLET_LOG_DIR: blocklet.env.logsDir,
375
379
  BLOCKLET_CACHE_DIR: blocklet.env.cacheDir,
@@ -501,7 +505,15 @@ const getHealthyCheckTimeout = (blocklet, { checkHealthImmediately } = {}) => {
501
505
  */
502
506
  const startBlockletProcess = async (
503
507
  blocklet,
504
- { preStart = noop, postStart = noopAsync, nodeEnvironments, nodeInfo, e2eMode, skippedProcessIds = [] } = {}
508
+ {
509
+ preStart = noop,
510
+ postStart = noopAsync,
511
+ nodeEnvironments,
512
+ nodeInfo,
513
+ e2eMode,
514
+ skippedProcessIds = [],
515
+ componentDids,
516
+ } = {}
505
517
  ) => {
506
518
  if (!blocklet) {
507
519
  throw new Error('blocklet should not be empty');
@@ -517,7 +529,12 @@ const startBlockletProcess = async (
517
529
  const { appMain, processId, appCwd, logsDir } = b.env;
518
530
 
519
531
  if (skippedProcessIds.includes(processId)) {
520
- logger.info(`skip start process ${processId}`);
532
+ logger.info(`skip start skipped process ${processId}`);
533
+ return;
534
+ }
535
+
536
+ if (shouldSkipComponent(b.meta.did, componentDids)) {
537
+ logger.info(`skip start process not selected: ${b.meta.did}`, { processId });
521
538
  return;
522
539
  }
523
540
 
@@ -618,31 +635,15 @@ const startBlockletProcess = async (
618
635
  * Stop all precesses of a blocklet
619
636
  * @param {*} blocklet should contain env props
620
637
  */
621
- const stopBlockletProcess = async (blocklet, { preStop = noop, skippedProcessIds = [] } = {}) => {
622
- await forEachBlocklet(
623
- blocklet,
624
- async (b, { ancestors }) => {
625
- if (b.meta?.group === BlockletGroup.gateway) {
626
- return;
627
- }
628
-
629
- if (skippedProcessIds.includes(b.env.processId)) {
630
- logger.info(`skip stop process ${b.env.processId}`);
631
- return;
632
- }
633
-
634
- await preStop(b, { ancestors });
635
- await deleteProcess(b.env.processId);
636
- },
637
- { parallel: true }
638
- );
638
+ const stopBlockletProcess = async (blocklet, { preStop = noop, skippedProcessIds = [], componentDids } = {}) => {
639
+ return deleteBlockletProcess(blocklet, { preDelete: preStop, skippedProcessIds, componentDids });
639
640
  };
640
641
 
641
642
  /**
642
643
  * Delete all precesses of a blocklet
643
644
  * @param {*} blocklet should contain env props
644
645
  */
645
- const deleteBlockletProcess = async (blocklet, { preDelete = noop, skippedProcessIds = [] } = {}) => {
646
+ const deleteBlockletProcess = async (blocklet, { preDelete = noop, skippedProcessIds = [], componentDids } = {}) => {
646
647
  await forEachBlocklet(
647
648
  blocklet,
648
649
  async (b, { ancestors }) => {
@@ -652,7 +653,12 @@ const deleteBlockletProcess = async (blocklet, { preDelete = noop, skippedProces
652
653
  }
653
654
 
654
655
  if (skippedProcessIds.includes(b.env.processId)) {
655
- logger.info(`skip delete process ${b.env.processId}`);
656
+ logger.info(`skip delete skipped process ${b.env.processId}`);
657
+ return;
658
+ }
659
+
660
+ if (shouldSkipComponent(b.meta?.did, componentDids)) {
661
+ logger.info(`skip delete process not selected: ${b.meta.did}`, { processId: b.env.processId });
656
662
  return;
657
663
  }
658
664
 
@@ -667,52 +673,25 @@ const deleteBlockletProcess = async (blocklet, { preDelete = noop, skippedProces
667
673
  * Reload all precesses of a blocklet
668
674
  * @param {*} blocklet should contain env props
669
675
  */
670
- const reloadBlockletProcess = async (blocklet) =>
676
+ const reloadBlockletProcess = async (blocklet, { componentDids } = {}) =>
671
677
  forEachBlocklet(
672
678
  blocklet,
673
679
  async (b) => {
674
680
  if (b.meta.group === BlockletGroup.gateway) {
675
681
  return;
676
682
  }
683
+
684
+ if (shouldSkipComponent(b.meta.did, componentDids)) {
685
+ logger.info(`skip reload process not selected: ${b.meta.did}`, { processId: b.env.processId });
686
+ return;
687
+ }
688
+
677
689
  logger.info('reload process', { processId: b.env.processId });
678
690
  await reloadProcess(b.env.processId);
679
691
  },
680
692
  { parallel: false }
681
693
  );
682
694
 
683
- const getBlockletStatusFromProcess = async (blocklet) => {
684
- const tasks = [];
685
- await forEachBlocklet(blocklet, (b) => {
686
- if (b.meta.group !== BlockletGroup.gateway) {
687
- tasks.push(getProcessState(b.env.processId));
688
- }
689
- });
690
-
691
- const list = await Promise.all(tasks);
692
-
693
- if (!list.length) {
694
- return blocklet.status;
695
- }
696
-
697
- return getRootBlockletStatus(list);
698
- };
699
-
700
- /**
701
- * @param {Array<BlockletStatus>} statusList
702
- */
703
- const getRootBlockletStatus = (statusList = []) => {
704
- const noRunningStatus = statusList.find((x) => x !== BlockletStatus.running);
705
- if (noRunningStatus) {
706
- if (statusList.some((x) => x === BlockletStatus.error)) {
707
- return BlockletStatus.error;
708
- }
709
-
710
- return noRunningStatus;
711
- }
712
-
713
- return BlockletStatus.running;
714
- };
715
-
716
695
  /**
717
696
  * @param {*} processId
718
697
  * @returns {BlockletStatus}
@@ -900,13 +879,20 @@ const validateBlockletChainInfo = (blocklet) => {
900
879
  return chainInfo;
901
880
  };
902
881
 
903
- const checkBlockletProcessHealthy = async (blocklet, { minConsecutiveTime, timeout } = {}) => {
882
+ const checkBlockletProcessHealthy = async (blocklet, { minConsecutiveTime, timeout, componentDids } = {}) => {
904
883
  await forEachBlocklet(
905
884
  blocklet,
906
885
  async (b) => {
907
- if (b.meta.group !== BlockletGroup.gateway) {
908
- await _checkProcessHealthy(b, { minConsecutiveTime, timeout });
886
+ if (b.meta.group === BlockletGroup.gateway) {
887
+ return;
888
+ }
889
+
890
+ if (shouldSkipComponent(b.meta.did, componentDids)) {
891
+ logger.info('skip check component healthy not selected', { id: b.env.id, processId: b.env.processId });
892
+ return;
909
893
  }
894
+
895
+ await _checkProcessHealthy(b, { minConsecutiveTime, timeout });
910
896
  },
911
897
  { parallel: true }
912
898
  );
@@ -1902,6 +1888,71 @@ const getBlockletDidDomainList = (blocklet, nodeInfo) => {
1902
1888
  return domainAliases;
1903
1889
  };
1904
1890
 
1891
+ const getBlockletStatus = (blocklet) => {
1892
+ const fallbackStatus = BlockletStatus.stopped;
1893
+
1894
+ if (!blocklet) {
1895
+ return fallbackStatus;
1896
+ }
1897
+
1898
+ if (!blocklet.children?.length) {
1899
+ if (blocklet.meta?.group === BlockletGroup.gateway) {
1900
+ return blocklet.status;
1901
+ }
1902
+
1903
+ if (blocklet.status === BlockletStatus.added) {
1904
+ return BlockletStatus.added;
1905
+ }
1906
+
1907
+ // for backward compatibility
1908
+ if (!blocklet.structVersion) {
1909
+ return blocklet.status;
1910
+ }
1911
+
1912
+ return fallbackStatus;
1913
+ }
1914
+
1915
+ let inProgressStatus;
1916
+ let runningStatus;
1917
+ let status;
1918
+
1919
+ forEachComponentV2Sync(blocklet, (component) => {
1920
+ if (component.meta?.group === BlockletGroup.gateway) {
1921
+ return;
1922
+ }
1923
+
1924
+ if (isInProgress(component.status)) {
1925
+ if (!inProgressStatus) {
1926
+ inProgressStatus = component.status;
1927
+ }
1928
+ return;
1929
+ }
1930
+
1931
+ if (isRunning(component.status)) {
1932
+ runningStatus = component.status;
1933
+ return;
1934
+ }
1935
+
1936
+ status = component.status;
1937
+ });
1938
+
1939
+ return inProgressStatus || runningStatus || status;
1940
+ };
1941
+
1942
+ const shouldSkipComponent = (componentDid, whiteList) => {
1943
+ if (!whiteList || !Array.isArray(whiteList)) {
1944
+ return false;
1945
+ }
1946
+
1947
+ const arr = whiteList.filter(Boolean);
1948
+
1949
+ if (!arr.length) {
1950
+ return false;
1951
+ }
1952
+
1953
+ return !arr.includes(componentDid);
1954
+ };
1955
+
1905
1956
  const shouldCleanExpiredBlocklet = (expirationDate) => {
1906
1957
  return dayjs().diff(dayjs(expirationDate), 'day') > EXPIRED_BLOCKLET_DATA_RETENTION_DAYS;
1907
1958
  };
@@ -1924,7 +1975,6 @@ module.exports = {
1924
1975
  stopBlockletProcess,
1925
1976
  deleteBlockletProcess,
1926
1977
  reloadBlockletProcess,
1927
- getBlockletStatusFromProcess,
1928
1978
  checkBlockletProcessHealthy,
1929
1979
  getHealthyCheckTimeout,
1930
1980
  getProcessInfo,
@@ -1963,6 +2013,9 @@ module.exports = {
1963
2013
  getFixedBundleSource,
1964
2014
  ensureAppLogo,
1965
2015
  getBlockletDidDomainList,
2016
+ getProcessState,
2017
+ getBlockletStatus,
2018
+ shouldSkipComponent,
1966
2019
  shouldCleanExpiredBlocklet,
1967
2020
  getBlockletURLForLauncher,
1968
2021
  };