Giter Club home page Giter Club logo

polkastats-backend-v3's Introduction

PolkaStats Backend v3

New improved backend for https://polkastats.io!

This repository is ARCHIVED, for latest version go to https://github.com/polkastats/polkastats

Table of Contents

Installation Instructions

git clone https://github.com/Colm3na/polkastats-backend-v3.git
cd polkastats-backend-v3
npm install

Usage Instructions

To launch all docker containers at once:

npm run docker

To run them separately:

npm run docker:<container-name>

List of current containers

  • substrate-node
  • postgres
  • graphql-engine
  • crawler
  • phragmen (temporarily disabled)

Updating containers

git pull
npm run docker:clean
npm run docker:build
npm run docker

Crawler

This crawler container listens to new blocks and fills the database. There are a number of processes executed within this container. Some of this processes are triggered based on time configuration that can be seen in this file: backend.config.js The crawler is able to detect and fill the gaps in postgres database by harvesting all the missing data, so it's safe and resilience against node outages or restarts.

Phragmen

This container includes an offline-phragmen binary. It is a forked modification of Kianenigma repository.

Hasura demo

The crawler needs to wait for your substrate-node container to get synced before starting to collect data. You can use an already synced external RPC for instant testing by changing the environment variable WS_PROVIDER_URL in docker-compose.yml file:

crawler:
  image: polkastats-backend:latest
  build:
    context: ../../
    dockerfile: ./docker/polkastats-backend/backend/Dockerfile
  depends_on:
    - "postgres"
    - "substrate-node"
  restart: on-failure
  environment:
    - NODE_ENV=production
    - WS_PROVIDER_URL=wss://kusama-rpc.polkadot.io # Change this line

Just uncomment out the first one and comment the second and rebuild the dockers.

npm run docker:clean
npm run docker

Then browse to http://localhost:8082

Click on "Data" at the top menu

Then add all tables to the tracking process

From now on, hasura will be collecting and tracking all the changes in the data base.

In order to check it and see its power you could start a new subscription or just perform an example query such us this one:

Query example. Static

  • Block query example:
query {
  block  {
    block_hash
    block_author
    block_number
    block_author_name
    current_era
    current_index
    new_accounts
    session_length
    session_per_era
    session_progress
  }
}
  • Rewards query example:
query {
  rewards {
    era_index
    era_rewards
    stash_id
    timestamp
  }
}
  • Validator by number of nominators example:
query {
  validator_num_nominators {
    block_number
    nominators
    timestamp
  }
}
  • Account query example:
query {
  account {
    account_id
    balances
    identity
  }
}

Subscription example. Dynamic

  • Block subscription example:
subscription {
  block {
    block_number
    block_hash
    current_era
    current_index
  }
}
  • Validator active subscription example:
subscription MySubscription {
	validator_active {
    account_id
    active
    block_number
    session_index
    timestamp
  }
}
  • Account subscription example:
subscription MySubscription {
  account {
    account_id
    balances
  }
}

Configuration

You can customize your configuration through the following environment variables:

Substrate

Env name Description Default Value
WS_PROVIDER_URL Substrate node to use ws://substrate-node:9944

Database

Env name Description Default Value
POSTGRES_USER PostgreSQL username polkastats
POSTGRES_PASSWORD PostgreSQL user password polkastats
POSTGRES_HOST PostgreSQL host postgres
POSTGRES_PORT PostgreSQL port 5432
POSTGRES_DATABASE PostgreSQL database name polkastats

Crawlers

Env name Description Default Value
CRAWLER_BLOCK_LISTENER_POLLING_TIME_MS Polling time for block listener (ms) 60000
CRAWLER_ACTIVE_ACCOUNTS_POLLING_TIME_MS Polling time for accounts crawler (ms) 600000
CRAWLER_PHRAGMEN_POLLING_TIME_MS Polling time for phragmen executions (ms) 300000
CRAWLER_PHRAGMEN_OUTPUT_DIR Directory to store the phgramen JSON result /tmp/phragmen
CRAWLER_PHRAGMEN_BINARY_PATH Path to the phragmen executable /usr/app/polkastats-backend-v3/offline-phragme

You can also disable specific crawlers with the following environment variables:

  • CRAWLER_SYSTEM_DISABLE
  • CRAWLER_BLOCK_LISTENER_DISABLE
  • CRAWLER_BLOCK_HARVESTER_DISABLE
  • CRAWLER_STAKING_DISABLE
  • CRAWLER_ACTIVE_ACCOUNTS_DISABLE
  • CRAWLER_CHAIN_DISABLE
  • CRAWLER_ERA_LISTENER_DISABLE
  • CRAWLER_PHRAGMEN_DISABLE

For instance, if you want to disable phgramen crawler just set CRAWLER_PHRAGMEN_DISABLE=true.

