Skip to content

Commit 756bd30

Browse files
committed
perf: cache getTransaction result when sync in indexer mode
1 parent c5b5c86 commit 756bd30

File tree

6 files changed

+85
-13
lines changed

6 files changed

+85
-13
lines changed

packages/neuron-wallet/src/listeners/tx-status.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,12 @@ const trackingStatus = async () => {
7373
const transaction = successTx.tx
7474
const { blockHash } = successTx
7575
const blockHeader = await getBlockService.getHeader(blockHash!)
76-
transaction.blockHash = blockHash!
77-
transaction.blockNumber = blockHeader.number
78-
transaction.timestamp = blockHeader.timestamp
79-
await TransactionPersistor.saveFetchTx(transaction)
76+
if (blockHeader) {
77+
transaction.blockHash = blockHash!
78+
transaction.blockNumber = blockHeader.number
79+
transaction.timestamp = blockHeader.timestamp
80+
await TransactionPersistor.saveFetchTx(transaction)
81+
}
8082
}
8183
}
8284
}

packages/neuron-wallet/src/services/indexer/queue.ts

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Subject, Subscription } from 'rxjs'
22
import Utils from 'services/sync/utils'
33
import logger from 'utils/logger'
44
import GetBlocks from 'services/sync/get-blocks'
5-
import { Transaction } from 'types/cell-types'
5+
import { Transaction, TransactionWithStatus } from 'types/cell-types'
66
import TypeConvert from 'types/type-convert'
77
import BlockNumber from 'services/sync/block-number'
88
import AddressesUsedSubject from 'models/subjects/addresses-used-subject'
@@ -13,6 +13,7 @@ import IndexerTransaction from 'services/tx/indexer-transaction'
1313
import IndexerRPC from './indexer-rpc'
1414
import HexUtils from 'utils/hex'
1515
import { TxUniqueFlagCache } from './tx-unique-flag'
16+
import { TransactionCache } from './transaction-cache'
1617
import TransactionEntity from 'database/chain/entities/transaction'
1718

1819
export interface LockHashInfo {
@@ -43,6 +44,7 @@ export default class IndexerQueue {
4344
private resetFlag = false
4445

4546
private latestCreatedBy: TxUniqueFlagCache = new TxUniqueFlagCache(100)
47+
private txCache: TransactionCache = new TransactionCache(100)
4648

4749
private url: string
4850

@@ -123,6 +125,7 @@ export default class IndexerQueue {
123125
const result = await this.getBlocksService.getTransaction(tx.hash)
124126
if (!result) {
125127
await IndexerTransaction.deleteTxWhenFork(tx.hash)
128+
this.txCache.delete(tx.hash)
126129
} else if (tip - BigInt(tx.blockNumber) >= 1000) {
127130
await IndexerTransaction.confirm(tx.hash)
128131
}
@@ -157,6 +160,16 @@ export default class IndexerQueue {
157160
})
158161
}
159162

163+
public getTransaction = async (txHash: string): Promise<TransactionWithStatus> => {
164+
let txWithStatus = this.txCache.get(txHash)
165+
if (!txWithStatus) {
166+
const transactionWithStatus = await this.getBlocksService.getTransaction(txHash)
167+
txWithStatus = TypeConvert.toTransactionWithStatus(transactionWithStatus)
168+
this.txCache.push(txWithStatus)
169+
}
170+
return txWithStatus
171+
}
172+
160173
// type: 'createdBy' | 'consumedBy'
161174
public pipeline = async (lockHash: string, type: TxPointType, startBlockNumber: bigint) => {
162175
let page = 0
@@ -180,9 +193,8 @@ export default class IndexerQueue {
180193
txPoint &&
181194
(BigInt(txPoint.blockNumber) >= startBlockNumber || this.tipBlockNumber - BigInt(txPoint.blockNumber) < 1000)
182195
) {
183-
const transactionWithStatus = await this.getBlocksService.getTransaction(txPoint.txHash)
184-
const ckbTransaction: CKBComponents.Transaction = transactionWithStatus.transaction
185-
const transaction: Transaction = TypeConvert.toTransaction(ckbTransaction)
196+
const transactionWithStatus = await this.getTransaction(txPoint.txHash)
197+
const transaction: Transaction = transactionWithStatus.transaction
186198
const txUniqueFlag = {
187199
txHash: transaction.hash,
188200
blockHash: transactionWithStatus.txStatus.blockHash!
@@ -210,9 +222,11 @@ export default class IndexerQueue {
210222
const { blockHash } = transactionWithStatus.txStatus
211223
if (blockHash) {
212224
const blockHeader = await this.getBlocksService.getHeader(blockHash)
213-
transaction.blockHash = blockHash
214-
transaction.blockNumber = blockHeader.number
215-
transaction.timestamp = blockHeader.timestamp
225+
if (blockHeader) {
226+
transaction.blockHash = blockHash
227+
transaction.blockNumber = blockHeader.number
228+
transaction.timestamp = blockHeader.timestamp
229+
}
216230
}
217231
txEntity = await TransactionPersistor.saveFetchTx(transaction)
218232
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { TransactionWithStatus } from "types/cell-types"
2+
3+
export class TransactionCache {
4+
private limit: number
5+
6+
private store = new Map<string, TransactionWithStatus>()
7+
8+
constructor(limit: number) {
9+
this.limit = limit
10+
}
11+
12+
public push(value: TransactionWithStatus) {
13+
const key = value.transaction.hash
14+
15+
if (this.store.has(key)) {
16+
return
17+
}
18+
this.store.set(key, value)
19+
if (this.store.size > this.limit) {
20+
const firstKey = Array.from(this.store.keys())[0]
21+
this.store.delete(firstKey)
22+
}
23+
}
24+
25+
public get(key: string): TransactionWithStatus | undefined {
26+
return this.store.get(key)
27+
}
28+
29+
public delete(key: string): boolean {
30+
return this.store.delete(key)
31+
}
32+
}

packages/neuron-wallet/src/services/sync/get-blocks.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,12 @@ export default class GetBlocks {
8282
return await this.core.rpc.getTransaction(hash)
8383
}
8484

85-
public getHeader = async (hash: string): Promise<BlockHeader> => {
85+
public getHeader = async (hash: string): Promise<BlockHeader | undefined> => {
8686
const result = await this.core.rpc.getHeader(hash)
87-
return TypeConvert.toBlockHeader(result)
87+
if (result) {
88+
return TypeConvert.toBlockHeader(result)
89+
}
90+
return undefined
8891
}
8992

9093
public getBlockByNumber = async (num: string): Promise<Block> => {

packages/neuron-wallet/src/types/cell-types.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,16 @@ export interface Transaction extends TransactionWithoutHash {
5757
hash: string
5858
}
5959

60+
export interface TxStatus {
61+
blockHash: string | null
62+
status: 'pending' | 'proposed' | 'committed'
63+
}
64+
65+
export interface TransactionWithStatus {
66+
transaction: Transaction
67+
txStatus: TxStatus
68+
}
69+
6070
export interface Input {
6171
previousOutput: OutPoint | null
6272
since?: string

packages/neuron-wallet/src/types/type-convert.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import HexUtils from 'utils/hex';
2+
import { TransactionWithStatus } from './cell-types';
23
import {
34
Block,
45
BlockHeader,
@@ -51,6 +52,16 @@ export default class TypeConvert {
5152
return tx
5253
}
5354

55+
static toTransactionWithStatus(transactionWithStatus: CKBComponents.TransactionWithStatus): TransactionWithStatus {
56+
return {
57+
transaction: TypeConvert.toTransaction(transactionWithStatus.transaction),
58+
txStatus: {
59+
blockHash: transactionWithStatus.txStatus.blockHash,
60+
status: transactionWithStatus.txStatus.status,
61+
}
62+
}
63+
}
64+
5465
static toCellDep(cellDep: CKBComponents.CellDep): CellDep {
5566
return {
5667
outPoint: cellDep.outPoint,

0 commit comments

Comments
 (0)