@ocap/resolver 1.19.4 → 1.19.5

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.
package/lib/index.js CHANGED
@@ -1046,11 +1046,11 @@ module.exports = class OCAPResolver {
1046
1046
  if (limit && paging.total > limit) {
1047
1047
  throw new CustomError('EXCEED_LIMIT', `Total exceeds limit ${limit}`);
1048
1048
  }
1049
- if (paging.total < pageSize) {
1049
+ if (paging.total <= pageSize) {
1050
1050
  return firstPage;
1051
1051
  }
1052
1052
 
1053
- const totalPage = Math.floor(paging.total / pageSize);
1053
+ const totalPage = Math.ceil(paging.total / pageSize) - 1;
1054
1054
  const cursors = new Array(totalPage).fill(true).map((_, i) => (i + 1) * pageSize);
1055
1055
  const step = process.env.RESOLVER_BATCH_CONCURRENCY || 3;
1056
1056
  let results = firstPage;
@@ -1282,23 +1282,14 @@ module.exports = class OCAPResolver {
1282
1282
  * @param {number} [param.concurrency=3] Number of concurrent requests
1283
1283
  * @param {number} [param.chunkSize=2000] Maximum number of items to return in each next() call
1284
1284
  * @param {number} [param.pageSize=100] Number of items per page
1285
- * @param {Function} param.getTime Function to get timestamp from item
1285
+ * @param {string} param.timeKey Key to access time in response
1286
1286
  * @param {string} param.dataKey Key to access data in response
1287
1287
  * @returns {Promise<Array>} Array of fetched items
1288
1288
  */
1289
- listChunks(fn, { concurrency = 3, chunkSize = 2000, pageSize = 100, getTime, dataKey }) {
1290
- let totalPage;
1291
- let curPage;
1289
+ listChunks(fn, { total, concurrency = 3, chunkSize = 2000, pageSize = 100, timeKey, dataKey }) {
1292
1290
  let done = false;
1293
1291
  let time;
1294
-
1295
- const fetchFirstPage = async () => {
1296
- const { paging, page, [dataKey]: list } = await fn({ size: pageSize, cursor: '0' });
1297
- const total = paging?.total || page?.total;
1298
- curPage = 1;
1299
- totalPage = Math.ceil(total / pageSize);
1300
- return list;
1301
- };
1292
+ const totalPage = Math.ceil(total / pageSize);
1302
1293
 
1303
1294
  const next = async () => {
1304
1295
  if (done) {
@@ -1307,28 +1298,10 @@ module.exports = class OCAPResolver {
1307
1298
 
1308
1299
  let results = [];
1309
1300
 
1310
- // first page
1311
- if (!totalPage) {
1312
- const data = await fetchFirstPage();
1313
- // only 1 page
1314
- if (data.length < pageSize) {
1315
- done = true;
1316
- return data;
1317
- }
1318
-
1319
- time = getTime(data[data.length - 1]);
1320
- results = results.concat(data);
1321
-
1322
- // limit
1323
- if (data.length >= chunkSize) {
1324
- return results;
1325
- }
1326
- }
1327
-
1328
1301
  // next pages
1329
- for (; curPage < totalPage; curPage += concurrency) {
1302
+ for (let curPage = 0; curPage < totalPage; curPage += concurrency) {
1330
1303
  const batchResults = await Promise.all(
1331
- new Array(concurrency).fill(true).map(async (_, i) => {
1304
+ new Array(Math.min(concurrency, totalPage - curPage)).fill(true).map(async (_, i) => {
1332
1305
  const { [dataKey]: list } = await fn({
1333
1306
  size: pageSize,
1334
1307
  cursor: i * pageSize,
@@ -1346,7 +1319,7 @@ module.exports = class OCAPResolver {
1346
1319
  }
1347
1320
 
1348
1321
  results = results.concat(flatResults);
1349
- time = results.length ? getTime(results[results.length - 1]) : null;
1322
+ time = results.length ? results[results.length - 1][timeKey] : null;
1350
1323
 
1351
1324
  // limit
1352
1325
  if (results.length >= chunkSize) {
@@ -1364,7 +1337,7 @@ module.exports = class OCAPResolver {
1364
1337
  };
1365
1338
  }
1366
1339
 
1367
- listTransactionsChunks(args = {}, { chunkSize = 2000, pageSize = 100 } = {}) {
1340
+ async listTransactionsChunks(args = {}, { chunkSize = 2000, pageSize = 100 } = {}) {
1368
1341
  return this.listChunks(
1369
1342
  ({ size, time, cursor }) =>
1370
1343
  this.listTransactions({
@@ -1379,14 +1352,15 @@ module.exports = class OCAPResolver {
1379
1352
  }),
1380
1353
  {
1381
1354
  dataKey: 'transactions',
1382
- getTime: (tx) => tx?.time,
1355
+ timeKey: 'time',
1356
+ total: await this.indexdb.tx.count(),
1383
1357
  chunkSize,
1384
1358
  pageSize,
1385
1359
  }
1386
1360
  );
1387
1361
  }
1388
1362
 
1389
- listStakeChunks(args = {}, { chunkSize = 2000, pageSize = 100 } = {}) {
1363
+ async listStakeChunks(args = {}, { chunkSize = 2000, pageSize = 100 } = {}) {
1390
1364
  return this.listChunks(
1391
1365
  ({ size, time, cursor }) =>
1392
1366
  this.listStakes({
@@ -1401,7 +1375,8 @@ module.exports = class OCAPResolver {
1401
1375
  }),
1402
1376
  {
1403
1377
  dataKey: 'stakes',
1404
- getTime: (state) => state?.time,
1378
+ timeKey: 'renaissanceTime',
1379
+ total: await this.indexdb.stake.count(),
1405
1380
  chunkSize,
1406
1381
  pageSize,
1407
1382
  }
@@ -40,7 +40,7 @@ class TokenDistributionManager {
40
40
  return data && createIndexedTokenDistribution(data);
41
41
  }
42
42
 
43
- async saveDistribution(distribution) {
43
+ async saveDistribution(distribution, isEnsureLatest = true) {
44
44
  const data = createIndexedTokenDistribution(distribution);
45
45
  const indexdbDistribution = await this.getDistribution(data.tokenAddress);
46
46
 
@@ -48,8 +48,10 @@ class TokenDistributionManager {
48
48
  await this.indexdb.tokenDistribution.insert(data);
49
49
  } else {
50
50
  // ensure txTime is latest
51
- const latestTime = Math.max(new Date(indexdbDistribution.txTime).getTime(), new Date(data.txTime).getTime());
52
- data.txTime = new Date(latestTime).toISOString();
51
+ if (isEnsureLatest) {
52
+ const latestTime = Math.max(new Date(indexdbDistribution.txTime).getTime(), new Date(data.txTime).getTime());
53
+ data.txTime = new Date(latestTime).toISOString();
54
+ }
53
55
  await this.indexdb.tokenDistribution.update(data.tokenAddress, data);
54
56
  }
55
57
 
@@ -100,14 +102,14 @@ class TokenDistributionManager {
100
102
  await Promise.all(handlePromises);
101
103
 
102
104
  // update indexdb
103
- await this.saveDistribution(distribution);
105
+ await this.saveDistribution(distribution, false);
104
106
  nextData = await next();
105
107
  }
106
108
 
107
109
  // We cannot distinguish between revokedStake and stake from tx receipts here,
108
110
  // so we need to read all stake transactions and recalculate token distribution based on their revokeTokens and tokens
109
111
  await this.splitStake(distribution, force);
110
- await this.saveDistribution(distribution);
112
+ await this.saveDistribution(distribution, false);
111
113
 
112
114
  const result = createIndexedTokenDistribution(distribution);
113
115
 
@@ -120,20 +122,25 @@ class TokenDistributionManager {
120
122
  * Split out revokedStake / gasStake from stake
121
123
  *
122
124
  * @param {Object} distribution
123
- * @param {boolean} force If force is false, only process transactions after txTime in indexdb. Default is false
124
125
  * @returns {Promise<Object>}
125
126
  */
126
- async splitStake(distribution, force) {
127
+ async splitStake(distribution) {
128
+ const { logger } = this.resolver;
127
129
  const { tokenAddress } = distribution;
128
130
 
129
- const { next } = await this.resolver.listStakeChunks({
130
- timeFilter: !force ? { startDateTime: distribution.txTime } : {},
131
- });
131
+ const { next } = await this.resolver.listStakeChunks();
132
132
 
133
133
  let nextData = await next();
134
134
 
135
135
  // Process transactions in chunks and update indexdb
136
136
  while (nextData.length) {
137
+ logger?.info('Updating stake distribution in chunks', {
138
+ chunkSize: nextData.length,
139
+ startTime: nextData[0].renaissanceTime,
140
+ startAddress: nextData[0].address,
141
+ endTime: nextData[nextData.length - 1].renaissanceTime,
142
+ });
143
+
137
144
  nextData.forEach((stakeState) => {
138
145
  const isGasStake = this.isGasStake(stakeState);
139
146
  const token = stakeState.tokens.find((x) => x.address === tokenAddress);
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.19.4",
6
+ "version": "1.19.5",
7
7
  "description": "GraphQL resolver built upon ocap statedb and GQL layer",
8
8
  "main": "lib/index.js",
9
9
  "files": [
@@ -22,18 +22,18 @@
22
22
  "jest": "^29.7.0"
23
23
  },
24
24
  "dependencies": {
25
- "@arcblock/did": "1.19.4",
26
- "@arcblock/did-util": "1.19.4",
27
- "@arcblock/validator": "1.19.4",
28
- "@ocap/config": "1.19.4",
29
- "@ocap/indexdb": "1.19.4",
30
- "@ocap/mcrypto": "1.19.4",
31
- "@ocap/message": "1.19.4",
32
- "@ocap/state": "1.19.4",
33
- "@ocap/tx-protocols": "1.19.4",
34
- "@ocap/util": "1.19.4",
25
+ "@arcblock/did": "1.19.5",
26
+ "@arcblock/did-util": "1.19.5",
27
+ "@arcblock/validator": "1.19.5",
28
+ "@ocap/config": "1.19.5",
29
+ "@ocap/indexdb": "1.19.5",
30
+ "@ocap/mcrypto": "1.19.5",
31
+ "@ocap/message": "1.19.5",
32
+ "@ocap/state": "1.19.5",
33
+ "@ocap/tx-protocols": "1.19.5",
34
+ "@ocap/util": "1.19.5",
35
35
  "debug": "^4.3.6",
36
36
  "lodash": "^4.17.21"
37
37
  },
38
- "gitHead": "9b026c7ad59839ac1242a68b24e18b3a1534918d"
38
+ "gitHead": "9f93acb129f6fee316149f3921a98b88dcccfac3"
39
39
  }