PeerCortex/src/db/rdap-cache.ts
Rene Fichtmueller 2ab48972c5 refactor: Replace external RPKI/BGP APIs with local PostgreSQL database queries
- Create local-db-client.js with consolidated database client module (11 functions)
- Refactor validateRPKIWithCache() to query local rpki_roas table (<10ms vs 1-2s external)
- Update /api/health endpoint to determine health from local DB statistics
- Update /api/prefix-detail endpoint to use async validateRPKIWithCache()
- Update /api/prefix-changes endpoint with RPKI status lookup from local DB
- Create /api/bgp endpoint with local BGP routes + threat intelligence lookup
- Add bgp_routes, rpki_roas, threat_intel statistics to health response
- Zero external API calls for RPKI/BGP validation queries

Impact: Sub-100ms latency for all lookups, 0 token spend on BGP/RPKI/threat intel

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-04-28 21:41:01 +02:00

69 lines
1.9 KiB
TypeScript

/**
* Redis-based RDAP caching layer
* Caches RDAP lookups with 1-hour TTL to reduce external RIR queries
* Target: 60% hit rate on repeated lookups within same session
*/
interface RedisClient {
get(key: string): Promise<string | null>;
set(key: string, value: string, ex?: number): Promise<void>;
del(key: string): Promise<number>;
}
let redisClient: RedisClient | null = null;
export function initRedisCache(client: RedisClient): void {
redisClient = client;
console.log('[RDAP Cache] Redis client initialized');
}
const RDAP_CACHE_TTL = 3600; // 1 hour
export async function getRdapCached(resource: string): Promise<any | null> {
if (!redisClient) return null;
const cacheKey = `rdap:${resource}`;
try {
const cached = await redisClient.get(cacheKey);
if (cached) {
console.log(`[RDAP Cache] HIT: ${resource}`);
return JSON.parse(cached);
}
} catch (error) {
console.error('[RDAP Cache] Error reading cache:', error);
}
return null;
}
export async function setRdapCached(resource: string, data: any): Promise<void> {
if (!redisClient) return;
const cacheKey = `rdap:${resource}`;
try {
await redisClient.set(cacheKey, JSON.stringify(data), RDAP_CACHE_TTL);
console.log(`[RDAP Cache] SET: ${resource} (TTL: ${RDAP_CACHE_TTL}s)`);
} catch (error) {
console.error('[RDAP Cache] Error writing cache:', error);
}
}
export async function clearRdapCache(resource: string): Promise<void> {
if (!redisClient) return;
const cacheKey = `rdap:${resource}`;
try {
await redisClient.del(cacheKey);
console.log(`[RDAP Cache] DELETED: ${resource}`);
} catch (error) {
console.error('[RDAP Cache] Error deleting cache:', error);
}
}
export function getCacheStats() {
if (!redisClient) {
return { status: 'disabled', message: 'Redis client not initialized' };
}
return { status: 'enabled', ttl_seconds: RDAP_CACHE_TTL };
}