-
Notifications
You must be signed in to change notification settings - Fork 2
Implement fuzzy refresh middleware for caching #31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@copilot 通过以下需求描述,实现 Caching 中间件 Fuzzy refresh 在大规模缓存系统中,严格基于 TTL / Expires 的刷新策略会导致两个典型问题: Fuzzy Refresh = 对缓存有效期引入可控随机性 + 提前刷新概率机制 刷新模型
soft_ttl = hard_ttl * fuzzy_ratio 例如: 刷新触发策略(概率驱动) 在
|
Co-authored-by: sendya <[email protected]>
Co-authored-by: sendya <[email protected]>
Co-authored-by: sendya <[email protected]>
Co-authored-by: sendya <[email protected]>
I've successfully implemented the fuzzy refresh middleware for caching. Here's a summary of the implementation: Key Features Implemented✅ Soft TTL Calculation: ConfigurationThe feature is enabled with: fuzzy_refresh: true
fuzzy_refresh_rate: 0.8 # Valid range: (0, 1.0]Example BehaviorWith
The implementation prevents cache stampede by distributing refresh requests over time and eliminates refresh jitter across edge nodes. Commit: 33bfe1e |
|
@copilot 不要修改 .gitignore |
Co-authored-by: sendya <[email protected]>
There was a problem hiding this 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 implements fuzzy refresh middleware for the caching system to prevent cache stampede and refresh jitter issues in large-scale distributed cache scenarios. The implementation adds probabilistic background cache revalidation that occurs before hard expiration, reducing synchronized cache misses and upstream load spikes.
Changes:
- Adds fuzzy refresh logic with configurable soft TTL calculation and linear probability-based refresh triggering
- Implements async background revalidation with proper handling of 304 Not Modified and 200 OK responses
- Adds comprehensive test coverage for soft TTL calculation, probability distribution, and boundary conditions
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| server/middleware/caching/caching_revalidate.go | Implements core fuzzy refresh logic including soft TTL calculation, probability-based refresh triggers, and async background revalidation |
| server/middleware/caching/caching_fuzzy_test.go | Adds comprehensive unit tests for fuzzy refresh functionality including edge cases and probability distribution validation |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if fuzzyRate <= 0 || fuzzyRate > 1 { | ||
| fuzzyRate = 0.8 // default to 0.8 if invalid | ||
| } |
Copilot
AI
Jan 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Silent fallback to default value masks configuration errors. Consider logging a warning when invalid fuzzy_rate values are detected to help with debugging and configuration validation.
| elapsed := float64(now - softTTL) | ||
| probability := elapsed / totalWindow | ||
|
|
||
| // Random trigger based on probability using math/rand/v2 which is thread-safe |
Copilot
AI
Jan 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While math/rand/v2 is thread-safe for concurrent use, consider documenting this thread-safety assumption in a comment since shouldTriggerFuzzyRefresh is called from multiple goroutines via the async refresh mechanism.
| // Random trigger based on probability using math/rand/v2 which is thread-safe | |
| // Random trigger based on probability. | |
| // Note: This relies on math/rand/v2's documented guarantee of being safe for concurrent use, | |
| // because shouldTriggerFuzzyRefresh may be called from multiple goroutines via async refresh. |
| time.Unix(hardTTL, 0).Format(time.DateTime)) | ||
|
|
||
| // Trigger async revalidation in background | ||
| go r.asyncRevalidate(c, req) |
Copilot
AI
Jan 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unbounded goroutine spawning could lead to resource exhaustion under high load. Consider using a worker pool or rate limiting mechanism to cap concurrent background refresh operations per cache key.
| // asyncRevalidate performs background revalidation for fuzzy refresh | ||
| func (r *RevalidateProcessor) asyncRevalidate(c *Caching, req *http.Request) { | ||
| // Create a background context with timeout | ||
| ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) | ||
| defer cancel() | ||
|
|
Copilot
AI
Jan 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 30-second timeout is hardcoded. Consider making this configurable through CachingOptions to allow tuning based on upstream latency characteristics.
| // asyncRevalidate performs background revalidation for fuzzy refresh | |
| func (r *RevalidateProcessor) asyncRevalidate(c *Caching, req *http.Request) { | |
| // Create a background context with timeout | |
| ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) | |
| defer cancel() | |
| const defaultAsyncRevalidateTimeout = 30 * time.Second | |
| // asyncRevalidate performs background revalidation for fuzzy refresh | |
| func (r *RevalidateProcessor) asyncRevalidate(c *Caching, req *http.Request) { | |
| // Create a background context with timeout or inherit existing deadline | |
| baseCtx := context.Background() | |
| var ( | |
| ctx context.Context | |
| cancel context.CancelFunc | |
| ) | |
| if deadline, ok := req.Context().Deadline(); ok { | |
| // Honor any existing deadline from the incoming request | |
| ctx, cancel = context.WithDeadline(baseCtx, deadline) | |
| } else { | |
| // Fall back to the default async revalidation timeout | |
| ctx, cancel = context.WithTimeout(baseCtx, defaultAsyncRevalidateTimeout) | |
| } | |
| defer cancel() |
Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.