Files
pezkuwi-subquery/docker-compose.prod.yml
T
SatoshiQaziMuhammed cb25e08547 noter: report a scan group in one batch, count progress as liveness (#34)
The first scan after the Zagros People upgrade re-confirmed all 98
accounts, one transaction per account, a block each. It ran past the
15-minute staleness window and the watchdog killed it halfway; the next
interval had meanwhile started a second scan beside it, which read the
same accounts before the first one's reports landed and sent them again
(124 submissions for 98 accounts). On mainnet every tracked citizen's
re-confirmation falls due in the same scan, every three days.

- A scan group's updates go out as one utility.forceBatch. The accounts
  are unrelated, so one refused report no longer takes the others with
  it; each refused item is logged with its decoded error.
- The heartbeat records progress -- a group read and, if it had anything
  to report, reported -- instead of a finished scan. A group that cannot
  be read, or whose report is refused outright, is not progress, so a
  mute noter still goes stale.
- A periodic scan does not start while the previous one is running.
2026-10-20 10:25:57 +04:00

227 lines
6.7 KiB
YAML

services:
postgres:
container_name: postgres-pezkuwi
image: postgres:16-alpine
ports:
- 5432:5432
volumes:
- pgdata:/var/lib/postgresql/data
- ./docker/init:/docker-entrypoint-initdb.d
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 10
environment:
POSTGRES_PASSWORD: pezkuwi_subquery_2024
restart: always
subquery-node-relay:
container_name: node-pezkuwi-relay
build:
context: .
dockerfile: docker/Dockerfile.node
depends_on:
postgres: { condition: service_healthy }
restart: always
environment:
TZ: UTC
DB_USER: postgres
DB_PASS: pezkuwi_subquery_2024
DB_DATABASE: postgres
DB_HOST: postgres
DB_PORT: 5432
volumes:
- ./:/app/project
command:
- -f=/app/project/pezkuwi.yaml
- --db-schema=subquery-pezkuwi-staking
- --disable-historical=true
- --batch-size=30
subquery-node-assethub:
container_name: node-pezkuwi-assethub
build:
context: .
dockerfile: docker/Dockerfile.node
depends_on:
postgres: { condition: service_healthy }
restart: always
environment:
TZ: UTC
DB_USER: postgres
DB_PASS: pezkuwi_subquery_2024
DB_DATABASE: postgres
DB_HOST: postgres
DB_PORT: 5432
volumes:
- ./:/app/project
command:
- -f=/app/project/pezkuwi-assethub.yaml
- --db-schema=subquery-pezkuwi-assethub
- --disable-historical=true
- --batch-size=30
graphql-engine:
container_name: query-pezkuwi
image: onfinality/subql-query:v1.5.0
ports:
- 3000:3000
depends_on:
- subquery-node-relay
restart: always
environment:
DB_USER: postgres
DB_PASS: pezkuwi_subquery_2024
DB_DATABASE: postgres
DB_HOST: postgres
DB_PORT: 5432
command:
- --name=subquery-pezkuwi-staking
- --playground
- --indexer=http://subquery-node-relay:3000
graphql-engine-assethub:
container_name: query-pezkuwi-ah
image: onfinality/subql-query:v1.5.0
ports:
- 3001:3000
depends_on:
- subquery-node-assethub
restart: always
environment:
DB_USER: postgres
DB_PASS: pezkuwi_subquery_2024
DB_DATABASE: postgres
DB_HOST: postgres
DB_PORT: 5432
command:
- --name=subquery-pezkuwi-assethub
- --playground
- --indexer=http://subquery-node-assethub:3000
subquery-node-governance:
container_name: node-pezkuwi-governance
build:
context: .
dockerfile: docker/Dockerfile.node
depends_on:
postgres: { condition: service_healthy }
restart: always
environment:
TZ: UTC
DB_USER: postgres
DB_PASS: pezkuwi_subquery_2024
DB_DATABASE: postgres
DB_HOST: postgres
DB_PORT: 5432
volumes:
- ./:/app/project
command:
- -f=/app/project/pezkuwi-governance.yaml
- --db-schema=subquery-pezkuwi-governance
- --disable-historical=true
- --batch-size=30
graphql-engine-governance:
container_name: query-pezkuwi-gov
image: onfinality/subql-query:v1.5.0
ports:
- 3002:3000
depends_on:
- subquery-node-governance
restart: always
environment:
DB_USER: postgres
DB_PASS: pezkuwi_subquery_2024
DB_DATABASE: postgres
DB_HOST: postgres
DB_PORT: 5432
command:
- --name=subquery-pezkuwi-governance
- --playground
- --indexer=http://subquery-node-governance:3000
noter-bot:
container_name: noter-pezkuwi
build:
context: ./noter
dockerfile: Dockerfile
depends_on:
postgres: { condition: service_healthy }
restart: unless-stopped
secrets:
- noter_mnemonic
environment:
TZ: UTC
# The block-producing nodes bind their RPC to localhost by design — reaching
# them from here needed the ports open to the internet, and closing them (as
# they should be) silently cut this bot off from every chain. These are the
# public endpoints, which is what an external client is supposed to use, and
# they are TLS-terminated rather than plaintext ws:// across the internet.
RELAY_RPC: wss://rpc.pezkuwichain.io
ASSET_HUB_RPC: wss://asset-hub-rpc.pezkuwichain.io
PEOPLE_RPC: wss://people-rpc.pezkuwichain.io
SCAN_INTERVAL_MS: "300000"
# The bot writes a heartbeat when a scan makes progress, not when it merely
# stays up: an endless reconnect loop kept the container "Up" for three weeks
# while no staking data reached the People chain.
healthcheck:
test: ["CMD", "node", "-e", "const fs=require('fs');const i=parseInt(process.env.SCAN_INTERVAL_MS||'300000',10);let t=0;try{t=Number(fs.readFileSync(process.env.HEARTBEAT_FILE||'/tmp/noter-heartbeat','utf8'))}catch{};process.exit(Number.isFinite(t)&&Date.now()-t<i*3?0:1)"]
interval: 60s
timeout: 10s
retries: 3
# The first scan has to walk every tracked account before it can report.
start_period: 10m
# The same bot for Zagros, the testnet that rehearses mainnet: its citizens have no
# trust until a noter reports their stake, so without this every Zagros governance
# track stalls. Same image, its own key, its own heartbeat. The bot reads its key
# from /run/secrets/noter_mnemonic, so the Zagros secret is mounted under that name.
noter-bot-zagros:
container_name: noter-zagros
build:
context: ./noter
dockerfile: Dockerfile
restart: unless-stopped
secrets:
- source: noter_zagros_mnemonic
target: noter_mnemonic
environment:
TZ: UTC
RELAY_RPC: wss://zagros-rpc.pezkuwichain.io
ASSET_HUB_RPC: wss://zagros-asset-hub-rpc.pezkuwichain.io
PEOPLE_RPC: wss://zagros-people-rpc.pezkuwichain.io
SCAN_INTERVAL_MS: "300000"
healthcheck:
test: ["CMD", "node", "-e", "const fs=require('fs');const i=parseInt(process.env.SCAN_INTERVAL_MS||'300000',10);let t=0;try{t=Number(fs.readFileSync(process.env.HEARTBEAT_FILE||'/tmp/noter-heartbeat','utf8'))}catch{};process.exit(Number.isFinite(t)&&Date.now()-t<i*3?0:1)"]
interval: 60s
timeout: 10s
retries: 3
start_period: 10m
payout-bot:
container_name: payout-pezkuwi
build:
context: ./payout-bot
dockerfile: Dockerfile
restart: unless-stopped
secrets:
- payout_mnemonic
environment:
TZ: UTC
ASSET_HUB_RPC: wss://asset-hub-rpc.pezkuwichain.io
MNEMONIC_FILE: /run/secrets/payout_mnemonic
INTERVAL_MS: "600000"
secrets:
noter_mnemonic:
file: ./secrets/noter_mnemonic.txt
payout_mnemonic:
file: ./secrets/payout_mnemonic.txt
noter_zagros_mnemonic:
file: ./secrets/noter_zagros_mnemonic.txt
volumes:
pgdata: