Skip to content

fix(api): tighten user search cache behavior#140

Merged
is0692vs merged 5 commits intomainfrom
split/pr138-users-cache
Mar 18, 2026
Merged

fix(api): tighten user search cache behavior#140
is0692vs merged 5 commits intomainfrom
split/pr138-users-cache

Conversation

@is0692vs
Copy link
Contributor

@is0692vs is0692vs commented Mar 17, 2026

Summary

  • make the user search cache behave like MRU on cache hits and evict expired entries cleanly
  • allow a test-only MAX_CACHE_SIZE override while keeping the default path in the route
  • simplify the focused users route tests so cache eviction stays fast and deterministic

Validation

  • npm run --workspace apps/api test -- src/routes/tests/users.test.ts

Split out of #138 to keep review scoped to the user-search cache behavior.

Greptile Summary

このPRはユーザー検索キャッシュのMRU(Most Recently Used)動作を整備し、テストを高速・決定論的に改善します。getCachedResults での delete+set による Map 末尾再挿入、期限切れエントリの即時削除、および setCachedResults へのテスト用 maxSize オーバーライドが主な変更点です。

  • getCachedResults: キャッシュヒット時に delete+set でエントリをMRU位置(Map末尾)へ昇格。期限切れエントリのみを削除するよう整理(旧実装はキー不在時も delete を呼んでいた)
  • setCachedResults: maxSize? パラメータを追加し、Number.isFinite による検証で安全にデフォルト値(1000)へフォールバック
  • Env: MAX_CACHE_SIZE?: string を追加して TypeScript 型エラーを解消
  • テスト: 1002リクエストから3リクエストに縮小し、中間カウントで各ステップ(キャッシュヒット→昇格→eviction→limit1退去・limit0保持)を個別に検証するよう精度向上

Confidence Score: 4/5

  • 軽微なスタイル上の改善点はあるが、MRUロジックとテストは正確に実装されておりマージ可能
  • MRU実装(Map挿入順を利用した delete+set)は正確で、テストも各ステップを中間カウントで個別検証している。as any キャストの残存と setCachedResults の到達不能ブランチという軽微な問題はあるが、実行時の動作には影響しない
  • users.tssetCachedResultsif (searchCache.has(key)) ブランチの意図明確化

Important Files Changed

Filename Overview
apps/api/src/routes/users.ts MRU昇格(delete+setによるMap末尾再挿入)と期限切れエントリの削除ロジックを正しくリファクタリング。setCachedResultsmaxSizeパラメータを追加。if (searchCache.has(key))ブランチが到達不能な可能性あり(防御的コードとして残されている)。
apps/api/src/routes/tests/users.test.ts MRU昇格を中間カウントで個別検証するように改善。キャッシュサイズを1002→3に削減して高速化。smallEnvas anyキャストがMAX_CACHE_SIZEEnv型追加により不要になっている。
apps/api/src/types.ts MAX_CACHE_SIZE?: stringEnv型に追加。型エラーを解消するための最小限かつ正しい変更。

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["GET /api/users/search?q=xxx"] --> B["getCachedResults(key)"]
    B --> C{"キーが存在?"}
    C -- "No" --> G["DB クエリ実行"]
    C -- "Yes" --> D{"TTL 有効?"}
    D -- "No (期限切れ)" --> E["searchCache.delete(key)"]
    E --> G
    D -- "Yes (有効)" --> F["delete(key) → set(key)\nMRU位置へ昇格"]
    F --> F2["キャッシュデータを返す\n早期リターン"]
    G --> H["setCachedResults(key, data, maxSize?)"]
    H --> I{"searchCache.has(key)?"}
    I -- "Yes (防御的)" --> J["delete(key)"]
    I -- "No (通常パス)" --> K{"size >= effectiveMaxSize?"}
    J --> L["set(key) MRU位置"]
    K -- "Yes" --> M["LRU キーを evict"]
    K -- "No" --> L
    M --> L
    L --> N["レスポンス返却"]
Loading

