feat: perf + correctness fixes (user_voted N+1, rate limiting, pg FTS, slug cache)#94
Merged
Merged
Conversation
…, slug cache) - list_posts: batch-populate user_voted (was always false in list view) - rate limiting: in-memory per-IP limiter on /auth + /api (closes #43) gated XFF behind RUNGU_TRUST_PROXY; per-bucket prune (no global burst) - postgres: generated tsvector + GIN index replaces unindexed LIKE - get_project_by_slug: 5-min moka cache (hit on most requests) - tests: +6 (user_voted batch, anon, cache invalidation; rate-limit unit)
🔍 Cora AI Code Review✅ No issues found. Code looks good! Review powered by cora-cli · BYOK · MIT |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Four independent perf/correctness improvements.
1.
list_postsuser_voted N+1 (correctness)Board list previously always returned
user_voted: false— onlyGET /posts/{id}set it. Now batch-populated via one indexed query over thevotesPK (SELECT post_id FROM votes WHERE user_id=? AND post_id IN (...)). Replaces the latent N+1.2. Rate limiting (closes #43)
In-memory per-IP fixed-window limiter, no external crate (governor was dropped for MSRV). Two independent limiters:
/auth/*—RUNGU_AUTH_RATE_LIMIT_PER_MIN(default 30)/api/*—RUNGU_RATE_LIMIT_PER_MIN(default 300)0disables.RUNGU_TRUST_PROXYgatesX-Forwarded-For(default false — socket addr). 429 +Retry-After. Per-bucket prune (no global burst reset).3. PostgreSQL FTS
Generated
search_tsv tsvector+ GIN index replaces unindexedLOWER(...) LIKEfull scan. SQLite stays on FTS5. Search path branches on backend via aSearchenum.4. Project-by-slug cache
get_project_by_slughit on nearly every request → now served from a 5-min TTLmokacache. Create/update/delete invalidate.Notes
Checklist