refactor: merge BOT_TOKEN + ADDITIONAL_BOT_TOKENS into single BOT_TOKENS env + speed audit
Deploy FileDrop / deploy (push) Failing after 19s
Deploy FileDrop / deploy (push) Failing after 19s
BOT_TOKENS env:
- Single BOT_TOKENS env var (comma-separated) replaces BOT_TOKEN + ADDITIONAL_BOT_TOKENS
- Backward compat: falls back to BOT_TOKEN + ADDITIONAL_BOT_TOKENS if BOT_TOKENS unset
- Config exposes botTokens: string[] instead of botToken + additionalBotTokens
- Updated env.ts, bot-pool.ts, docker-compose.yml, .env.example, CLAUDE.md, all tests
Speed audit (S3 -> Telegram upload flow):
- Hoisted 5 dynamic await import('../../../db/index') to top-level static imports
in s3-controller.ts (3x) and web-api-controller.ts (2x)
-> saves module resolution + async overhead on every upload
- Removed stale UPLOAD_CONCURRENCY env from docker-compose.yml
(already removed from env.ts in prior refactor)
Upload flow is already concurrent:
- streamBodyToTemp() uses Bun.file(path).writer() — O(1) memory, safe for multi-GB blobs
- utils/chunked-storage.ts reads chunks serially but uploads concurrently with
inFlight backpressure at effectiveConcurrency * 2 (= 16 with 8 bots)
- bot-pool.ts: per-bot PQueue(concurrency=1), 8 bots = 8 concurrent uploads per file,
selectBot() picks least-loaded, 429 detection + inner+outer retry loops
- TELEGRAM_API_TIMEOUT_MS=120s — ample for 48MB chunks
- Infrastructure chunked-storage.ts (DI-based, dead code) has serial upload trap —
noted for future cleanup
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, mock } from 'bun:test';
|
||||
|
||||
process.env.BOT_TOKEN = 'bot1:token';
|
||||
process.env.ADDITIONAL_BOT_TOKENS = 'bot2:token,bot3:token';
|
||||
process.env.BOT_TOKENS = 'bot1:token,bot2:token,bot3:token';
|
||||
process.env.STORAGE_CHANNEL_ID = '-1001234567890';
|
||||
process.env.BASE_URL = 'https://example.com';
|
||||
process.env.DATABASE_URL = 'sqlite://test.db';
|
||||
|
||||
+8
-7
@@ -3,7 +3,7 @@ import { config } from '../src/env';
|
||||
|
||||
describe('Environment Variables Validation', () => {
|
||||
it('config should have all required fields', () => {
|
||||
expect(config).toHaveProperty('botToken');
|
||||
expect(config).toHaveProperty('botTokens');
|
||||
expect(config).toHaveProperty('storageChatId');
|
||||
expect(config).toHaveProperty('baseUrl');
|
||||
expect(config).toHaveProperty('databaseUrl');
|
||||
@@ -17,8 +17,9 @@ describe('Environment Variables Validation', () => {
|
||||
expect(config).toHaveProperty('sessionMaxAgeMs');
|
||||
});
|
||||
|
||||
it('config.botToken should return BOT_TOKEN from process.env', () => {
|
||||
expect(config.botToken).toBe(process.env.BOT_TOKEN || '');
|
||||
it('config.botTokens should return array from BOT_TOKENS env', () => {
|
||||
expect(Array.isArray(config.botTokens)).toBe(true);
|
||||
expect(config.botTokens.length).toBeGreaterThanOrEqual(3);
|
||||
});
|
||||
|
||||
it('config.storageChatId should be parsed as integer from STORAGE_CHANNEL_ID', () => {
|
||||
@@ -52,10 +53,10 @@ describe('Environment Variables Validation', () => {
|
||||
expect(config.sessionMaxAgeMs).toBe(86400 * 1000);
|
||||
});
|
||||
|
||||
it('additionalBotTokens should be populated in test environment', () => {
|
||||
expect(Array.isArray(config.additionalBotTokens)).toBe(true);
|
||||
// With mock tokens from setup-env.ts there should be 2 additional tokens
|
||||
expect(config.additionalBotTokens.length).toBeGreaterThanOrEqual(2);
|
||||
it('botTokens should be populated in test environment', () => {
|
||||
expect(Array.isArray(config.botTokens)).toBe(true);
|
||||
// With mock tokens from setup-env.ts there should be at least 3 tokens
|
||||
expect(config.botTokens.length).toBeGreaterThanOrEqual(3);
|
||||
});
|
||||
|
||||
it('S3 validation should not throw — env already loaded without error at import time', () => {
|
||||
|
||||
@@ -10,12 +10,11 @@
|
||||
* defaults in `src/env.ts` and are not touched.
|
||||
*/
|
||||
|
||||
process.env.BOT_TOKEN ||= '123456:ABC-DEF';
|
||||
process.env.BOT_TOKENS ||= '123456:ABC-DEF,789012:GHI-JKL,345678:MNO-PQR';
|
||||
process.env.STORAGE_CHANNEL_ID ||= '-1001234567890';
|
||||
process.env.BASE_URL ||= 'https://example.com';
|
||||
process.env.DATABASE_URL ||= 'postgresql://user:pass@localhost:5432/test';
|
||||
process.env.PORT ||= '3000';
|
||||
process.env.NODE_ENV = 'test';
|
||||
|
||||
// Add mock additional bot tokens so multi-bot rotation logic is tested too
|
||||
process.env.ADDITIONAL_BOT_TOKENS ||= '789012:GHI-JKL,345678:MNO-PQR';
|
||||
// Keep old env names for backward compat with tests that reference them directly
|
||||
|
||||
@@ -148,7 +148,7 @@ describe('Telegram API Utilities', () => {
|
||||
file_size: 98765,
|
||||
mime_type: 'image/jpeg',
|
||||
file_path: 'photos/file_0.jpg',
|
||||
bot_token: config.botToken,
|
||||
bot_token: config.botTokens[0],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user