Comments Outside Diff (2)

  1. apps/api/src/routes/__tests__/users.test.ts, line 260 (link)

    P2 テストコメントが実際の動作と一致していない

    コメントに「setCachedResults which hits if (searchCache.has(key))」と書かれていますが、これは不正確です。getCachedResults は期限切れエントリを検出した際にすでに searchCache.delete(key) を呼び出します。そのため、その後に setCachedResults が呼ばれたとき、searchCache.has(key)false を返し、if (searchCache.has(key)) ブランチにはヒットしません。

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: apps/api/src/routes/__tests__/users.test.ts
    Line: 260
    
    Comment:
    **テストコメントが実際の動作と一致していない**
    
    コメントに「`setCachedResults` which hits `if (searchCache.has(key))`」と書かれていますが、これは不正確です。`getCachedResults` は期限切れエントリを検出した際にすでに `searchCache.delete(key)` を呼び出します。そのため、その後に `setCachedResults` が呼ばれたとき、`searchCache.has(key)`**false** を返し、`if (searchCache.has(key))` ブランチにはヒットしません。
    
    
    
    How can I resolve this? If you propose a fix, please make it concise.
  2. apps/api/src/routes/users.ts, line 98-105 (link)

    P2 searchCache.has(key) ブランチが到達不能な可能性

    このブランチは現在の通常フローでは実行されません。理由は以下のとおりです:

    • キャッシュヒット時getCachedResults がデータを返し、ルートハンドラが早期リターンするため setCachedResults が呼ばれない
    • キャッシュミス / 期限切れ時getCachedResultssearchCache.delete(key) を呼んでからnullを返す → setCachedResults 呼び出し時には has(key)false

    防御的実装として残しておくことは理解できますが、users.test.ts の246行目のテストコメント(「setCachedResults which hits if (searchCache.has(key))」)はこのブランチが実際には通らないため誤解を招きます。コメントを更新するか、このブランチの存在意図をコメントで明示することを検討してください。

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: apps/api/src/routes/users.ts
    Line: 98-105
    
    Comment:
    **`searchCache.has(key)` ブランチが到達不能な可能性**
    
    このブランチは現在の通常フローでは実行されません。理由は以下のとおりです:
    
    - **キャッシュヒット時**`getCachedResults` がデータを返し、ルートハンドラが早期リターンするため `setCachedResults` が呼ばれない
    - **キャッシュミス / 期限切れ時**`getCachedResults``searchCache.delete(key)` を呼んでからnullを返す → `setCachedResults` 呼び出し時には `has(key)``false`
    
    防御的実装として残しておくことは理解できますが、`users.test.ts` の246行目のテストコメント(「`setCachedResults` which hits `if (searchCache.has(key))`」)はこのブランチが実際には通らないため誤解を招きます。コメントを更新するか、このブランチの存在意図をコメントで明示することを検討してください。
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: apps/api/src/routes/__tests__/users.test.ts
Line: 274

Comment:
**`as any` キャストは `createTestEnv` のオーバーライドで代替可能**

`MAX_CACHE_SIZE``Env` 型(および `TestEnv` 型)に追加されたことで、`as any` キャストは不要になりました。`createTestEnv``overrides` 引数を受け取るため、以下のように書き替えることでより型安全になります:

```suggestion
        const smallEnv = createTestEnv({ MAX_CACHE_SIZE: "3" });
```

これにより `TestEnv` に存在しないフィールドを誤って追加してしまうリスクも防げます。

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: apps/api/src/routes/users.ts
Line: 98-105

Comment:
**`searchCache.has(key)` ブランチが到達不能な可能性**

このブランチは現在の通常フローでは実行されません。理由は以下のとおりです:

- **キャッシュヒット時**`getCachedResults` がデータを返し、ルートハンドラが早期リターンするため `setCachedResults` が呼ばれない
- **キャッシュミス / 期限切れ時**`getCachedResults``searchCache.delete(key)` を呼んでからnullを返す → `setCachedResults` 呼び出し時には `has(key)``false`

防御的実装として残しておくことは理解できますが、`users.test.ts` の246行目のテストコメント(「`setCachedResults` which hits `if (searchCache.has(key))`」)はこのブランチが実際には通らないため誤解を招きます。コメントを更新するか、このブランチの存在意図をコメントで明示することを検討してください。

How can I resolve this? If you propose a fix, please make it concise.

Last reviewed commit: f98e430

@vercel
Copy link

vercel bot commented Mar 17, 2026

Deployment failed with the following error:

Resource is limited - try again in 24 hours (more than 100, code: "api-deployments-free-per-day").

