perf: cache webhook secret resolution with a TTL cache - #8041
Open
dejanzele wants to merge 1 commit into
Open
Conversation
Contributor
Greptile SummaryAdds TTL-based caching for webhook secret resolution while preserving mutation consistency.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains; same-revision misses are coalesced, while revision changes isolate post-mutation reads from older in-flight results. Important Files Changed
Sequence DiagramsequenceDiagram
participant W as Webhook listeners
participant C as Cached secret client
participant F as singleflight
participant K as Kubernetes API
W->>C: Concurrent Get(namespace/name)
C->>C: Check TTL cache and capture revision
C->>F: Do(revision/key)
F->>K: One secret read
K-->>F: Secret or not-found
F-->>C: Shared result
C->>C: Cache defensive copy
C-->>W: Independent copies
Note over C: Mutation increments revision and invalidates entries
W->>C: Get after mutation
C->>F: Do(newRevision/key)
F->>K: Fresh secret read
Reviews (4): Last reviewed commit: "refactor(secret): build the secret read ..." | Re-trigger Greptile |
Contributor
Author
Contributor
Author
1 similar comment
Contributor
Author
dejanzele
force-pushed
the
tkc-6252/secret-ttl-cache
branch
from
July 31, 2026 12:30
4f1e15e to
903bbbc
Compare
dejanzele
force-pushed
the
tkc-6252/secret-ttl-cache
branch
from
July 31, 2026 12:45
85975cc to
bab53c7
Compare
courageousillumination
approved these changes
Aug 7, 2026
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.
How
Adds a caching decorator in
pkg/secretand wraps the one client the webhook loader builds. Webhook parameters are resolved on every notification, so an event burst previously turned into one uncached secret GET per event per parameter.Only
GetandGetObjectare cached. Every mutating method passes through to the inner client and invalidates the affected key. Entries are keyed by name plus the namespace the call resolves to, so a read with an explicit namespace and a read that falls back to the default share one entry. Returned maps and objects are copies, so a caller cannot mutate what the cache holds.TESTKUBE_SECRET_CACHE_TTLsets the lifetime and defaults to 30s. A zero value returns the inner client unchanged, which disables caching completely.Missing secrets are cached too, for a third of the TTL, so a webhook pointing at a secret that does not exist does not hammer the API server either. Every other error is treated as possibly transient and is never cached.
A read that started before an invalidation does not repopulate the cache afterwards, so a mutation cannot be overwritten by an older in flight result.
The saving is larger than one read per event.
processTemplaterebuilds the resolved config map for every templated field, so an uncached notification reads the same secret once for the uri, once for the payload and once more for every header. A webhook with a templated uri and a payload resolves it twice per event before this change and once per TTL window after it.Storage is the shared
pkg/cache, rather than another map with an expiry sweep next to it. That package needed two things it did not have:Delete, without which a mutation cannot invalidate what it replaced, and a way to substitute the time source, without which TTL behavior can only be tested by waiting. Both are added here, andClearcomes withDeleteforDeleteAll, which changes secrets it cannot map back to individual keys.What stays in
pkg/secretis the part that is specific to reading secrets: a shorter lifetime for not found results, coalescing of concurrent misses, and the revision that lets a mutation discard reads it superseded.Notes for review
This trades immediacy for request volume, and the staleness bound is worth an explicit decision: rotating a secret takes up to the TTL to reach webhook parameters, and creating a secret that was just looked up and missing takes up to a third of the TTL to become visible. Setting the TTL to zero restores the current behavior for anyone who needs rotation to apply immediately.
This branch includes the
Getclock fix from #8053, since injecting a time source is pointless whileGetreads the wall clock. Merge that first and this diff shrinks accordingly.Widening
cache.Cachetouches every implementer. In this repository that isInMemoryCacheand one test fake inpkg/imageinspector, both updated here.The decorator is applied at exactly one construction site. Other
pkg/secretcallers are unchanged, and adopting it elsewhere is now a one line change per site.Concurrent misses for the same key are coalesced with
singleflight, so a burst arriving on a cold key produces one read rather than one per listener. Without that the cache only helps after the first read completes, which is not the case the change exists for.