Skip to content

Commit

Permalink
feat: Add script to suspend Indexers (#829)
Browse files Browse the repository at this point in the history
This PR adds a Node script to Runner to suspend Indexers due to
inactivity. The script will:
1. Call Coordinator to disable the indexer
2. Write to the Indexers logs table to notify of suspension

Note that as Coordinator is in a private network, you must tunnel to the
machine to expose the gRPC server. This can be achieved via running the
following in a separate terminal:
```sh
gcloud compute ssh ubuntu@queryapi-coordinator-mainnet -- -L 9003:0.0.0.0:9003
```

The following environment variables are required:
- `HASURA_ADMIN_SECRET`
- `HASURA_ENDPOINT`
- `PGPORT`
- `PGHOST`

All of which can be found in the Runner compute instance metadata:
```sh
gcloud compute instances describe queryapi-runner-mainnet
```


Usage: `npm run script:suspend-indexer -- <accountId> <functionName>`
  • Loading branch information
morgsmccauley authored Jun 25, 2024
1 parent 9ec0ced commit ec17eee
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 4 deletions.
3 changes: 2 additions & 1 deletion runner/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"start:dev": "tsc -p ./tsconfig.build.json && node ./dist",
"start:docker": "node dist/index.js",
"test": "npm run codegen && node --experimental-vm-modules ./node_modules/.bin/jest --silent",
"lint": "eslint -c .eslintrc.js"
"lint": "eslint -c .eslintrc.js",
"script:suspend-indexer": "tsc -p ./tsconfig.json && node ./dist/scripts/suspend-indexer.js"
},
"keywords": [],
"author": "",
Expand Down
100 changes: 100 additions & 0 deletions runner/scripts/suspend-indexer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* This script is used to suspend an indexer for a given account. It will:
* 1. Call Coordinator to disable the indexer
* 2. Write to the Indexers logs table to notify of suspension
*
* Note that as Coordinator is in a private network, you must tunnel to the machine to expose the gRPC server.
* This can be achieved via running the following in a separate terminal:
* ```sh
* gcloud compute ssh ubuntu@queryapi-coordinator-mainnet -- -L 9003:0.0.0.0:9003
* ```
*
* The following environment variables are required:
* - `HASURA_ADMIN_SECRET`
* - `HASURA_ENDPOINT`
* - `PGPORT`
* - `PGHOST`
*
* All of which can be found in the Runner compute instance metadata:
* ```sh
* gcloud compute instances describe queryapi-runner-mainnet
* ```
*
*
* Usage: npm run script:suspend-indexer -- <accountId> <functionName>
*/

import assert from 'assert'
import * as fs from 'fs'

import * as grpc from '@grpc/grpc-js'
import * as protoLoader from '@grpc/proto-loader'

import Provisioner from '../src/provisioner'
import IndexerConfig from '../src/indexer-config'
import IndexerMeta, { LogEntry } from '../src/indexer-meta';

const COORDINATOR_PROTO_PATH = '../coordinator/proto/indexer_manager.proto';

assert(exists(COORDINATOR_PROTO_PATH), 'Coordinator proto file not found. Make sure you run this script from the root directory.');
assert(process.argv.length === 4, 'Usage: npm run script:suspend-indexer -- <accountId> <functionName>');
assert(process.env.COORDINATOR_PORT, 'COORDINATOR_PORT env var is required');
assert(process.env.HASURA_ADMIN_SECRET, 'HASURA_ADMIN_SECRET env var is required');
assert(process.env.HASURA_ENDPOINT, 'HASURA_ENDPOINT env var is required');
assert(process.env.PGPORT, 'PGPORT env var is required');
assert(process.env.PGHOST, 'PGHOST env var is required');

const [_binary, _file, accountId, functionName] = process.argv;
const { COORDINATOR_PORT = 9003 } = process.env;

main();

async function main() {
await suspendIndexer();
await logSuspension();

console.log('Done')
}

async function logSuspension() {
console.log('Logging suspension notification');

const config = new IndexerConfig('not needed', accountId, functionName, 0, 'not needed', 'not needed', 2);

const pgCredentials = await new Provisioner().getPostgresConnectionParameters(config.userName());

await new IndexerMeta(config, pgCredentials).writeLogs([
LogEntry.systemInfo('The indexer is suspended due to inactivity.'),
]);
}

async function suspendIndexer() {
console.log(`Suspending indexer: ${accountId}/${functionName}`);

const indexerManager = createIndexerManagerClient();

return new Promise((resolve, reject) => {
indexerManager.disable({ accountId, functionName }, (err: any, response: any) => {
if (err) {
reject(err);
} else {
resolve(response);
}
});
})
}

function exists(path: string): boolean {
try {
fs.statSync(path);
return true;
} catch (err) {
return false;
}
}

function createIndexerManagerClient() {
const packageDefinition = protoLoader.loadSync(COORDINATOR_PROTO_PATH);
const protoDescriptor: any = grpc.loadPackageDefinition(packageDefinition);
return new protoDescriptor.indexer.IndexerManager(`localhost:${COORDINATOR_PORT}`, grpc.credentials.createInsecure());
}
1 change: 1 addition & 0 deletions runner/src/indexer-meta/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { default } from './indexer-meta';
export { IndexerStatus, METADATA_TABLE_UPSERT, MetadataFields } from './indexer-meta';
export { default as LogEntry } from './log-entry';
2 changes: 1 addition & 1 deletion runner/tsconfig.build.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"extends": "./tsconfig.json",
"include": ["./src"],
"exclude": ["node_modules", "dist", "**/*.test.*"]
"exclude": ["node_modules", "dist", "**/*.test.*", "scripts"]
}
4 changes: 2 additions & 2 deletions runner/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"target": "es2018", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
"lib": ["es2021"], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
"module": "commonjs", /* Specify what module code is generated. */
"rootDirs": ["./src", "./tests"],
"rootDirs": ["./src", "./tests", "./scripts"],
"moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
"resolveJsonModule": true, /* Enable importing .json files. */
"allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
Expand All @@ -20,6 +20,6 @@
"noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
},
"include": ["./src", "./tests"],
"include": ["./src", "./tests", "./scripts"],
"exclude": ["node_modules", "dist"]
}

0 comments on commit ec17eee

Please sign in to comment.