Feat: Introdue cache interface.#131
Conversation
There was a problem hiding this comment.
All reported issues were addressed across 2 files
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #131 +/- ##
==========================================
+ Coverage 88.44% 88.53% +0.08%
==========================================
Files 92 93 +1
Lines 4805 4841 +36
==========================================
+ Hits 4250 4286 +36
- Misses 366 367 +1
+ Partials 189 188 -1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
1 issue found across 1 file (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="cache/map_test.go">
<violation number="1" location="cache/map_test.go:40">
P3: The 3-second `time.Sleep` at line 40 adds a hard delay to every test run. Consider reducing the TTL to e.g. 100ms and sleeping only ~150ms to test expiry, or testing the expiry behavior directly via `memoryCache.IsExpired()` without wall-clock waiting.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
| store.Put("test", "test data", time.Second*2) | ||
| store.Put("test2", "test data", 0) | ||
| store.Put("test3", "test data", -1) | ||
| time.Sleep(3 * time.Second) |
There was a problem hiding this comment.
P3: The 3-second time.Sleep at line 40 adds a hard delay to every test run. Consider reducing the TTL to e.g. 100ms and sleeping only ~150ms to test expiry, or testing the expiry behavior directly via memoryCache.IsExpired() without wall-clock waiting.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At cache/map_test.go, line 40:
<comment>The 3-second `time.Sleep` at line 40 adds a hard delay to every test run. Consider reducing the TTL to e.g. 100ms and sleeping only ~150ms to test expiry, or testing the expiry behavior directly via `memoryCache.IsExpired()` without wall-clock waiting.</comment>
<file context>
@@ -0,0 +1,78 @@
+ store.Put("test", "test data", time.Second*2)
+ store.Put("test2", "test data", 0)
+ store.Put("test3", "test data", -1)
+ time.Sleep(3 * time.Second)
+ Expect(store.Get("test")).Should(BeNil())
+ Expect(store.Get("test2")).Should(Equal("test data"))
</file context>
There was a problem hiding this comment.
The delay is intentional in this test because the goal is to validate the end-to-end cache behavior rather than just the expiration check. If we only test IsExpired() directly, we wouldn't be exercising the complete cache workflow that this test is intended to cover, so I'd prefer to keep this.
Signed-off-by: kash2104 <kparikh1104@gmail.com>
Signed-off-by: kash2104 <kparikh1104@gmail.com>
Signed-off-by: kash2104 <kparikh1104@gmail.com>
Signed-off-by: kash2104 <kparikh1104@gmail.com>
Phase 1 change requestFraming this as Phase 1: move the existing cache into pkg and point every consumer at it. LRU is Phase 2, so nothing below asks for LRU here. The Phase 1 goal is one cache, in pkg, with no duplicate left behind. What this PR needs:
Not for this PR, just so the interface does not box us in later: Phase 2 (the LRU work) will need byte accounting, an |
| // Cache interface defines the methods for a cache implementation. | ||
| type Cache[K comparable] interface { | ||
| // Get retrieves a value from the cache by key. | ||
| Get(key K) (value interface{}, expired bool) |
There was a problem hiding this comment.
The second return being expired (not found) is a footgun. sync.Map.Load and idiomatic Go caches return (value, found), so consumers naturally write if v, ok := Get(k); ok. With expired, that reads backwards and silently disables the caller's logic. This already bit workflow #240 (line 141). Please make it (value, found):
| Get(key K) (value interface{}, expired bool) | |
| Get(key K) (value interface{}, found bool) |
and invert the check inside MemoryCacheStore.Get (line 101) accordingly (return data, true on a live hit, return nil, false when absent or expired).
There was a problem hiding this comment.
Have updated the Get function to return value, found
Phase 1 wrap-up (all three PRs)Since this package is the foundation the other two PRs build on, capturing the Phase 1 endgame in one place so the sequencing is clear. Phase 1 is done when there is a single cache in Merge order and remaining work across the three PRs:
Acceptance check for the whole of Phase 1: |
|
@cubic-dev-ai review |
@roguepikachu I have started the AI code review. It will take a few minutes to complete. |
There was a problem hiding this comment.
All reported issues were addressed across 3 files
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
roguepikachu
left a comment
There was a problem hiding this comment.
The implementation now correctly returns a found boolean, but the interface still declares Get(key K) (value interface{}, expired bool) in cache/cache.go. That named result documents the opposite contract and leaves the original consumer trap in place. Please rename expired to found so the interface and implementation agree.
Local validation at 56785c5: go test ./cache and go vet ./cache both pass.
| // Cache interface defines the methods for a cache implementation. | ||
| type Cache[K comparable] interface { | ||
| // Get retrieves a value from the cache by key. | ||
| Get(key K) (value interface{}, expired bool) |
There was a problem hiding this comment.
This named return still says expired, but the implementation now returns true for a live hit. Please rename it to found so the public contract documents the corrected semantics and does not recreate the inversion trap for consumers.
Signed-off-by: kash2104 <kparikh1104@gmail.com>
|
Thank you for your contribution @kash2104 ! |
This PR introduces a generic Cache interface (Put/Get/Delete) package, decoupling consumers from concrete implementations and making a reusable package across KubeVela repo. This enables swapping backends (sync.Map, hashicorp/golang-lru, etc.) without touching consumer code.
The first implementation,
MemoryCache, uses sync.Mapwith per-entry TTL and a background eviction goroutine (migrated from thekubevela/kubevela/pkg/utils/cache.gowith identical behaviour).Summary by cubic
Introduce a generic
cache.Cacheand in-memoryMemoryCacheStorewith per-entry TTL and background eviction. Uses a simple Get/Put/Delete API withfoundsemantics and context-aware cleanup.cache.Cache[K comparable]withGet(key) (value, found),Put(key, value, expiration), andDelete(key).MemoryCacheStoreusingsync.Map, a 3s sweep interval, and context-aware shutdown.github.com/onsi/ginkgo/v2andgithub.com/onsi/gomegafor expiration, non-expiring entries, delete, multi-key, and overwrite.Written for commit d0f4239. Summary will update on new commits.