polkastats-backend-v3's People

Contributors

aitorjs avatar bigomby avatar bitcoinera avatar dependabot[bot] avatar derfredy avatar mariopino avatar scriptonita avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

polkastats-backend-v3's Issues

Bug in staking crawler

crawler_1         | [PolkaStats backend v3] - Staking crawler - Storing intentions staking info at block #1516549 (session #2684)
crawler_1         | (node:18) UnhandledPromiseRejectionWarning: Error: staking.validators(AccountId) is a map, requiring 1 argument, 0 found
crawler_1         |     at assert (/usr/app/polkastats-backend-v3/node_modules/@polkadot/util/assert.js:34:11)
crawler_1         |     at doMap (/usr/app/polkastats-backend-v3/node_modules/@polkadot/api/util/validate.js:35:217)
crawler_1         |     at extractStorageArgs (/usr/app/polkastats-backend-v3/node_modules/@polkadot/api/util/validate.js:48:12)
crawler_1         |     at getArgs (/usr/app/polkastats-backend-v3/node_modules/@polkadot/api/base/Decorate.js:282:67)
crawler_1         |     at decorated.hasSubscriptions.creator.iterKey.creator.meta.type.isMap.creator.meta.type.asMap.linked.isTrue.decorateMethod.methodName (/usr/app/polkastats-backend-v3/node_modules/@polkadot/api/base/Decorate.js:286:24)
crawler_1         |     at Object.validators (/usr/app/polkastats-backend-v3/node_modules/@polkadot/api/promise/Api.js:78:14)
crawler_1         |     at Object.storeStakingInfo (/usr/app/polkastats-backend-v3/lib/crawlers/staking.js:192:57)
crawler_1         |     at processTicksAndRejections (internal/process/task_queues.js:97:5)
crawler_1         |     at async SafeSubscriber._next (/usr/app/polkastats-backend-v3/lib/crawlers/staking.js:42:11)
crawler_1         | (node:18) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)

Log improvements

