Skip to content

🧹 chore: Improve Cache middleware defaults#3740

Merged
ReneWerner87 merged 4 commits intomainfrom
update-cachecontrol-to-true-across-files
Sep 13, 2025
Merged

🧹 chore: Improve Cache middleware defaults#3740
ReneWerner87 merged 4 commits intomainfrom
update-cachecontrol-to-true-across-files

Conversation

@gaby
Copy link
Member

@gaby gaby commented Sep 11, 2025

Summary

  • Enable CacheControl by default
  • Set default timeout to 5m from 1m
  • Set default maxbytes to 1M
  • Replace sleep with time ticker to avoid time drift

Replaced #3726

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 11, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Renames CacheControl to DisableCacheControl in the cache middleware Config, changes default Expiration to 5m and MaxBytes to 1 MiB, updates docs and tests to match, replaces a busy-wait timestamp loop with a ticker, and adds tests for Cache-Control emission/omission.

Changes

Cohort / File(s) Summary
Docs: Cache middleware
docs/middleware/cache.md
Updated top note and default config snippet to Expiration = 5m and MaxBytes = 1 MiB; replaced CacheControl docs with DisableCacheControl (describes omission of Cache-Control when true); clarified KeyGenerator wording and noted ExpirationGenerator/Storage/StoreResponseHeaders.
Config: defaults & API
middleware/cache/config.go
Renamed public field CacheControl boolDisableCacheControl bool; updated comments and defaults: Expiration 1m → 5m, MaxBytes 0 → 1 * 1024 * 1024, DisableCacheControl default = false; updated ConfigDefault.
Runtime: timestamp updater
middleware/cache/cache.go
Replaced busy-wait loop with time.NewTicker(timestampUpdatePeriod) and defer ticker.Stop(); updates timestamp on ticker.C ticks. Also changed Cache-Control emission to be conditional on !cfg.DisableCacheControl.
Tests: Cache-Control behavior & configs
middleware/cache/cache_test.go
Reworked many test Config literals to remove/replace CacheControl with DisableCacheControl or rely on Expiration; added tests asserting Cache-Control emitted when enabled and omitted when DisableCacheControl=true; updated assertions and test setups accordingly.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant App as App
  participant MW as CacheMiddleware
  participant Store as CacheStorage
  participant Ticker as TimestampTicker

  rect #E8F0FF
  note right of MW: Initialization (changed)
  App->>MW: Initialize middleware
  MW->>Ticker: time.NewTicker(timestampUpdatePeriod)
  Ticker-->>MW: tick events on ticker.C
  MW->>MW: update internal timestamp on tick
  end

  rect #F0FFF0
  note right of MW: Request handling (Cache-Control conditional)
  App->>MW: HTTP Request
  MW->>Store: Lookup(key)
  alt Hit
    Store-->>MW: Cached response
    MW-->>App: Return cached response (sets Cache-Control if !cfg.DisableCacheControl)
  else Miss
    MW->>App: Call next handler
    App-->>MW: Response
    MW->>Store: Store response (respect MaxBytes)
    MW-->>App: Return response (sets Cache-Control if !cfg.DisableCacheControl)
  end
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • sixcolors
  • ReneWerner87
  • efectn

