From 39a43a783a29185e29e1b0a2de433a8015ff1ecd Mon Sep 17 00:00:00 2001 From: Steven Date: Thu, 21 Nov 2024 08:02:58 +0100 Subject: [PATCH] feat(tools): adding a cron for checking test.graph (#2671) --- .changeset/kind-schools-lick.md | 2 + packages/apps/tools/next.config.js | 9 ++ .../tools/src/app/api/graph/route.route.ts | 8 ++ .../src/scripts/{faucetCron => }/constants.ts | 3 + .../faucetCron/__tests__/index.test.ts | 2 +- .../faucetCron/__tests__/messages.test.ts | 2 +- .../tools/src/scripts/faucetCron/index.ts | 4 +- .../tools/src/scripts/faucetCron/messages.ts | 4 +- .../apps/tools/src/scripts/graphCron/index.ts | 98 +++++++++++++++++++ .../tools/src/scripts/graphCron/messages.ts | 36 +++++++ packages/apps/tools/vercel.json | 4 + 11 files changed, 166 insertions(+), 6 deletions(-) create mode 100644 .changeset/kind-schools-lick.md create mode 100644 packages/apps/tools/src/app/api/graph/route.route.ts rename packages/apps/tools/src/scripts/{faucetCron => }/constants.ts (89%) create mode 100644 packages/apps/tools/src/scripts/graphCron/index.ts create mode 100644 packages/apps/tools/src/scripts/graphCron/messages.ts diff --git a/.changeset/kind-schools-lick.md b/.changeset/kind-schools-lick.md new file mode 100644 index 0000000000..a845151cc8 --- /dev/null +++ b/.changeset/kind-schools-lick.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/packages/apps/tools/next.config.js b/packages/apps/tools/next.config.js index ea92099894..aa2780a5ee 100644 --- a/packages/apps/tools/next.config.js +++ b/packages/apps/tools/next.config.js @@ -61,6 +61,15 @@ const config = { }, ], }, + { + source: '/api/graph', + headers: [ + { + key: 'Cache-Control', + value: 'no-store, max-age=0', + }, + ], + }, ]; }, }; diff --git a/packages/apps/tools/src/app/api/graph/route.route.ts b/packages/apps/tools/src/app/api/graph/route.route.ts new file mode 100644 index 0000000000..0b13902345 --- /dev/null +++ b/packages/apps/tools/src/app/api/graph/route.route.ts @@ -0,0 +1,8 @@ +import { runJob } from '@/scripts/graphCron'; + +export async function GET(request: Request) { + await runJob(); + return new Response(`Graph cron job`); +} + +export const revalidate = 0; diff --git a/packages/apps/tools/src/scripts/faucetCron/constants.ts b/packages/apps/tools/src/scripts/constants.ts similarity index 89% rename from packages/apps/tools/src/scripts/faucetCron/constants.ts rename to packages/apps/tools/src/scripts/constants.ts index c94b2da505..3cb9c014cf 100644 --- a/packages/apps/tools/src/scripts/faucetCron/constants.ts +++ b/packages/apps/tools/src/scripts/constants.ts @@ -5,6 +5,9 @@ export const tokenId = process.env.SLACK_TOKEN; export const faucetAccount = 'c:Ecwy85aCW3eogZUnIQxknH8tG8uXHM5QiC__jeI0nWA'; export const MINBALANCE = 1000; +//graph +export const MAXBLOCKHEIGHT_DIFFERENCE = 100; + export interface IChainAccount { balance: number; chainId: string; diff --git a/packages/apps/tools/src/scripts/faucetCron/__tests__/index.test.ts b/packages/apps/tools/src/scripts/faucetCron/__tests__/index.test.ts index 88558f5137..b13308d08e 100644 --- a/packages/apps/tools/src/scripts/faucetCron/__tests__/index.test.ts +++ b/packages/apps/tools/src/scripts/faucetCron/__tests__/index.test.ts @@ -1,5 +1,5 @@ import { creatLowChainsString, lowFaucetChains, runJob } from '..'; -import type { IAccount, IChainAccount } from '../constants'; +import type { IAccount, IChainAccount } from '../../constants'; describe('faucetCron Utils', () => { describe('creatLowChainsString', () => { diff --git a/packages/apps/tools/src/scripts/faucetCron/__tests__/messages.test.ts b/packages/apps/tools/src/scripts/faucetCron/__tests__/messages.test.ts index b49d1d8dcf..b168161e18 100644 --- a/packages/apps/tools/src/scripts/faucetCron/__tests__/messages.test.ts +++ b/packages/apps/tools/src/scripts/faucetCron/__tests__/messages.test.ts @@ -1,4 +1,4 @@ -import type { IAccount } from '../constants'; +import type { IAccount } from '../../constants'; import { sendErrorMessage, sendMessage } from '../messages'; const mocks = vi.hoisted(() => { diff --git a/packages/apps/tools/src/scripts/faucetCron/index.ts b/packages/apps/tools/src/scripts/faucetCron/index.ts index d7e59b8503..f0e80d7274 100644 --- a/packages/apps/tools/src/scripts/faucetCron/index.ts +++ b/packages/apps/tools/src/scripts/faucetCron/index.ts @@ -1,5 +1,5 @@ -import type { IAccount, IChainAccount } from './constants'; -import { MINBALANCE, faucetAccount } from './constants'; +import type { IAccount, IChainAccount } from './../constants'; +import { MINBALANCE, faucetAccount } from './../constants'; import { sendErrorMessage, sendMessage } from './messages'; export const lowFaucetChains = ( diff --git a/packages/apps/tools/src/scripts/faucetCron/messages.ts b/packages/apps/tools/src/scripts/faucetCron/messages.ts index 3e5f8d028c..e3dd33febb 100644 --- a/packages/apps/tools/src/scripts/faucetCron/messages.ts +++ b/packages/apps/tools/src/scripts/faucetCron/messages.ts @@ -1,6 +1,6 @@ import { creatLowChainsString, lowFaucetChains } from '.'; -import type { IAccount } from './constants'; -import { MINBALANCE, channelId, faucetAccount, tokenId } from './constants'; +import type { IAccount } from './../constants'; +import { MINBALANCE, channelId, faucetAccount, tokenId } from './../constants'; export const sendMessage = async (data: IAccount): Promise => { const lowChains = lowFaucetChains( diff --git a/packages/apps/tools/src/scripts/graphCron/index.ts b/packages/apps/tools/src/scripts/graphCron/index.ts new file mode 100644 index 0000000000..dd07151c1f --- /dev/null +++ b/packages/apps/tools/src/scripts/graphCron/index.ts @@ -0,0 +1,98 @@ +import { MAXBLOCKHEIGHT_DIFFERENCE } from '../constants'; +import { sendErrorMessage } from './messages'; + +interface IEnvProps { + env: 'testnet04' | 'mainnet01'; + chainweb: string; + graphql: string; +} + +const countHeightOnChainweb = async (props: IEnvProps): Promise => { + try { + const result = await fetch(props.chainweb); + const data: any = await result.json(); + return Object.entries(data.hashes) + .map(([key, val]) => val) + .reduce((acc: number, val: any) => { + return acc + val.height; + }, 0); + } catch (e) { + return parseInt('no Number'); + } +}; + +const countHeightOnGraph = async (props: IEnvProps): Promise => { + const result = await fetch(props.graphql, { + method: 'POST', + headers: { + accept: + 'application/graphql-response+json, application/json, multipart/mixed', + 'cache-control': 'no-cache', + 'content-type': 'application/json', + pragma: 'no-cache', + 'sec-fetch-mode': 'cors', + 'sec-fetch-site': 'cross-site', + }, + body: JSON.stringify({ + query: `query graphBlockHeight { + lastBlockHeight + }`, + variables: {}, + extensions: {}, + }), + }); + + const data = (await result.json()) as any; + return data.data.lastBlockHeight * 20; +}; + +export const runJobPerEnvironment = async (props: IEnvProps) => { + try { + const totalHeightOnChainWeb = await countHeightOnChainweb(props); + const totalHeightOnGraph = await countHeightOnGraph(props); + + if (Number.isNaN(totalHeightOnChainWeb)) { + await sendErrorMessage({ + title: `${props.env} chainweb.com fail`, + msg: `We were unable to retrieve the blockheights from chainweb. \n There seems to be an issue with ChainWeb (${props.chainweb})`, + }); + return; + } + if (Number.isNaN(totalHeightOnGraph)) { + await sendErrorMessage({ + title: `${props.env} graph fail`, + msg: `We were unable to retrieve the blockheights from the test graph. \n There seems to be an issue with test graph (${props.graphql})`, + }); + return; + } + + if ( + Math.abs(totalHeightOnChainWeb - totalHeightOnGraph) > + MAXBLOCKHEIGHT_DIFFERENCE + ) { + await sendErrorMessage({ + title: `${props.env} graph issue`, + msg: `There is a large difference in the last blockheight between ${props.env} chainweb and graph. \n difference: ${Math.abs(totalHeightOnChainWeb - totalHeightOnGraph)}`, + }); + } + } catch (e) { + await sendErrorMessage({ + title: `There was a general issue with the ${props.env} graph cron job`, + msg: ``, + }); + } +}; + +export const runJob = async () => { + await runJobPerEnvironment({ + env: 'testnet04', + chainweb: 'https://ap1.testnet.chainweb.com/chainweb/0.0/testnet04/cut', + graphql: 'https://graph.testnet.kadena.network/graphql', + }); + + await runJobPerEnvironment({ + env: 'mainnet01', + chainweb: 'https://api.chainweb.com/chainweb/0.0/mainnet01/cut ', + graphql: 'https://graph.kadena.network/graphql', + }); +}; diff --git a/packages/apps/tools/src/scripts/graphCron/messages.ts b/packages/apps/tools/src/scripts/graphCron/messages.ts new file mode 100644 index 0000000000..e7a6f5f0bb --- /dev/null +++ b/packages/apps/tools/src/scripts/graphCron/messages.ts @@ -0,0 +1,36 @@ +import { channelId, tokenId } from './../constants'; + +export const sendErrorMessage = async ({ + title, + msg, +}: { + title: string; + msg: string; +}): Promise => { + await fetch('https://slack.com/api/chat.postMessage', { + method: 'POST', + headers: { + 'Content-Type': 'application/json; charset=utf-8', + Authorization: `Bearer ${tokenId}`, + }, + body: JSON.stringify({ + channel: `${channelId}`, + blocks: JSON.stringify([ + { + type: 'header', + text: { + type: 'plain_text', + text: title ? title : `Error in Graph check! 🚨`, + }, + }, + { + type: 'section', + text: { + type: 'mrkdwn', + text: `${msg}`, + }, + }, + ]), + }), + }); +}; diff --git a/packages/apps/tools/vercel.json b/packages/apps/tools/vercel.json index ee5b6fc1bd..7fde5ff9db 100644 --- a/packages/apps/tools/vercel.json +++ b/packages/apps/tools/vercel.json @@ -3,6 +3,10 @@ { "path": "/api/faucet", "schedule": "15 3,15 * * *" + }, + { + "path": "/api/graph", + "schedule": "15 4,16 * * *" } ] }