Learn More: https://vercel.com/hirokis-projects-afd618c7?upgradeToPro=build-rate-limit

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request refines the user search caching mechanism to improve its efficiency and predictability. It introduces a Most Recently Used (MRU) eviction policy for cache hits and ensures that expired cache entries are promptly removed. Additionally, the cache's maximum size can now be configured, which significantly streamlines testing of cache eviction logic.

Highlights

  • Cache Behavior Enhancement: Implemented a Most Recently Used (MRU) strategy for the user search cache, ensuring that frequently accessed items remain in the cache and expired entries are cleanly evicted.
  • Configurable Cache Size: Introduced an optional maxSize parameter for the cache, allowing the maximum cache size to be overridden, particularly useful for testing scenarios via environment variables.
  • Simplified Cache Eviction Tests: Refactored the user search cache eviction tests to be faster and more deterministic by using a smaller, configurable cache size.
Changelog
  • apps/api/src/routes/tests/users.test.ts
    • Refactored cache eviction test to use a smaller, configurable cache size (3 items) for faster and more deterministic execution.
    • Updated test assertions to verify database call counts after cache eviction and re-requesting an evicted item.
    • Renamed a test description for clarity.
  • apps/api/src/routes/users.ts
    • Modified getCachedResults to re-insert cached items on a hit, promoting them to Most Recently Used (MRU), and to explicitly delete expired entries.
    • Updated setCachedResults to accept an optional maxSize parameter, allowing dynamic configuration of the cache limit.
    • Integrated the MAX_CACHE_SIZE environment variable into the setCachedResults call within the user search route, enabling test-specific cache size overrides.
Activity
  • The pull request was created by is0692vs with the title 'fix(api): tighten user search cache behavior' and a detailed description outlining the summary, validation steps, and context of the changes.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request tightens the user search cache behavior by implementing an MRU policy on cache hits and providing a mechanism to override the cache size for testing. The changes make the cache eviction tests faster and more deterministic. The implementation of the cache logic is sound.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 17, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 36f80ee5-8463-4df7-b56e-acecf3e65c5e

📥 Commits

Reviewing files that changed from the base of the PR and between 7a0d275 and af45d6c.

📒 Files selected for processing (1)
  • apps/api/src/routes/__tests__/users.test.ts

📝 Walkthrough

Summary by CodeRabbit

リリースノート

  • Tests
    • キャッシュ削除シナリオのテストアサーションを改善しました。キャッシュの削除と昇格の動作検証をより正確に行うようにテストを最適化しました。

Walkthrough

キャッシュ削除シナリオに関するテストアサーションを修正し、limit1要求前後、limit0要求前後のDB呼び出しカウントをキャプチャして、削除・昇格動作を正確に検証するようにテストケースを再構成しました。

Changes

コホート / ファイル(s) 概要
ユーザーテスト - キャッシュ検証
apps/api/src/routes/__tests__/users.test.ts
キャッシュ削除/昇格の動作確認用テストアサーションを更新。limit1要求前にcountBeforeLimit1をキャプチャし、その後のmockDb.select呼び出しがちょうど1回増加することを検証。limit1後にcountBeforeLimit0をキャプチャし、limit0要求ではDB呼び出しが増加しないことを確認。

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Suggested labels

size/XXL

Poem

🐰 キャッシュの踊り、くるくる回り
カウント数え、その数増えて
削除・昇格、正しく動き
テストが笑う、バグもさようなら
穏やかなデータベース、幸せな呼び出し

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed タイトルはPRの主要な変更内容(ユーザー検索キャッシュの動作を厳密化)を正確に反映しており、簡潔で明確です。
Description check ✅ Passed 説明はキャッシュのMRU動作、期限切れエントリの削除、テスト用の最大キャッシュサイズオーバーライド、テストの簡略化など、変更内容と密接に関連しています。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch split/pr138-users-cache
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@vercel
Copy link

vercel bot commented Mar 17, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
open-shelf Ignored Ignored Mar 18, 2026 1:25am

@is0692vs is0692vs merged commit 14ad9dc into main Mar 18, 2026
18 checks passed
@is0692vs is0692vs deleted the split/pr138-users-cache branch March 18, 2026 01:38
@codecov
Copy link

codecov bot commented Mar 18, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant