@abtnode/core 1.8.3 → 1.8.4

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.
@@ -128,7 +128,7 @@ const {
128
128
  validateOwner,
129
129
  } = util;
130
130
 
131
- const preDownloadLock = new Lock('pre-download-lock');
131
+ const statusLock = new Lock('blocklet-status-lock');
132
132
 
133
133
  const asyncFs = fs.promises;
134
134
 
@@ -429,6 +429,12 @@ class BlockletManager extends BaseBlockletManager {
429
429
 
430
430
  return blocklet;
431
431
  } catch (err) {
432
+ const status = await states.blocklet.getBlockletStatus(did);
433
+ if ([BlockletStatus.stopping, BlockletStatus.stopped].includes(status)) {
434
+ logger.info('Failed to start blocklet maybe due to manually stopped');
435
+ return states.blocklet.getBlocklet(did);
436
+ }
437
+
432
438
  const error = Array.isArray(err) ? err[0] : err;
433
439
  logger.error('Failed to start blocklet', { error, did, name: blocklet.meta.name });
434
440
  const description = `Start blocklet ${blocklet.meta.name} failed with error: ${error.message}`;
@@ -679,26 +685,38 @@ class BlockletManager extends BaseBlockletManager {
679
685
  return newBlocklet;
680
686
  }
681
687
 
682
- async cancelDownload({ did }, context) {
683
- await preDownloadLock.acquire();
688
+ async cancelDownload({ did: inputDid }, context) {
684
689
  try {
685
- const blocklet = await states.blocklet.getBlocklet(did);
690
+ await statusLock.acquire();
691
+ const blocklet = await states.blocklet.getBlocklet(inputDid);
686
692
  if (!blocklet) {
687
- throw new Error('Can not cancel download for non-exist blocklet in database.', { did });
693
+ throw new Error('Can not cancel download for non-exist blocklet in database.', { inputDid });
694
+ }
695
+
696
+ const { name, did, version } = blocklet.meta;
697
+
698
+ if (![BlockletStatus.downloading, BlockletStatus.waiting].includes(blocklet.status)) {
699
+ throw new Error(`Can not cancel blocklet that status is ${fromBlockletStatus(blocklet.status)}`);
700
+ }
701
+
702
+ const job = await this.installQueue.get(did);
703
+ if (job) {
704
+ const { postAction, oldBlocklet } = job;
705
+ await this._rollback(postAction, did, oldBlocklet);
688
706
  }
689
707
 
690
708
  if (blocklet.status === BlockletStatus.downloading) {
691
709
  await this._cancelDownload(blocklet.meta, context);
692
710
  } else if (blocklet.status === BlockletStatus.waiting) {
693
711
  await this._cancelWaiting(blocklet.meta, context);
694
- } else {
695
- throw new Error(`Can not cancel blocklet that status is ${fromBlockletStatus(blocklet.status)}`);
696
712
  }
697
713
 
698
- preDownloadLock.release();
714
+ logger.info('cancel download blocklet', { did, name, version, status: fromBlockletStatus(blocklet.status) });
715
+
716
+ statusLock.release();
699
717
  return blocklet;
700
718
  } catch (error) {
701
- preDownloadLock.release();
719
+ statusLock.release();
702
720
  throw error;
703
721
  }
704
722
  }
@@ -1516,39 +1534,45 @@ class BlockletManager extends BaseBlockletManager {
1516
1534
  const { meta } = blocklet;
1517
1535
  const { name, did, version } = meta;
1518
1536
 
1537
+ // check status
1519
1538
  try {
1520
- await preDownloadLock.acquire();
1539
+ await statusLock.acquire();
1521
1540
 
1522
1541
  const b0 = await states.blocklet.getBlocklet(did);
1523
- if (!b0 || ![BlockletStatus.waiting, BlockletStatus.downloading].includes(b0.status)) {
1542
+ if (!b0 || ![BlockletStatus.waiting].includes(b0.status)) {
1524
1543
  if (!b0) {
1525
- logger.error('blocklet does not exist before downloading', { name, did });
1544
+ throw new Error('blocklet does not exist before downloading');
1526
1545
  } else {
1527
- logger.error('blocklet status is invalid before downloading', {
1528
- name,
1529
- did,
1530
- status: fromBlockletStatus(b0.status),
1531
- });
1546
+ throw new Error(`blocklet status is invalid before downloading: ${fromBlockletStatus(b0.status)}`);
1532
1547
  }
1533
- preDownloadLock.release();
1534
- await this._rollback(postAction, did, oldBlocklet);
1535
- return;
1536
1548
  }
1549
+ statusLock.release();
1550
+ } catch (error) {
1551
+ statusLock.release();
1552
+ logger.error('Check blocklet status failed before downloading', {
1553
+ name,
1554
+ did,
1555
+ error,
1556
+ });
1557
+ await this._rollback(postAction, did, oldBlocklet);
1558
+ return;
1559
+ }
1537
1560
 
1538
- preDownloadLock.release();
1539
-
1561
+ // download bundle
1562
+ try {
1540
1563
  const { isCancelled } = await this._downloadBlocklet(blocklet, oldBlocklet, context);
1541
1564
 
1542
1565
  if (isCancelled) {
1543
- logger.info('Download was canceled manually', { name, did, version });
1544
- await this._rollback(postAction, did, oldBlocklet);
1566
+ logger.info('Download was canceled', { name, did, version });
1567
+
1568
+ if ((await states.blocklet.getBlockletStatus(did)) === BlockletStatus.downloading) {
1569
+ await this._rollback(postAction, did, oldBlocklet);
1570
+ }
1545
1571
  return;
1546
1572
  }
1547
1573
  } catch (err) {
1548
1574
  logger.error('Download blocklet tarball failed', { name, did, version });
1549
1575
 
1550
- preDownloadLock.release();
1551
-
1552
1576
  this.emit(BlockletEvents.downloadFailed, {
1553
1577
  meta: { did },
1554
1578
  error: {
@@ -1576,6 +1600,31 @@ class BlockletManager extends BaseBlockletManager {
1576
1600
  return;
1577
1601
  }
1578
1602
 
1603
+ // update status
1604
+ try {
1605
+ await statusLock.acquire();
1606
+
1607
+ if ((await states.blocklet.getBlockletStatus(did)) !== BlockletStatus.downloading) {
1608
+ throw new Error('blocklet status changed durning download');
1609
+ }
1610
+
1611
+ if (postAction === 'install') {
1612
+ const state = await states.blocklet.setBlockletStatus(did, BlockletStatus.installing);
1613
+ this.emit(BlockletEvents.statusChange, state);
1614
+ }
1615
+
1616
+ if (['upgrade', 'downgrade'].includes(postAction)) {
1617
+ const state = await states.blocklet.setBlockletStatus(did, BlockletStatus.upgrading);
1618
+ this.emit(BlockletEvents.statusChange, state);
1619
+ }
1620
+
1621
+ statusLock.release();
1622
+ } catch (error) {
1623
+ logger.error(error.message);
1624
+ statusLock.release();
1625
+ }
1626
+
1627
+ // install
1579
1628
  try {
1580
1629
  // install blocklet
1581
1630
  if (postAction === 'install') {
@@ -1599,9 +1648,6 @@ class BlockletManager extends BaseBlockletManager {
1599
1648
  const { did, version } = meta;
1600
1649
  logger.info('do install blocklet', { did, version });
1601
1650
 
1602
- const state = await states.blocklet.setBlockletStatus(did, BlockletStatus.installing);
1603
- this.emit(BlockletEvents.statusChange, state);
1604
-
1605
1651
  try {
1606
1652
  const installedBlocklet = await this._installBlocklet({
1607
1653
  did,
@@ -1629,9 +1675,6 @@ class BlockletManager extends BaseBlockletManager {
1629
1675
  const { version, did } = newBlocklet.meta;
1630
1676
  logger.info(`do ${action} blocklet`, { did, version });
1631
1677
 
1632
- const state = await states.blocklet.setBlockletStatus(did, BlockletStatus.upgrading);
1633
- this.emit(BlockletEvents.statusChange, state);
1634
-
1635
1678
  try {
1636
1679
  await this._upgradeBlocklet({
1637
1680
  newBlocklet,
@@ -1663,6 +1706,12 @@ class BlockletManager extends BaseBlockletManager {
1663
1706
  const res = await this.status(did, { forceSync: true });
1664
1707
  this.emit(BlockletEvents.started, res);
1665
1708
  } catch (error) {
1709
+ const status = await states.blocklet.getBlockletStatus(did);
1710
+ if ([BlockletStatus.stopping, BlockletStatus.stopped].includes(status)) {
1711
+ logger.info(`Check blocklet healthy failing because blocklet is ${fromBlockletStatus(status)}`);
1712
+ return;
1713
+ }
1714
+
1666
1715
  logger.error('check blocklet if started failed', { did, name, context, timeout, error });
1667
1716
 
1668
1717
  await this.deleteProcess({ did }, context);
@@ -3157,26 +3206,19 @@ class BlockletManager extends BaseBlockletManager {
3157
3206
 
3158
3207
  // eslint-disable-next-line no-unused-vars
3159
3208
  async _cancelDownload(blockletMeta, context) {
3160
- const { did, name, version } = blockletMeta;
3209
+ const { did } = blockletMeta;
3161
3210
 
3162
3211
  if (this.downloadCtrls[did]) {
3163
3212
  for (const cancelCtrl of this.downloadCtrls[did].values()) {
3164
3213
  cancelCtrl.cancel();
3165
3214
  }
3166
- logger.info('cancel download blocklet', { did, name, version });
3167
3215
  }
3168
3216
  }
3169
3217
 
3170
3218
  // eslint-disable-next-line no-unused-vars
3171
3219
  async _cancelWaiting(blockletMeta, context) {
3172
- const { did, name, version } = blockletMeta;
3173
-
3174
- const {
3175
- job: { postAction, oldBlocklet },
3176
- } = await this.installQueue.cancel(did);
3177
- await this._rollback(postAction, did, oldBlocklet);
3178
-
3179
- logger.info('cancel waiting blocklet', { did, name, version });
3220
+ const { did } = blockletMeta;
3221
+ return this.installQueue.cancel(did);
3180
3222
  }
3181
3223
 
3182
3224
  /**
@@ -102,6 +102,22 @@ class BlockletState extends BaseState {
102
102
  });
103
103
  }
104
104
 
105
+ async getBlockletStatus(did) {
106
+ return new Promise((resolve, reject) => {
107
+ if (!did) {
108
+ resolve(null);
109
+ }
110
+
111
+ this.db.findOne({ $or: [{ 'meta.did': did }, { appDid: did }] }, { status: 1 }, (err, doc) => {
112
+ if (err) {
113
+ return reject(err);
114
+ }
115
+
116
+ return resolve(doc ? doc.status : null);
117
+ });
118
+ });
119
+ }
120
+
105
121
  hasBlocklet(did) {
106
122
  return new Promise((resolve, reject) => {
107
123
  if (!did) {
@@ -4,6 +4,7 @@ const { evaluateURLs } = require('@abtnode/util/lib/url-evaluation');
4
4
  const checkURLAccessible = require('@abtnode/util/lib/url-evaluation/check-accessible-node');
5
5
  const { EVENTS } = require('@abtnode/constant');
6
6
  const WebHookSender = require('./sender');
7
+ const WalletSender = require('./sender/wallet');
7
8
  const createQueue = require('../queue');
8
9
  const IP = require('../util/ip');
9
10
  const states = require('../states');
@@ -72,6 +73,11 @@ module.exports = ({ events, dataDirs, instance }) => {
72
73
  const baseUrls = await getBaseUrls(instance, [external, internal]);
73
74
  const senderFns = {};
74
75
 
76
+ // Always send message to wallet
77
+ webhookList.push({
78
+ type: WalletSender.type,
79
+ });
80
+
75
81
  if (webhookList.length) {
76
82
  for (let i = 0; i < webhookList.length; i++) {
77
83
  const item = webhookList[i];
@@ -79,8 +85,7 @@ module.exports = ({ events, dataDirs, instance }) => {
79
85
  const senderInstance = WebHookSender.getMessageSender(item.type);
80
86
  senderFns[item.type] = senderInstance.send.bind(senderInstance);
81
87
  }
82
- const { name } = nodeInfo;
83
- const options = { ...message, nodeInfo: `*${name}*` };
88
+ const options = { ...message, nodeInfo, node: instance };
84
89
  if (item.type === 'slack') {
85
90
  // eslint-disable-next-line
86
91
  options.urlInfo = await getSlackUrlInfo(message.action, baseUrls);
@@ -3,6 +3,7 @@ const logger = require('@abtnode/logger')('@abtnode/core:sender');
3
3
 
4
4
  const Slack = require('./slack');
5
5
  const Api = require('./api');
6
+ const Wallet = require('./wallet');
6
7
 
7
8
  const SenderMap = new Map([
8
9
  [Slack.type, Slack],
@@ -12,6 +13,10 @@ const SenderMap = new Map([
12
13
  const getSenderNames = () => [...SenderMap.keys()];
13
14
 
14
15
  const getSender = (name) => {
16
+ if (name === Wallet.type) {
17
+ return Wallet;
18
+ }
19
+
15
20
  if (!SenderMap.has(name)) {
16
21
  logger.error(`getSender:sender name [${name}] does not exist`);
17
22
  return null;
@@ -29,7 +29,7 @@ class SlackSender extends BaseSender {
29
29
  type: 'section',
30
30
  text: {
31
31
  type: 'mrkdwn',
32
- text: nodeInfo,
32
+ text: `*${nodeInfo.name}*`,
33
33
  },
34
34
  },
35
35
  {
@@ -0,0 +1,45 @@
1
+ const logger = require('@abtnode/logger')('@abtnode/core:sender:api');
2
+ const { sendToUser } = require('@blocklet/sdk/lib/util/send-notification');
3
+ const { ROLES, PASSPORT_STATUS } = require('@abtnode/constant');
4
+ const BaseSender = require('../base');
5
+
6
+ class WalletSender extends BaseSender {
7
+ async send(params, data = {}) {
8
+ const { title, description, nodeInfo, node } = data;
9
+
10
+ try {
11
+ const sender = {
12
+ appDid: nodeInfo.did,
13
+ appSk: nodeInfo.sk,
14
+ };
15
+
16
+ const message = {
17
+ title,
18
+ body: description,
19
+ };
20
+
21
+ const { users } = await node.getUsers({ teamDid: nodeInfo.did, paging: { pageSize: 100 } });
22
+ const adminUsers = users
23
+ .filter(
24
+ (x) =>
25
+ x.approved &&
26
+ (x.passports || []).some(
27
+ (y) => [ROLES.OWNER, ROLES.ADMIN].includes(y.name) && y.status === PASSPORT_STATUS.VALID
28
+ )
29
+ )
30
+ .map((x) => x.did);
31
+
32
+ if (!adminUsers.length) {
33
+ return;
34
+ }
35
+
36
+ await sendToUser(adminUsers, message, sender, process.env.ABT_NODE_SERVICE_PORT);
37
+ } catch (error) {
38
+ logger.error('failed to push notification to wallet', { error });
39
+ }
40
+ }
41
+ }
42
+
43
+ WalletSender.type = 'wallet';
44
+
45
+ module.exports = WalletSender;
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.8.3",
6
+ "version": "1.8.4",
7
7
  "description": "",
8
8
  "main": "lib/index.js",
9
9
  "files": [
@@ -19,17 +19,17 @@
19
19
  "author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
20
20
  "license": "MIT",
21
21
  "dependencies": {
22
- "@abtnode/certificate-manager": "1.8.3",
23
- "@abtnode/constant": "1.8.3",
24
- "@abtnode/cron": "1.8.3",
25
- "@abtnode/db": "1.8.3",
26
- "@abtnode/logger": "1.8.3",
27
- "@abtnode/queue": "1.8.3",
28
- "@abtnode/rbac": "1.8.3",
29
- "@abtnode/router-provider": "1.8.3",
30
- "@abtnode/static-server": "1.8.3",
31
- "@abtnode/timemachine": "1.8.3",
32
- "@abtnode/util": "1.8.3",
22
+ "@abtnode/certificate-manager": "1.8.4",
23
+ "@abtnode/constant": "1.8.4",
24
+ "@abtnode/cron": "1.8.4",
25
+ "@abtnode/db": "1.8.4",
26
+ "@abtnode/logger": "1.8.4",
27
+ "@abtnode/queue": "1.8.4",
28
+ "@abtnode/rbac": "1.8.4",
29
+ "@abtnode/router-provider": "1.8.4",
30
+ "@abtnode/static-server": "1.8.4",
31
+ "@abtnode/timemachine": "1.8.4",
32
+ "@abtnode/util": "1.8.4",
33
33
  "@arcblock/did": "1.17.5",
34
34
  "@arcblock/did-motif": "^1.1.10",
35
35
  "@arcblock/did-util": "1.17.5",
@@ -37,10 +37,11 @@
37
37
  "@arcblock/jwt": "^1.17.5",
38
38
  "@arcblock/pm2-events": "^0.0.5",
39
39
  "@arcblock/vc": "1.17.5",
40
- "@blocklet/meta": "1.8.3",
40
+ "@blocklet/meta": "1.8.4",
41
+ "@blocklet/sdk": "1.8.4",
41
42
  "@fidm/x509": "^1.2.1",
42
- "@nedb/core": "^1.3.1",
43
- "@nedb/multi": "^1.3.1",
43
+ "@nedb/core": "^1.3.2",
44
+ "@nedb/multi": "^1.3.2",
44
45
  "@ocap/mcrypto": "1.17.5",
45
46
  "@ocap/util": "1.17.5",
46
47
  "@ocap/wallet": "1.17.5",
@@ -81,5 +82,5 @@
81
82
  "express": "^4.17.1",
82
83
  "jest": "^27.4.5"
83
84
  },
84
- "gitHead": "c734aca7bf1fc03378c3b082d0622b6a540a8bd3"
85
+ "gitHead": "c42fb1bb84c5eef0f753fd5397d8007c7a6eee19"
85
86
  }