Skip to content

feat(core): Discord REST caching proxy — poller, cache, HTTP server#9

Merged
bakeb7j0 merged 1 commit into
mainfrom
feature/3-core-proxy
Apr 2, 2026
Merged

feat(core): Discord REST caching proxy — poller, cache, HTTP server#9
bakeb7j0 merged 1 commit into
mainfrom
feature/3-core-proxy

Conversation

@bakeb7j0
Copy link
Copy Markdown
Contributor

@bakeb7j0 bakeb7j0 commented Apr 2, 2026

Summary

Implements the core of scream-hole: a single poller fetches channels and messages from Discord on a configurable interval, stores them in an in-memory cache with snowflake-based eviction, and serves them via Discord-compatible REST endpoints.

Changes

  • discord.ts — Authenticated Discord REST client with injectable fetch, rate limit retry (proper Retry-After: 0 handling)
  • cache.ts — In-memory cache with snowflake ID filtering, TTL-based staleness tracking, 4h rolling window eviction, merge-on-update dedup
  • poller.ts — Polling loop with per-channel (10s) and total (30s) timeouts, error isolation per channel
  • index.ts — HTTP proxy routes: /health, /api/v10/guilds/{id}/channels, /api/v10/channels/{id}/messages with after required, limit validation, X-Cache HIT/STALE headers
  • config.ts — Added cacheTtlMs (poll × 1.5) and cacheWindowMs (4h default)
  • 44 tests across 5 files (cache: 14, discord: 5, poller: 6, routes: 12, config: 7)

Test Plan

  • bun test — 44 pass, 0 fail, 110 assertions
  • bunx tsc --noEmit — clean
  • bun run lint — clean
  • Code reviewer: 4 high-risk findings fixed (snowflake validation, Retry-After edge case, X-Cache staleness, limit validation), 1 deferred

Closes #3

🤖 Generated with Claude Code

Implements the core proxy: a single poller fetches channels and messages
from Discord on a configurable interval, stores them in an in-memory cache
with snowflake-based eviction (4h window), and serves them via
Discord-compatible REST endpoints.

Key decisions:
- `after` parameter required on messages endpoint (prevents full-history dumps)
- Cache TTL = poll interval × 1.5 for staleness tracking
- X-Cache header reports HIT/STALE based on TTL freshness
- Input validation on `after` (must be numeric snowflake) and `limit` (positive int)
- Injectable fetch in Discord client for testability

44 tests across 5 files, 110 assertions.

Closes #3

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@bakeb7j0 bakeb7j0 merged commit 0a9f72a into main Apr 2, 2026
4 checks passed
@bakeb7j0 bakeb7j0 deleted the feature/3-core-proxy branch April 2, 2026 21:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Core proxy — polling loop, cache, HTTP server

1 participant