From 02d4af5eaeff56b1c85291c5b24acdac51a04c67 Mon Sep 17 00:00:00 2001 From: ziad Date: Fri, 10 Jul 2026 03:04:54 +1000 Subject: [PATCH 1/3] Disable unused Telegram message history persistence in Redis The telegram chat adapter defaults persistMessageHistory to true, which writes every message to Redis (msg-history:telegram:, up to 100 messages/thread, 7-day TTL) even though nothing in this repo reads that history back. This was pure write waste that consumed 3MB/30MB (8.6%) of the Redis plan in a single day after Redis state was connected for dedup locks. Co-Authored-By: Claude Sonnet 5 --- src/lib/telegram/chat/bot.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/lib/telegram/chat/bot.ts b/src/lib/telegram/chat/bot.ts index b68bf8b8..3d47824c 100644 --- a/src/lib/telegram/chat/bot.ts +++ b/src/lib/telegram/chat/bot.ts @@ -11,6 +11,12 @@ export function createTelegramChatBot() { secretToken: process.env.TELEGRAM_CHAT_WEBHOOK_SECRET_TOKEN, mode: 'webhook', }); + // The adapter defaults persistMessageHistory to true, which writes every + // message to Redis (msg-history:) forever. Nothing in this repo + // reads that history back (no LLM context use), so it's pure write waste. + // Field is typed readonly upstream but is a plain mutable class field at + // runtime — force it off here instead of forking the adapter. + (telegramAdapter as { persistMessageHistory: boolean }).persistMessageHistory = false; const bot = new Chat({ userName: process.env.TELEGRAM_CHAT_BOT_USERNAME!, From 21b2a6bd547815b8e40d4f85c6708077b2314faf Mon Sep 17 00:00:00 2001 From: ziad Date: Fri, 10 Jul 2026 03:05:18 +1000 Subject: [PATCH 2/3] Apply prettier formatting Co-Authored-By: Claude Sonnet 5 --- src/lib/telegram/chat/bot.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib/telegram/chat/bot.ts b/src/lib/telegram/chat/bot.ts index 3d47824c..33669c9b 100644 --- a/src/lib/telegram/chat/bot.ts +++ b/src/lib/telegram/chat/bot.ts @@ -16,7 +16,9 @@ export function createTelegramChatBot() { // reads that history back (no LLM context use), so it's pure write waste. // Field is typed readonly upstream but is a plain mutable class field at // runtime — force it off here instead of forking the adapter. - (telegramAdapter as { persistMessageHistory: boolean }).persistMessageHistory = false; + ( + telegramAdapter as { persistMessageHistory: boolean } + ).persistMessageHistory = false; const bot = new Chat({ userName: process.env.TELEGRAM_CHAT_BOT_USERNAME!, From 2368c719bce21e0a52407978393e1ae94350a3fa Mon Sep 17 00:00:00 2001 From: ziad Date: Fri, 10 Jul 2026 03:08:14 +1000 Subject: [PATCH 3/3] Update mapMetadataToSupabase.test.ts --- .../__tests__/mapMetadataToSupabase.test.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/lib/moment/__tests__/mapMetadataToSupabase.test.ts b/src/lib/moment/__tests__/mapMetadataToSupabase.test.ts index 6416ac9b..bad9d636 100644 --- a/src/lib/moment/__tests__/mapMetadataToSupabase.test.ts +++ b/src/lib/moment/__tests__/mapMetadataToSupabase.test.ts @@ -2,16 +2,32 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; vi.mock('@/lib/metadata/getMetadataHandler', () => ({ default: vi.fn() })); vi.mock('@/lib/arweave/getMimeType', () => ({ default: vi.fn() })); +vi.mock('@/lib/farcaster/getFarcasterUsernameByAddress', () => ({ + default: vi.fn(), +})); +vi.mock('@/lib/ens/resolveAddressToEns', () => ({ default: vi.fn() })); import { mapMetadataToSupabase } from '../mapMetadataToSupabase'; import getMetadataHandler from '@/lib/metadata/getMetadataHandler'; import getMimeType from '@/lib/arweave/getMimeType'; +import getFarcasterUsernameByAddress from '@/lib/farcaster/getFarcasterUsernameByAddress'; +import resolveAddressToEns from '@/lib/ens/resolveAddressToEns'; const mockGetMetadata = vi.mocked(getMetadataHandler); const mockGetMimeType = vi.mocked(getMimeType); +const mockGetFarcasterUsername = vi.mocked(getFarcasterUsernameByAddress); +const mockResolveEns = vi.mocked(resolveAddressToEns); describe('mapMetadataToSupabase', () => { - beforeEach(() => vi.clearAllMocks()); + beforeEach(() => { + vi.clearAllMocks(); + // When metadata has no `artist` field, mapMetadataToSupabase falls back + // to a real Farcaster/ENS lookup for the creator address. Default both + // to "not found" so tests that don't care about this fallback don't hit + // the network and hang. + mockGetFarcasterUsername.mockResolvedValue(undefined); + mockResolveEns.mockResolvedValue(null); + }); it('returns empty records for empty input', async () => { const result = await mapMetadataToSupabase([]);