We can do a few tweaks to improve our logs:

  • Add datetime in ISO format.
  • Simplify crawler name to single word tags (#accounts, #phragmen, #staking, #harvester, #listener and #rewards)

Duplicate keys in block harvester and listener

It seems the logic in these crawlers is not adjusted enough. Sometimes the crawlers try to store the same duplicated element in the DB, resulting in an ugly duplicate keys error.

The fix is actually to effectively prevent these duplicates from trying being stored, as the primary keys are correct.

Error in Block harvester:

image

Error in Block listener:

image

Especially easy to reproduce with a slow wifi network and at startup with the new backend structure ( #46 )

Use dotenv for configuration

We should aim for universal docker images. Currently, our docker image is built with (mostly) static configuration so the result image is not configurable. This renders the image unusable in others environments, since it has the configuration hardcoded.

Following docker good practices, we should avoid static configuration so we can change application parameters without rebuilding the image. Environment variables are the way to go.

In the Node.js ecosystem we have the dotenv package which allows us to merge environment variables with variables from a local file named .env.

Dockers should be able to build different git branches

The command "docker-compose up" now builds develop branch. It is hard coded inside Dockerfile located at docker/polkastats-backend/backend/Dockerfile

Possible solutions:

  • Environment variable inside docker-compose.yml
  • Read the branch name from current local cloned repo

...

Implement PolkaStats identity

Is your feature request related to a problem? Please describe.
We need to implement PolkaStats identity system, though we will use it only to get the logo image for validators.

Describe the solution you'd like
Just create the table identity and include current data taken from PolkaStats backend V2. That way we have that info available in Hasura.

Add startup delay to backend

Is your feature request related to a problem? Please describe.

This is needed to avoid problems on crawler startup when node is not yet available.

Describe the solution you'd like
Add startup delay of 15s to runCrawlers() func.

Add data for intention graphs

Is your feature request related to a problem? Please describe.

Fetch and store data in database for intention total bonded graph.

All validators are offline

Describe the bug
The validators table shows all validators offline.

Validator_staking.imOnline.isOnline is always false.

To Reproduce
Go to Hasura and get json from the staking validator.
Parse it to object
get imOnline.isOnline values.

Expected behavior
Some validators could be active.

Screenshots

Additional context

Save data for future validator graphs

We need to populate that tables for allow us to create cool charts for our future frontend v3 ^^

  • validator_bonded
  • validator_selfbonded
  • validator_num_nominators
  • validator_era_points
  • validator_active

IMO this should be done in the staking crawler for every sessión change (every hour), like the store of the staking info (in fact the data is already there).

Use proper logger instead console.log

Currently the application is using console.log for logging. We should avoid using it on production, instead a proper logger should be used.

I propose pino, which has good performance and outputs useful info for production environments and pretty logs in development environments.

Add restart always flag to substrate-node and crawler services in docker-compose

Is your feature request related to a problem? Please describe.

Sometimes the substrate node and especially the backend can stop due to an unhandled error. That services should be more resilient to failures.

Describe the solution you'd like
Add restart always flag to substrate-node and crawler services in docker-compose (postgres and graphql-engine services already have it).

Additional context
I'm getting out of memory error in the crawler sometimes, we need this asap meanwhile we debug the possible memory leak.

Add system table

Is your feature request related to a problem? Please describe.

We need to add system table to store client information:

  • Client version
  • Finalized block height

Add block counters

We need to add some block counters. This should be done in blockListener and blockHarvester crawlers.

Counter list (per block):

  • Total events
  • Total balance transfers
  • New accounts

Edge case. Failure of harverster when nothing to do

Sometimes after harverster docker start you see this log:

[PolkaStats backend v3] - Block harvester - Detected gap! Harvest blocks from #0 to #0
[PolkaStats backend v3] - Block harvester - Error adding block #0: error: duplicate key value violates unique constraint "block_pkey"
at Connection.parseE (/usr/app/polkastats-backend-v3/node_modules/pg/lib/connection.js:614:13)
at Connection.parseMessage (/usr/app/polkastats-backend-v3/node_modules/pg/lib/connection.js:413:19)
at Socket. (/usr/app/polkastats-backend-v3/node_modules/pg/lib/connection.js:129:22)
at Socket.emit (events.js:223:5)
at addChunk (_stream_readable.js:309:12)
at readableAddChunk (_stream_readable.js:290:11)
at Socket.Readable.push (_stream_readable.js:224:10)
at TCP.onStreamRead (internal/stream_base_commons.js:181:23)
[PolkaStats backend v3] - Block harvester - Total execution time: 6s

It seems to happen when nothing to do. It finds a gap between block 0 and 0, what does not make sense.

Error adding event duplicate key in block listener

Describe the bug

Error adding event duplicate key in block listener:

crawler_1         | [PolkaStats backend v3] - Block listener - Error adding event #1521996-0: error: duplicate key value violates unique constraint "event_pkey", sql: INSERT INTO event (
crawler_1         |               block_number,
crawler_1         |               event_index,
crawler_1         |               section,
crawler_1         |               method,
crawler_1         |               phase,
crawler_1         |               data
crawler_1         |             ) VALUES (
crawler_1         |               '1521996',
crawler_1         |               '0',
crawler_1         |               'system',
crawler_1         |               'ExtrinsicSuccess',
crawler_1         |               '{"ApplyExtrinsic":0}',
crawler_1         |               '[{"weight":10000,"class":"Operational","paysFee":true}]'
crawler_1         |             );

Allow crawlers to be disabled

Is your feature request related to a problem? Please describe.

There is no simple way to prevent some crawlers for being executed. It would be nice to have some way to disable misbehaving crawlers o just disable a specific crawler during development.

Describe the solution you'd like

A way to disable specific crawlers through config.

Describe alternatives you've considered

The current alternative is to comment crawlers code.

Additional context

Error in blockHarvester

Describe the bug

We need to update queries to fix it.

crawler_1         | [PolkaStats backend v3] - Starting block harvester...
crawler_1         | [PolkaStats backend v3] - Block harvester - Detected gap! Harvesting blocks from #1516547 to #0
crawler_1         | [PolkaStats backend v3] - Block harvester - => Adding event #1516547-0 system => ExtrinsicSuccess
crawler_1         | [PolkaStats backend v3] - Block harvester - => Adding event #1516547-1 system => ExtrinsicSuccess
crawler_1         | (node:18) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'at' of undefined
crawler_1         |     at Object.harvestBlocks (/usr/app/polkastats-backend-v3/lib/crawlers/blockHarvester.js:126:95)
crawler_1         |     at runMicrotasks (<anonymous>)
crawler_1         |     at processTicksAndRejections (internal/process/task_queues.js:97:5)
crawler_1         |     at async Object.start (/usr/app/polkastats-backend-v3/lib/crawlers/blockHarvester.js:46:9)
crawler_1         | (node:18) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 3)

Disable phragmen crawler

offline-phragmen is currently broken so we should disable it before deliver Milestone 1. As discussed with @Bigomby and @derfredy the crawler is tested and was saving data to DB before recent runtime upgrade. Enable it to save data again is straightforward once we get a working version!

Deliverable Milestone 1

Find here all sub tasks needed to accomplish our commitments for Milestone 1

As we stated here

"Deliverables in this milestone will be dockerized. We will also include a README to run the development container. The container will include the PosgresSQL data base, the Crawlers and Hasura."

  • Documentation to build Milestone 1 demo
  • Dockers

Dockerize phragmem-offline crawler

phragmem-offline crawler needs to be dockerize using a different strategy since it depends on a Rust binary that should be compiled during the build process.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.