From 8a24294eb686522c10b2d869c243fde6d51e5f52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ph=E1=BA=A1m=20Th=C3=A0nh=20Phong?= <49814372+phamphong9981@users.noreply.github.com> Date: Thu, 12 Sep 2024 11:29:40 +0700 Subject: [PATCH] feat: material view erc721 holder statistic (#896) * feat: material view erc721 holder statistic * refactor: index * refactor: review --- ci/config.json.ci | 4 ++- config.json | 4 ++- ...05021812_m_view_erc721_holder_statistic.ts | 21 ++++++++++++++ src/services/evm/constant.ts | 1 + src/services/evm/erc721.service.ts | 29 +++++++++++++++++++ 5 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 migrations/evm/20240905021812_m_view_erc721_holder_statistic.ts diff --git a/ci/config.json.ci b/ci/config.json.ci index c6972e44d..006513ba5 100644 --- a/ci/config.json.ci +++ b/ci/config.json.ci @@ -421,7 +421,9 @@ "chunkSizeInsert": 1000, "mediaPerBatch": 10, "concurrencyHandleTokenMedia": 10, - "timeRefreshErc721Stats": "1 * * * *" + "timeRefreshErc721Stats": "1 * * * *", + "timeRefreshMViewErc721HolderStats": "*/10 * * * *", + "statementTimeout": 600000 }, "jobRefreshMViewAccountBalanceStatistic": { "timeRefreshMViewAccountBalanceStatistic": "*/10 * * * *" diff --git a/config.json b/config.json index 86f99b299..e2e103e8c 100644 --- a/config.json +++ b/config.json @@ -419,7 +419,9 @@ "chunkSizeInsert": 500, "mediaPerBatch": 10, "concurrencyHandleTokenMedia": 10, - "timeRefreshErc721Stats": "1 * * * *" + "timeRefreshErc721Stats": "1 * * * *", + "timeRefreshMViewErc721HolderStats": "*/10 * * * *", + "statementTimeout": 600000 }, "crawlEvmProxyHistory": { "key": "crawlEvmProxyHistory", diff --git a/migrations/evm/20240905021812_m_view_erc721_holder_statistic.ts b/migrations/evm/20240905021812_m_view_erc721_holder_statistic.ts new file mode 100644 index 000000000..12496c414 --- /dev/null +++ b/migrations/evm/20240905021812_m_view_erc721_holder_statistic.ts @@ -0,0 +1,21 @@ +import { Knex } from 'knex'; +import config from '../../config.json' assert { type: 'json' }; +export async function up(knex: Knex): Promise { + await knex.raw(`set statement_timeout to ${config.erc721.statementTimeout}`); + await knex.raw(` + CREATE MATERIALIZED VIEW m_view_erc721_holder_statistic AS + select count(*), erc721_token.owner, erc721_token.erc721_contract_address + from erc721_token + group by erc721_token.owner, erc721_token.erc721_contract_address; + CREATE INDEX m_view_erc721_holder_statistic_owner_index + ON m_view_erc721_holder_statistic (owner); + CREATE INDEX m_view_erc721_holder_statistic_erc721_contract_address_count_index + ON m_view_erc721_holder_statistic (erc721_contract_address, count); +`); +} + +export async function down(knex: Knex): Promise { + await knex.schema.dropMaterializedViewIfExists( + 'm_view_erc721_holder_statistic' + ); +} diff --git a/src/services/evm/constant.ts b/src/services/evm/constant.ts index e107b7768..0dc717a69 100644 --- a/src/services/evm/constant.ts +++ b/src/services/evm/constant.ts @@ -293,6 +293,7 @@ export const BULL_JOB_NAME = { INSERT_VERIFY_BY_CODEHASH: 'job:insert-verify-by-codehash', HANDLE_SELF_DESTRUCT: 'handle:self-destruct', REINDEX_ERC20: 'reindex:erc20', + REFRESH_ERC721_HOLDER_STATISTIC: 'refresh:erc721-holder-statistic', }; export const MSG_TYPE = { diff --git a/src/services/evm/erc721.service.ts b/src/services/evm/erc721.service.ts index d47c123cc..b561549a5 100644 --- a/src/services/evm/erc721.service.ts +++ b/src/services/evm/erc721.service.ts @@ -278,6 +278,21 @@ export default class Erc721Service extends BullableService { this.logger.info(`Reindex erc721 contract ${address} done.`); } + @QueueHandler({ + queueName: BULL_JOB_NAME.REFRESH_ERC721_HOLDER_STATISTIC, + jobName: BULL_JOB_NAME.REFRESH_ERC721_HOLDER_STATISTIC, + }) + public async refreshErc721HolderStatistic(): Promise { + await knex.transaction(async (trx) => { + await knex + .raw(`set statement_timeout to ${config.erc721.statementTimeout}`) + .transacting(trx); + await knex.schema + .refreshMaterializedView('m_view_erc721_holder_statistic') + .transacting(trx); + }); + } + @Action({ name: SERVICE.V1.Erc721.insertNewErc721Contracts.key, params: { @@ -535,6 +550,20 @@ export default class Erc721Service extends BullableService { }, } ); + await this.createJob( + BULL_JOB_NAME.REFRESH_ERC721_HOLDER_STATISTIC, + BULL_JOB_NAME.REFRESH_ERC721_HOLDER_STATISTIC, + {}, + { + removeOnComplete: true, + removeOnFail: { + count: 3, + }, + repeat: { + pattern: config.erc721.timeRefreshMViewErc721HolderStats, + }, + } + ); } return super._start(); }