From cd508320387409fc41df5e8d227a57c48ef5cb35 Mon Sep 17 00:00:00 2001 From: Prathamesh Musale Date: Thu, 21 Mar 2024 07:17:01 +0000 Subject: [PATCH] Add a Ajna watcher stack (#781) Part of https://www.notion.so/Generate-ajna-finance-subgraph-watcher-with-codegen-5b80ac149b3f449fb138f5d92cc5485e Reviewed-on: https://git.vdb.to/cerc-io/stack-orchestrator/pulls/781 Co-authored-by: Prathamesh Musale Co-committed-by: Prathamesh Musale --- .../compose/docker-compose-watcher-ajna.yml | 76 +++++++++++ .../config/watcher-ajna/start-job-runner.sh | 20 +++ .../data/config/watcher-ajna/start-server.sh | 20 +++ .../watcher-ajna/watcher-config-template.toml | 98 +++++++++++++++ .../cerc-watcher-ajna/Dockerfile | 10 ++ .../cerc-watcher-ajna/build.sh | 9 ++ stack_orchestrator/data/stacks/ajna/README.md | 118 ++++++++++++++++++ stack_orchestrator/data/stacks/ajna/stack.yml | 9 ++ 8 files changed, 360 insertions(+) create mode 100644 stack_orchestrator/data/compose/docker-compose-watcher-ajna.yml create mode 100755 stack_orchestrator/data/config/watcher-ajna/start-job-runner.sh create mode 100755 stack_orchestrator/data/config/watcher-ajna/start-server.sh create mode 100644 stack_orchestrator/data/config/watcher-ajna/watcher-config-template.toml create mode 100644 stack_orchestrator/data/container-build/cerc-watcher-ajna/Dockerfile create mode 100755 stack_orchestrator/data/container-build/cerc-watcher-ajna/build.sh create mode 100644 stack_orchestrator/data/stacks/ajna/README.md create mode 100644 stack_orchestrator/data/stacks/ajna/stack.yml diff --git a/stack_orchestrator/data/compose/docker-compose-watcher-ajna.yml b/stack_orchestrator/data/compose/docker-compose-watcher-ajna.yml new file mode 100644 index 00000000..b3fcaab5 --- /dev/null +++ b/stack_orchestrator/data/compose/docker-compose-watcher-ajna.yml @@ -0,0 +1,76 @@ +version: '3.2' + +services: + ajna-watcher-db: + restart: unless-stopped + image: postgres:14-alpine + environment: + - POSTGRES_USER=vdbm + - POSTGRES_MULTIPLE_DATABASES=ajna-watcher,ajna-watcher-job-queue + - POSTGRES_EXTENSION=ajna-watcher-job-queue:pgcrypto + - POSTGRES_PASSWORD=password + volumes: + - ../config/postgresql/multiple-postgressql-databases.sh:/docker-entrypoint-initdb.d/multiple-postgressql-databases.sh + - ajna_watcher_db_data:/var/lib/postgresql/data + ports: + - "5432" + healthcheck: + test: ["CMD", "nc", "-v", "localhost", "5432"] + interval: 20s + timeout: 5s + retries: 15 + start_period: 10s + + ajna-watcher-job-runner: + restart: unless-stopped + depends_on: + ajna-watcher-db: + condition: service_healthy + image: cerc/watcher-ajna:local + environment: + CERC_SCRIPT_DEBUG: ${CERC_SCRIPT_DEBUG} + CERC_ETH_RPC_ENDPOINT: ${CERC_ETH_RPC_ENDPOINT} + command: ["bash", "./start-job-runner.sh"] + volumes: + - ../config/watcher-ajna/watcher-config-template.toml:/app/environments/watcher-config-template.toml + - ../config/watcher-ajna/start-job-runner.sh:/app/start-job-runner.sh + ports: + - "9000" + healthcheck: + test: ["CMD", "nc", "-v", "localhost", "9000"] + interval: 20s + timeout: 5s + retries: 15 + start_period: 5s + extra_hosts: + - "host.docker.internal:host-gateway" + + ajna-watcher-server: + restart: unless-stopped + depends_on: + ajna-watcher-db: + condition: service_healthy + ajna-watcher-job-runner: + condition: service_healthy + image: cerc/watcher-ajna:local + environment: + CERC_SCRIPT_DEBUG: ${CERC_SCRIPT_DEBUG} + CERC_ETH_RPC_ENDPOINT: ${CERC_ETH_RPC_ENDPOINT} + command: ["bash", "./start-server.sh"] + volumes: + - ../config/watcher-ajna/watcher-config-template.toml:/app/environments/watcher-config-template.toml + - ../config/watcher-ajna/start-server.sh:/app/start-server.sh + ports: + - "3008" + - "9001" + healthcheck: + test: ["CMD", "nc", "-v", "localhost", "3008"] + interval: 20s + timeout: 5s + retries: 15 + start_period: 5s + extra_hosts: + - "host.docker.internal:host-gateway" + +volumes: + ajna_watcher_db_data: diff --git a/stack_orchestrator/data/config/watcher-ajna/start-job-runner.sh b/stack_orchestrator/data/config/watcher-ajna/start-job-runner.sh new file mode 100755 index 00000000..819b1096 --- /dev/null +++ b/stack_orchestrator/data/config/watcher-ajna/start-job-runner.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +set -e +if [ -n "$CERC_SCRIPT_DEBUG" ]; then + set -x +fi +set -u + +echo "Using ETH RPC endpoint ${CERC_ETH_RPC_ENDPOINT}" + +# Read in the config template TOML file and modify it +WATCHER_CONFIG_TEMPLATE=$(cat environments/watcher-config-template.toml) +WATCHER_CONFIG=$(echo "$WATCHER_CONFIG_TEMPLATE" | \ + sed -E "s|REPLACE_WITH_CERC_ETH_RPC_ENDPOINT|${CERC_ETH_RPC_ENDPOINT}| ") + +# Write the modified content to a new file +echo "$WATCHER_CONFIG" > environments/local.toml + +echo "Running job-runner..." +DEBUG=vulcanize:* exec node --enable-source-maps dist/job-runner.js diff --git a/stack_orchestrator/data/config/watcher-ajna/start-server.sh b/stack_orchestrator/data/config/watcher-ajna/start-server.sh new file mode 100755 index 00000000..e2bbdaad --- /dev/null +++ b/stack_orchestrator/data/config/watcher-ajna/start-server.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +set -e +if [ -n "$CERC_SCRIPT_DEBUG" ]; then + set -x +fi +set -u + +echo "Using ETH RPC endpoint ${CERC_ETH_RPC_ENDPOINT}" + +# Read in the config template TOML file and modify it +WATCHER_CONFIG_TEMPLATE=$(cat environments/watcher-config-template.toml) +WATCHER_CONFIG=$(echo "$WATCHER_CONFIG_TEMPLATE" | \ + sed -E "s|REPLACE_WITH_CERC_ETH_RPC_ENDPOINT|${CERC_ETH_RPC_ENDPOINT}| ") + +# Write the modified content to a new file +echo "$WATCHER_CONFIG" > environments/local.toml + +echo "Running server..." +DEBUG=vulcanize:* exec node --enable-source-maps dist/server.js diff --git a/stack_orchestrator/data/config/watcher-ajna/watcher-config-template.toml b/stack_orchestrator/data/config/watcher-ajna/watcher-config-template.toml new file mode 100644 index 00000000..b2b54c69 --- /dev/null +++ b/stack_orchestrator/data/config/watcher-ajna/watcher-config-template.toml @@ -0,0 +1,98 @@ +[server] + host = "0.0.0.0" + port = 3008 + kind = "active" + gqlPath = "/graphql" + + # Checkpointing state. + checkpointing = true + + # Checkpoint interval in number of blocks. + checkpointInterval = 2000 + + # Enable state creation + # CAUTION: Disable only if state creation is not desired or can be filled subsequently + enableState = false + + subgraphPath = "./subgraph-build" + + # Interval to restart wasm instance periodically + wasmRestartBlocksInterval = 20 + + # Interval in number of blocks at which to clear entities cache. + clearEntitiesCacheInterval = 1000 + + # Max block range for which to return events in eventsInRange GQL query. + # Use -1 for skipping check on block range. + maxEventsBlockRange = 1000 + + # Flag to specify whether RPC endpoint supports block hash as block tag parameter + rpcSupportsBlockHashParam = false + + # GQL cache settings + [server.gqlCache] + enabled = true + + # Max in-memory cache size (in bytes) (default 8 MB) + # maxCacheSize + + # GQL cache-control max-age settings (in seconds) + maxAge = 15 + timeTravelMaxAge = 86400 # 1 day + +[metrics] + host = "0.0.0.0" + port = 9000 + [metrics.gql] + port = 9001 + +[database] + type = "postgres" + host = "ajna-watcher-db" + port = 5432 + database = "ajna-watcher" + username = "vdbm" + password = "password" + synchronize = true + logging = false + +[upstream] + [upstream.ethServer] + rpcProviderEndpoint = "REPLACE_WITH_CERC_ETH_RPC_ENDPOINT" + + # Boolean flag to specify if rpc-eth-client should be used for RPC endpoint instead of ipld-eth-client (ipld-eth-server GQL client) + rpcClient = true + + # Boolean flag to specify if rpcProviderEndpoint is an FEVM RPC endpoint + isFEVM = true + + # Boolean flag to filter event logs by contracts + filterLogsByAddresses = true + # Boolean flag to filter event logs by topics + filterLogsByTopics = true + + [upstream.cache] + name = "requests" + enabled = false + deleteOnStart = false + +[jobQueue] + dbConnectionString = "postgres://vdbm:password@ajna-watcher-db/ajna-watcher-job-queue" + maxCompletionLagInSecs = 300 + jobDelayInMilliSecs = 100 + eventsInBatch = 50 + subgraphEventsOrder = true + # Filecoin block time: https://docs.filecoin.io/basics/the-blockchain/blocks-and-tipsets#blocktime + blockDelayInMilliSecs = 30000 + + # Boolean to switch between modes of processing events when starting the server. + # Setting to true will fetch filtered events and required blocks in a range of blocks and then process them. + # Setting to false will fetch blocks consecutively with its events and then process them (Behaviour is followed in realtime processing near head). + useBlockRanges = true + + # Block range in which logs are fetched during historical blocks processing + historicalLogsBlockRange = 2000 + + # Max block range of historical processing after which it waits for completion of events processing + # If set to -1 historical processing does not wait for events processing and completes till latest canonical block + historicalMaxFetchAhead = 10000 diff --git a/stack_orchestrator/data/container-build/cerc-watcher-ajna/Dockerfile b/stack_orchestrator/data/container-build/cerc-watcher-ajna/Dockerfile new file mode 100644 index 00000000..4369d50a --- /dev/null +++ b/stack_orchestrator/data/container-build/cerc-watcher-ajna/Dockerfile @@ -0,0 +1,10 @@ +FROM node:18.17.1-alpine3.18 + +RUN apk --update --no-cache add git python3 alpine-sdk bash curl jq + +WORKDIR /app + +COPY . . + +RUN echo "Installing dependencies and building ajna-watcher-ts" && \ + yarn && yarn build diff --git a/stack_orchestrator/data/container-build/cerc-watcher-ajna/build.sh b/stack_orchestrator/data/container-build/cerc-watcher-ajna/build.sh new file mode 100755 index 00000000..4feede03 --- /dev/null +++ b/stack_orchestrator/data/container-build/cerc-watcher-ajna/build.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +# Build cerc/watcher-ajna + +source ${CERC_CONTAINER_BASE_DIR}/build-base.sh + +# See: https://stackoverflow.com/a/246128/1701505 +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +docker build -t cerc/watcher-ajna:local -f ${SCRIPT_DIR}/Dockerfile ${build_command_args} ${CERC_REPO_BASE_DIR}/ajna-watcher-ts diff --git a/stack_orchestrator/data/stacks/ajna/README.md b/stack_orchestrator/data/stacks/ajna/README.md new file mode 100644 index 00000000..6f88ec0a --- /dev/null +++ b/stack_orchestrator/data/stacks/ajna/README.md @@ -0,0 +1,118 @@ +# Ajna Watcher + +## Setup + +Clone required repositories: + +```bash +laconic-so --stack ajna setup-repositories --git-ssh --pull +``` + +Build the container images: + +```bash +laconic-so --stack ajna build-containers +``` + +## Deploy + +Create a spec file for the deployment: + +```bash +laconic-so --stack ajna deploy init --output ajna-spec.yml +``` + +### Ports + +Edit `network` in the spec file to map container ports to host ports as required: + +```yml +... +network: + ports: + ajna-watcher-db: + - 15432:5432 + ajna-watcher-job-runner: + - 9000:9000 + ajna-watcher-server: + - 3008:3008 + - 9001:9001 +``` + +### Create a deployment + +Create a deployment from the spec file: + +```bash +laconic-so --stack ajna deploy create --spec-file ajna-spec.yml --deployment-dir ajna-deployment +``` + +### Configuration + +Inside deployment directory, open the `config.env` file and set following env variables: + +```bash +# External Filecoin (ETH RPC) endpoint to point the watcher to +CERC_ETH_RPC_ENDPOINT=https://example-lotus-endpoint/rpc/v1 +``` + +### Start the deployment + +```bash +laconic-so deployment --dir ajna-deployment start +``` + +* To list down and monitor the running containers: + + ```bash + # With status + docker ps -a + + # Check logs for a container + docker logs -f + ``` + +* Open the GQL playground at + + ```graphql + # Example query + query { + _meta { + block { + hash + number + timestamp + } + deployment + hasIndexingErrors + } + + accounts { + id + txCount + tokensDelegated + rewardsClaimed + } + } + ``` + +## Clean up + +Stop all the ajna services running in background: + +```bash +# Only stop the docker containers +laconic-so deployment --dir ajna-deployment stop + +# Run 'start' to restart the deployment +``` + +To stop all the ajna services and also delete data: + +```bash +# Stop the docker containers +laconic-so deployment --dir ajna-deployment stop --delete-volumes + +# Remove deployment directory (deployment will have to be recreated for a re-run) +rm -r ajna-deployment +``` diff --git a/stack_orchestrator/data/stacks/ajna/stack.yml b/stack_orchestrator/data/stacks/ajna/stack.yml new file mode 100644 index 00000000..6956d90d --- /dev/null +++ b/stack_orchestrator/data/stacks/ajna/stack.yml @@ -0,0 +1,9 @@ +version: "1.0" +name: ajna +description: "Ajna watcher stack" +repos: + - git.vdb.to/cerc-io/ajna-watcher-ts +containers: + - cerc/watcher-ajna +pods: + - watcher-ajna