Skip to content

Commit

Permalink
Merge pull request #186 from utxostack/perf/cache
Browse files Browse the repository at this point in the history
perf: add cacheable decorator to CKB RPC service & Bitcoin API
  • Loading branch information
ahonn authored Sep 23, 2024
2 parents 955fa61 + 9e85046 commit 39d9d7c
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 81 deletions.
5 changes: 5 additions & 0 deletions backend/src/core/bitcoin-api/bitcoin-api.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,11 @@ export class BitcoinApiService {
return this.call('getTxOutSpends', { txid });
}

@Cacheable({
namespace: 'bitcoinApiService',
key: ({ txids }) => `getTransactionTimes:${txids.join(',')}`,
ttl: 10_000,
})
public async getTransactionTimes({ txids }: { txids: string[] }) {
return this.call('getTransactionTimes', { txids });
}
Expand Down
7 changes: 1 addition & 6 deletions backend/src/core/blockchain/blockchain.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,12 +258,7 @@ export class BlockchainService {
this.logger.debug(
`get_transactions - searchKey: ${JSON.stringify(searchKey)}, order: ${order}, limit: ${limit}, after: ${after}`,
);
const result = await this.websocket.call('get_transactions', [
searchKey,
order,
limit,
after,
]);
const result = await this.websocket.call('get_transactions', [searchKey, order, limit, after]);
const transactions = result as GetTransactionsResult;
return transactions;
}
Expand Down
78 changes: 19 additions & 59 deletions backend/src/core/ckb-explorer/ckb-explorer.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,10 @@ import {
AddressInfo,
AddressTransactionSortType,
Block,
BlockList,
BlockSortType,
CkbExplorerResponse,
DetailTransaction,
NonPaginatedResponse,
PaginatedResponse,
RgbppDigest,
RgbppTransaction,
Transaction,
TransactionSortType,
Expand All @@ -21,7 +18,6 @@ import {
Statistics,
TransactionFeesStatistic,
TransactionListSortType,
TransactionListItem,
} from './ckb-explorer.interface';
import { ONE_MONTH_MS } from 'src/common/date';
import { CACHE_MANAGER, Cache } from '@nestjs/cache-manager';
Expand All @@ -44,10 +40,6 @@ export type GetAddressTransactionsParams = BasePaginationParams & {
sort?: AddressTransactionSortType;
};

type GetBlockListParams = BasePaginationParams & {
sort?: BlockSortType;
};

type GetRgbppTransactionsParams = BasePaginationParams & {
sort?: TransactionSortType;
leapDirection?: 'in' | 'out';
Expand All @@ -64,10 +56,6 @@ type GetXUDTTransactionsParams = BasePaginationParams & {
addressHash?: string;
};

type GetTransactionListParams = BasePaginationParams & {
sort?: 'height.desc' | 'height.asc';
};

@Injectable()
export class CkbExplorerService {
private logger = new Logger(CkbExplorerService.name);
Expand Down Expand Up @@ -119,6 +107,12 @@ export class CkbExplorerService {
return response.data;
}

@Cacheable({
namespace: 'CkbExplorerService',
key: (address: string, sort, page = 1, pageSize = 10) =>
`getAddressTransactions:${address},${sort},${page},${pageSize}`,
ttl: 10_000,
})
public async getAddressTransactions({
address,
sort,
Expand All @@ -135,17 +129,6 @@ export class CkbExplorerService {
return response.data;
}

public async getBlockList({
page = 1,
pageSize = 10,
sort = BlockSortType.HeightDesc,
}: GetBlockListParams = {}): Promise<PaginatedResponse<BlockList>> {
const response = await this.request.get(
`/v1/blocks?page=${page}&page_size=${pageSize}&sort=${sort}`,
);
return response.data;
}

@Cacheable({
namespace: 'CkbExplorerService',
key: (heightOrHash: string) => `getBlock:${heightOrHash}`,
Expand All @@ -162,20 +145,10 @@ export class CkbExplorerService {

@Cacheable({
namespace: 'CkbExplorerService',
key: (heightOrHash: string, { page = 1, pageSize = 10 }: BasePaginationParams = {}) =>
`getBlockTransactions:${heightOrHash},${page},${pageSize}`,
ttl: ONE_MONTH_MS,
key: (address: string, leapDirection, page = 1, pageSize = 10) =>
`getRgbppTransactions:${address},${page},${pageSize},${leapDirection}`,
ttl: 10_000,
})
public async getBlockTransactions(
blockHash: string,
{ page = 1, pageSize = 10 }: BasePaginationParams = {},
): Promise<PaginatedResponse<Transaction>> {
const response = await this.request.get(
`/v1/block_transactions/${blockHash}?page=${page}&page_size=${pageSize}`,
);
return response.data;
}

public async getRgbppTransactions({
sort = TransactionSortType.NumberDesc,
page = 1,
Expand Down Expand Up @@ -231,31 +204,12 @@ export class CkbExplorerService {
return response.data;
}

public async getTransactionList({
page = 1,
pageSize = 10,
sort = 'height.desc',
}: GetTransactionListParams): Promise<PaginatedResponse<TransactionListItem>> {
const response = await this.request.get('/v1/transactions', {
params: {
page,
page_size: pageSize,
sort,
},
});
return response.data;
}

@Cacheable({
namespace: 'CkbExplorerService',
key: (txHash: string) => `getRgbppDigest:${txHash}`,
ttl: ONE_MONTH_MS,
key: (address: string, tags, sort, page = 1, pageSize = 10) =>
`getXUDTList:${address},${tags.join('|')},${sort},${page},${pageSize}`,
ttl: 10_000,
})
public async getRgbppDigest(txHash: string): Promise<CkbExplorerResponse<RgbppDigest>> {
const response = await this.request.get(`/v2/ckb_transactions/${txHash}/rgb_digest`);
return response.data;
}

public async getXUDTList({
symbol,
tags,
Expand Down Expand Up @@ -284,6 +238,12 @@ export class CkbExplorerService {
return response.data;
}

@Cacheable({
namespace: 'CkbExplorerService',
key: (typeHash: string, { page = 1, pageSize = 10, txHash, addressHash }) =>
`getXUDTTransactions:${typeHash},${page},${pageSize},${txHash},${addressHash}`,
ttl: 10_000,
})
public async getXUDTTransactions(
typeHash: string,
{ page = 1, pageSize = 10, txHash, addressHash }: GetXUDTTransactionsParams = {},
Expand All @@ -308,7 +268,7 @@ export class CkbExplorerService {
key: 'getStatistics',
// Same as the ckb explorer frontend
// https://github.com/nervosnetwork/ckb-explorer-frontend/blob/develop/src/constants/common.ts#L3
ttl: 4000,
ttl: 4_000,
})
public async getStatistics(): Promise<NonPaginatedResponse<Statistics>> {
const response = await this.request.get('/v1/statistics');
Expand Down
6 changes: 0 additions & 6 deletions backend/src/middlewares/field-performance.middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,14 @@ export const fieldPerformanceMiddleware: FieldMiddleware = async (
next: NextFn,
) => {
const now = performance.now();
const memoryUsageNow = process.memoryUsage();

const value = await next();

const executionTime = performance.now() - now;
const memoryUsage = process.memoryUsage().heapUsed - memoryUsageNow.heapUsed;

Sentry.setContext('graphql', {
executionTime,
memoryUsage,
field: ctx.info.fieldName,
parent: ctx.info.parentType.name,
});
Sentry.setMeasurement('graphql.executionTime', executionTime, 'millisecond');
Sentry.setMeasurement('graphql.memoryUsage', memoryUsage, 'byte');
return value;
};
10 changes: 0 additions & 10 deletions backend/src/modules/ckb/block/block.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@ export class CkbBlockService {
private ckbRpcService: CkbRpcWebsocketService,
) {}

public async getLatestBlockNumbers(): Promise<string[]> {
const blockList = await this.ckbExplorerService.getBlockList();
return blockList.data.map((block) => block.attributes.number);
}

public async getBlockFromRpc(heightOrHash: string): Promise<CkbRpc.Block> {
if (heightOrHash.startsWith('0x')) {
return await this.ckbRpcService.getBlock(heightOrHash);
Expand All @@ -31,9 +26,4 @@ export class CkbBlockService {
public async getBlockEconomicState(blockHash: string): Promise<CkbRpc.BlockEconomicState> {
return await this.ckbRpcService.getBlockEconomicState(blockHash);
}

public async getBlockTransactions(blockHash: string): Promise<CkbExplorer.Transaction[]> {
const blockTransactions = await this.ckbExplorerService.getBlockTransactions(blockHash);
return blockTransactions.data.map((transaction) => transaction.attributes);
}
}

0 comments on commit 39d9d7c

Please sign in to comment.