From 7cee9a9f021ea710c1f727320c317768b9ffcb9e Mon Sep 17 00:00:00 2001 From: TaprootFreak <142087526+TaprootFreak@users.noreply.github.com> Date: Tue, 19 Aug 2025 08:56:32 +0200 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20Add=20automatic=20fallback=20to=20d?= =?UTF-8?q?ev.ponder.deuro.com=20when=20main=20Ponder=E2=80=A6=20(#55)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: Add automatic fallback to dev.ponder.deuro.com when main Ponder is unavailable - Implements 10-minute fallback mechanism for improved reliability - Automatically switches to dev Ponder URL on network errors/timeouts - Returns to main URL after fallback period expires - Maintains transparent operation for all GraphQL services * feat: replace console.log and minor improvements --------- Co-authored-by: bernd2022 --- .env.example | 1 + api.apollo.config.ts | 40 ++++++++++++++++++++++++++++++++++------ api.config.ts | 8 ++++++-- 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/.env.example b/.env.example index eb6cec7..672ae40 100644 --- a/.env.example +++ b/.env.example @@ -2,6 +2,7 @@ PORT=3000 CONFIG_APP_URL=https://app.deuro.com CONFIG_INDEXER_URL=https://ponder.deuro.com +CONFIG_INDEXER_FALLBACK_URL=https://dev.ponder.deuro.com CONFIG_CHAIN=mainnet RPC_URL_MAINNET=https://eth-mainnet.g.alchemy.com/v2/[API-KEY] diff --git a/api.apollo.config.ts b/api.apollo.config.ts index 6ed2907..757b806 100644 --- a/api.apollo.config.ts +++ b/api.apollo.config.ts @@ -1,12 +1,31 @@ import { ApolloClient, ApolloLink, createHttpLink, InMemoryCache } from '@apollo/client/core'; import { onError } from '@apollo/client/link/error'; +import { Logger } from '@nestjs/common'; import fetch from 'cross-fetch'; import { CONFIG } from './api.config'; +const logger = new Logger('ApiApolloConfig'); + +// Fallback URL management +let fallbackUntil: number | null = null; + +function getIndexerUrl(): string { + if (fallbackUntil && Date.now() < fallbackUntil) return CONFIG.indexerFallback; + if (fallbackUntil) fallbackUntil = null; // Reset expired fallback + return CONFIG.indexer; +} + +function activateFallback(): void { + if (!fallbackUntil) { + fallbackUntil = Date.now() + 10 * 60 * 1000; // 10 minutes + logger.log(`[Ponder] Switching to fallback for 10min: ${CONFIG.indexerFallback}`); + } +} + const errorLink = onError(({ graphQLErrors, networkError, operation }) => { if (graphQLErrors) { graphQLErrors.forEach((error) => { - console.error(`[GraphQL error in operation: ${operation?.operationName || 'unknown'}]`, { + logger.error(`[GraphQL error in operation: ${operation?.operationName || 'unknown'}]`, { message: error.message, locations: error.locations, path: error.path, @@ -14,16 +33,19 @@ const errorLink = onError(({ graphQLErrors, networkError, operation }) => { }); } if (networkError) { - console.error(`[Network error in operation: ${operation?.operationName || 'unknown'}]`, { + logger.error(`[Network error in operation: ${operation?.operationName || 'unknown'}]`, { message: networkError.message, name: networkError.name, stack: networkError.stack, }); + + // Activate fallback on network errors + if (getIndexerUrl() === CONFIG.indexer) activateFallback(); } }); const httpLink = createHttpLink({ - uri: CONFIG.indexer, + uri: getIndexerUrl(), fetch: (uri: RequestInfo | URL, options?: RequestInit) => { const controller = new AbortController(); const timeout = setTimeout(() => { @@ -33,9 +55,15 @@ const httpLink = createHttpLink({ return fetch(uri, { ...options, signal: controller.signal, - }).finally(() => { - clearTimeout(timeout); - }); + }) + .catch((error) => { + // Activate fallback on http errors + if (getIndexerUrl() === CONFIG.indexer) activateFallback(); + throw error; + }) + .finally(() => { + clearTimeout(timeout); + }); }, }); diff --git a/api.config.ts b/api.config.ts index 4a03f6f..12c9104 100644 --- a/api.config.ts +++ b/api.config.ts @@ -1,6 +1,7 @@ import { Chain, createPublicClient, http } from 'viem'; import { mainnet, polygon } from 'viem/chains'; +import { Logger } from '@nestjs/common'; import * as dotenv from 'dotenv'; dotenv.config(); @@ -13,6 +14,7 @@ if (process.env.COINGECKO_API_KEY === undefined) throw new Error('COINGECKO_API_ export type ConfigType = { app: string; indexer: string; + indexerFallback: string; coingeckoApiKey: string; chain: Chain; network: { @@ -38,6 +40,7 @@ export type ConfigType = { export const CONFIG: ConfigType = { app: process.env.CONFIG_APP_URL || 'https://app.deuro.com', indexer: process.env.CONFIG_INDEXER_URL || 'https://ponder.deuro.com/', + indexerFallback: process.env.CONFIG_INDEXER_FALLBACK_URL || 'https://dev.ponder.deuro.com/', coingeckoApiKey: process.env.COINGECKO_API_KEY, chain: process.env.CONFIG_CHAIN === 'polygon' ? polygon : mainnet, // @dev: default mainnet network: { @@ -60,8 +63,9 @@ export const CONFIG: ConfigType = { }; // Start up message -console.log(`Starting API with this config:`); -console.log(CONFIG); +const logger = new Logger('ApiConfig'); +logger.log(`Starting API with this config:`); +logger.log(CONFIG); // Refer to https://github.com/yagop/node-telegram-bot-api/blob/master/doc/usage.md#sending-files process.env.NTBA_FIX_350 = 'true'; From b026ddf4124bb7e63624328d1ed730c6327e91ac Mon Sep 17 00:00:00 2001 From: lapatric <42653152+lapatric@users.noreply.github.com> Date: Tue, 19 Aug 2025 09:55:10 +0200 Subject: [PATCH 2/2] [NO-TASK] index url fix --- api.apollo.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api.apollo.config.ts b/api.apollo.config.ts index 757b806..2d262bf 100644 --- a/api.apollo.config.ts +++ b/api.apollo.config.ts @@ -45,7 +45,7 @@ const errorLink = onError(({ graphQLErrors, networkError, operation }) => { }); const httpLink = createHttpLink({ - uri: getIndexerUrl(), + uri: getIndexerUrl, fetch: (uri: RequestInfo | URL, options?: RequestInit) => { const controller = new AbortController(); const timeout = setTimeout(() => {