Pre-merge checks (1 passed, 2 warnings)

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The current description is minimal and does not follow the repository template: it omits a "Fixes #" reference, the detailed "Changes introduced" section and checklist items (benchmarks, docs, changelog, migration guide), a Type of change selection, and it fails to document the breaking API rename (CacheControl → DisableCacheControl) or provide migration steps. Please update the PR description to match the repository template: state the purpose and any related issue(s) (Fixes #), expand "Changes introduced" with explicit entries for documentation updates, tests, and changelog notes, add a migration guide describing how users should adapt to CacheControl → DisableCacheControl (with code examples), mark the Type of change, and complete the checklist items (benchmarks/docs/tests) so reviewers can verify the scope and impact.
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Title Check ✅ Passed The title concisely summarizes the PR's primary intent — improving cache middleware defaults — and is short, relevant, and easy for a teammate scanning history to understand.

Poem

I twitch my whiskers, start the tick—
Five minutes warm, one meg to pick.
Headers hush when told to hide,
Tests hop in to check the tide.
A rabbit nods: the cache feels slick. 🐇


📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6056515 and bd5da21.

📒 Files selected for processing (4)
  • docs/middleware/cache.md (3 hunks)
  • middleware/cache/cache.go (2 hunks)
  • middleware/cache/cache_test.go (5 hunks)
  • middleware/cache/config.go (2 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Format Go code using gofumpt (enforced via make format)
Ensure code passes golangci-lint checks (enforced via make lint)
Optimize struct field alignment using betteralign (enforced via make betteralign)
Modernize Go code using gopls modernize (enforced via make modernize)

Files:

  • middleware/cache/cache.go
  • middleware/cache/config.go
  • middleware/cache/cache_test.go
docs/**

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Review and update the contents of the docs folder if necessary when modifying code

Files:

  • docs/middleware/cache.md
🧠 Learnings (1)
📚 Learning: 2024-10-08T19:06:06.583Z
Learnt from: hcancelik
PR: gofiber/fiber#3036
File: docs/middleware/cache.md:103-103
Timestamp: 2024-10-08T19:06:06.583Z
Learning: There are no hard tabs in the lines 100 to 105 of the `docs/middleware/cache.md` file. Future comments about formatting should accurately reflect the actual content.

Applied to files:

  • docs/middleware/cache.md
🧬 Code graph analysis (1)
middleware/cache/cache_test.go (2)
middleware/cache/cache.go (1)
  • New (68-303)
middleware/cache/config.go (1)
  • Config (11-75)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: unit (1.25.x, windows-latest)
  • GitHub Check: unit (1.25.x, macos-latest)
  • GitHub Check: repeated
  • GitHub Check: Compare
🔇 Additional comments (14)
docs/middleware/cache.md (3)

9-9: LGTM! Helpful introductory note added.

The new introduction clearly communicates the default cache settings (5 minutes expiration, 1 MB storage) to users before they dive into the details.


72-72: LGTM! Example updated to use the new field name.

The example correctly demonstrates the use of DisableCacheControl: true instead of the old CacheControl: false.


126-141: LGTM! Default configuration updated correctly.

All the default values are correctly updated to reflect the new defaults:

  • Expiration: 5 * time.Minute (increased from 1 minute)
  • DisableCacheControl: false (replaces CacheControl: true)
  • MaxBytes: 1 * 1024 * 1024 (increased from 0)
middleware/cache/config.go (4)

55-56: LGTM! Comment updated to reflect new default.

The comment correctly shows the new default expiration of 5 minutes instead of the previous 1 minute.


62-63: LGTM! Comment updated to reflect new default.

The comment correctly shows the new default MaxBytes of 1 MB instead of the previous 0 (no limit).


65-68: LGTM! Field renamed with clearer semantics.

The renaming from CacheControl to DisableCacheControl provides much clearer semantics - setting it to true disables client-side caching by omitting the Cache-Control header. The comment accurately describes this behavior.


79-91: LGTM! ConfigDefault values updated correctly.

All the default values are correctly updated to match the documented changes:

  • Expiration: 5 * time.Minute
  • DisableCacheControl: false
  • MaxBytes: 1 * 1024 * 1024

The field ordering and formatting are also clean and consistent.

middleware/cache/cache.go (2)

93-98: LGTM! Ticker-based timestamp updates prevent time drift.

The replacement of the busy-wait loop with time.NewTicker(timestampUpdatePeriod) is an excellent improvement. This approach:

  1. Eliminates the potential for time drift that could occur with sleep-based loops
  2. Uses a more idiomatic Go pattern for periodic tasks
  3. Properly handles cleanup with defer ticker.Stop()

167-171: LGTM! Updated logic to use new DisableCacheControl field.

The Cache-Control header logic correctly uses !cfg.DisableCacheControl to determine whether to emit the header. The condition also properly checks if the header is already set to avoid overwriting existing values, which maintains backward compatibility.

middleware/cache/cache_test.go (5)

24-41: LGTM! New test verifies Cache-Control header emission.

This test correctly verifies that when using the default configuration (with DisableCacheControl: false), the Cache-Control header is properly emitted with the expected max-age value.


43-63: LGTM! New test verifies Cache-Control header suppression.

This test correctly verifies that when DisableCacheControl: true is set, no Cache-Control header is emitted, confirming the new functionality works as intended.


363-364: LGTM! Test updated to focus on expiration settings.

The test now properly focuses on testing the expiration behavior rather than the removed CacheControl field, which aligns with the API changes.


902-905: LGTM! Test configuration cleaned up.

The test configuration has been appropriately updated to remove the obsolete CacheControl field and focus on the relevant storage and MaxBytes configuration.


1153-1153: LGTM! Test simplified by removing redundant field.

The test correctly removes the now-redundant explicit CacheControl setting since DisableCacheControl defaults to false (enabling Cache-Control headers by default).

✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch update-cachecontrol-to-true-across-files

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.

@gaby gaby changed the title Enable Cache-Control by default and raise cache defaults 🧹 chore: Improve Cache middleware defaults Sep 11, 2025
@codecov
Copy link

codecov bot commented Sep 11, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.02%. Comparing base (4f5c1a5) to head (bd5da21).
⚠️ Report is 186 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3740   +/-   ##
=======================================
  Coverage   92.02%   92.02%           
=======================================
  Files         115      115           
  Lines       11585    11586    +1     
=======================================
+ Hits        10661    10662    +1     
  Misses        670      670           
  Partials      254      254           
Flag Coverage Δ
unittests 92.02% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@gaby gaby added this to v3 Sep 11, 2025
@gaby gaby added this to the v3 milestone Sep 11, 2025
@gaby gaby moved this to In Progress in v3 Sep 11, 2025
@gaby gaby marked this pull request as ready for review September 11, 2025 14:38
@gaby gaby requested a review from a team as a code owner September 11, 2025 14:38
@gaby gaby requested review from ReneWerner87, Copilot, efectn and sixcolors and removed request for Copilot September 11, 2025 14:38
@gaby
Copy link
Member Author

gaby commented Sep 11, 2025

/gemini review

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 improves the default configuration for the cache middleware by enabling CacheControl by default, increasing the default expiration time to 5 minutes, and setting a default MaxBytes limit of 1MB. It also correctly replaces time.Sleep with a time.Ticker for timestamp updates to prevent time drift. The code changes and test updates are solid. I've found a significant issue in the documentation where two configuration options were accidentally removed from the configuration table, and I've also noted some formatting issues in the same table, for which I've provided a suggestion.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
middleware/cache/config.go (2)

62-69: Defaults for MaxBytes and CacheControl: code vs. runtime behavior mismatch

You updated comments/defaults to 1 MiB and true, but configDefault(...) does not populate these when a partial Config literal is passed (common usage). That means:

  • New() → CacheControl=true, MaxBytes=1MiB
  • New(Config{...}) (omit) → CacheControl=false, MaxBytes=0 (unlimited)

This is surprising given the docs. Two options:

  • Short term (docs): clearly document that omitted fields in a provided literal take Go zero-values and must be explicitly set to match defaults.
  • Long term (API): consider tri-state config (e.g., CacheControl *bool, MaxBytes *uint) or a sentinel for unlimited to let configDefault apply real defaults without breaking explicit false/0.

If you want, I can draft a non-breaking docs note now and an RFC for tri-state in v3.


101-121: configDefault doesn’t apply new defaults to MaxBytes/CacheControl

Consider whether you want defaults to apply when users pass a partial Config. If yes, you’ll need a tri-state approach for bool/uint (breaking) or companion flags (e.g., MaxBytesUnlimited bool) to preserve “0 means unlimited” while still defaulting to 1 MiB when omitted. Otherwise, add a prominent doc note (see docs comment).

middleware/cache/cache.go (1)

93-96: Ticker-based timestamp updater — LGTM; consider lifecycle

Using time.Ticker avoids drift. Minor: the goroutine has no shutdown path, so defer ticker.Stop() won’t run. Optional: tie ticker to app lifecycle or a done channel for clean shutdowns in long-lived tests.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4f5c1a5 and 50f40c1.

📒 Files selected for processing (4)
  • docs/middleware/cache.md (2 hunks)
  • middleware/cache/cache.go (1 hunks)
  • middleware/cache/cache_test.go (7 hunks)
  • middleware/cache/config.go (2 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Format Go code using gofumpt (enforced via make format)
Ensure code passes golangci-lint checks (enforced via make lint)
Optimize struct field alignment using betteralign (enforced via make betteralign)
Modernize Go code using gopls modernize (enforced via make modernize)

Files:

  • middleware/cache/config.go
  • middleware/cache/cache_test.go
  • middleware/cache/cache.go
docs/**

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Review and update the contents of the docs folder if necessary when modifying code

Files:

  • docs/middleware/cache.md
🧬 Code graph analysis (2)
middleware/cache/config.go (2)
internal/memory/memory.go (1)
  • Storage (12-15)
internal/storage/memory/memory.go (1)
  • Storage (14-19)
middleware/cache/cache_test.go (1)
middleware/cache/config.go (1)
  • Config (11-75)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Compare
  • GitHub Check: repeated
🔇 Additional comments (13)
middleware/cache/cache_test.go (7)

31-31: Good test improvement!

Moving CacheControl: true to the end ensures the test focuses on the core functionality while maintaining proper field ordering.


46-66: Excellent test coverage for disabled CacheControl!

This new test ensures that when CacheControl: false is set, no Cache-Control header is emitted. This validates the correct behavior when users explicitly disable client-side caching.


366-366: LGTM!

The test properly uses only the Expiration field, which is appropriate since the default CacheControl: true from the updated defaults will be used.


819-819: LGTM!

The field reordering maintains consistency across tests while preserving the intended behavior.


875-876: LGTM!

The field reordering is consistent with the overall improvements and maintains test functionality.


911-911: LGTM!

The field placement maintains consistency across the test suite.


1160-1160: LGTM!

The config correctly uses explicit field values, which is appropriate for this test that needs to control specific behavior.

middleware/cache/config.go (2)

55-56: Default Expiration: 5m — LGTM

Doc + default value align and are reasonable for typical cache workloads.


80-92: ConfigDefault updates — LGTM, but ensure tests cover “partial config” edge

Values match the new policy. Please add/adjust tests to assert:

  • New() uses CacheControl=true, MaxBytes=1MiB
  • New(Config{Expiration: X}) keeps CacheControl=false and MaxBytes=0 unless explicitly set
    This makes the behavior explicit and prevents regressions.
docs/middleware/cache.md (2)

9-10: Top-level defaults text — LGTM

Matches code: 5 minutes and ~1 MB.


124-139: Default Config snippet — LGTM

Matches middleware/cache/config.go.

middleware/cache/cache.go (2)

168-171: Cache-Control emission logic — LGTM

Header is set only on hits, only when enabled, and only if not already present; preserves server intent.


269-279: Expiration/TTL math — LGTM

Seconds precision with periodic timestamp refresh is consistent with max-age/Age semantics.

Copilot AI review requested due to automatic review settings September 11, 2025 15:12
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR improves the Cache middleware defaults to provide better out-of-the-box performance and behavior for caching functionality in Fiber applications.

  • Enable CacheControl by default to provide client-side caching headers
  • Increase default timeout from 1 minute to 5 minutes for longer cache retention
  • Set default MaxBytes to 64MB to prevent unbounded memory usage
  • Replace sleep-based timestamp updates with time.Ticker to prevent time drift

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.

File Description
middleware/cache/config.go Updates default configuration values for expiration, CacheControl, and MaxBytes
middleware/cache/cache_test.go Adds test for disabled CacheControl and updates existing tests to reflect new defaults
middleware/cache/cache.go Replaces sleep loop with time.Ticker for timestamp updates
docs/middleware/cache.md Updates documentation to reflect new default values and adds description of default behavior

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
docs/middleware/cache.md (1)

112-116: Defaults update looks correct; missing prior omissions are now covered

Expiration=5m and CacheControl=true reflected; KeyGenerator and CacheInvalidator rows restored. Nice.

🧹 Nitpick comments (4)
docs/middleware/cache.md (4)

9-10: Unify size unit (1 MiB) for consistency with defaults

Top note says “1 MB” while the table uses 1 * 1024 * 1024 (~1 MB). Recommend “1 MiB (~1 MB)” to avoid ambiguity.

-By default, cached responses expire after five minutes and the middleware stores up to 1 MB of response bodies.
+By default, cached responses expire after five minutes and the middleware stores up to 1 MiB (~1 MB) of response bodies.

109-122: Add a note about zero-values when passing partial Config literals

Readers may assume documented defaults apply when only some fields are set. Clarify that omitted fields take Go zero-values.

 | Methods              | `[]string`                                     | Methods specifies the HTTP methods to cache.                                                                                                                                                                                                                                                                   | `[]string{fiber.MethodGet, fiber.MethodHead}`                    |
 |
+> Note: When passing a partial `cache.Config` literal to `cache.New(...)`, omitted fields take Go zero-values
+> (e.g., `CacheControl` becomes `false`, `MaxBytes` becomes `0`). To keep the documented defaults while
+> customizing, either set them explicitly (e.g., `CacheControl: true`, `MaxBytes: 1*1024*1024`) or start from
+> `cfg := cache.ConfigDefault` and override only what you need.

114-114: Specify exact header semantics for CacheControl=true

Document what header is emitted (e.g., “Cache-Control: public, max-age=”) and how its value relates to Expiration/ExpirationGenerator.

-| CacheControl         | `bool`                                          | CacheControl enables client-side caching if set to true. Set to `false` to omit the `Cache-Control` header. | `true`                                                          |
+| CacheControl         | `bool`                                          | When `true`, emits a `Cache-Control` response header (max-age equals the effective expiration). Set to `false` to omit the header. | `true`                                                          |

120-120: Clarify behavior when MaxBytes is reached

Does the middleware evict entries (LRU/size-based) or skip writing new ones? Add one sentence describing the policy.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 50f40c1 and 6056515.

📒 Files selected for processing (1)
  • docs/middleware/cache.md (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
docs/**

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Review and update the contents of the docs folder if necessary when modifying code

Files:

  • docs/middleware/cache.md
🧠 Learnings (1)
📚 Learning: 2024-10-08T19:06:06.583Z
Learnt from: hcancelik
PR: gofiber/fiber#3036
File: docs/middleware/cache.md:103-103
Timestamp: 2024-10-08T19:06:06.583Z
Learning: There are no hard tabs in the lines 100 to 105 of the `docs/middleware/cache.md` file. Future comments about formatting should accurately reflect the actual content.

Applied to files:

  • docs/middleware/cache.md
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Analyse
  • GitHub Check: unit (1.25.x, macos-latest)
  • GitHub Check: unit (1.25.x, windows-latest)
  • GitHub Check: unit (1.25.x, macos-13)
  • GitHub Check: repeated
  • GitHub Check: Compare
🔇 Additional comments (1)
docs/middleware/cache.md (1)

128-139: Default Config snippet aligns with stated defaults

Values for Expiration, CacheControl, and MaxBytes match the table and summary.

@gaby
Copy link
Member Author

gaby commented Sep 11, 2025

/gemini review

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 introduces sensible improvements to the cache middleware's default settings, such as enabling CacheControl by default, increasing the expiration time, and setting a MaxBytes limit. The switch from time.Sleep to time.Ticker is a great enhancement for accuracy. The changes are well-reflected in the documentation and tests. I have one minor suggestion to improve the documentation's formatting.

@ReneWerner87 ReneWerner87 merged commit aedffa1 into main Sep 13, 2025
15 checks passed
@ReneWerner87 ReneWerner87 deleted the update-cachecontrol-to-true-across-files branch September 13, 2025 16:25
@github-project-automation github-project-automation bot moved this from In Progress to Done in v3 Sep 13, 2025
Abhirup-99 pushed a commit to Abhirup-99/fiber that referenced this pull request Nov 3, 2025
* Make CacheControl boolean

* docs(cache): align defaults with config

* Limit cache entries to 1MB and restore docs

* Rename cache control option
@gaby gaby added the 📜 RFC Compliance Feature, implementation, or contribution adheres to relevant RFC standards. label Nov 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

codex 📜 RFC Compliance Feature, implementation, or contribution adheres to relevant RFC standards. 🧹 Updates v3

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants