Skip to content

Commit 3d6c308

Browse files
committed
fix: improve object cache reliability
* make sure objects expire after DefaultTTLSeconds * make cached objects have GKV information * fix cache retrieval and removal logic Closes #502 Signed-off-by: Marco Nenciarini <[email protected]>
1 parent 2dc29a5 commit 3d6c308

File tree

1 file changed

+39
-4
lines changed
  • internal/cnpgi/instance/internal/client

1 file changed

+39
-4
lines changed

internal/cnpgi/instance/internal/client/client.go

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ const DefaultTTLSeconds = 10
2121
type cachedEntry struct {
2222
entry client.Object
2323
fetchUnixTime int64
24-
ttl time.Duration
24+
ttlSeconds int64
2525
}
2626

2727
func (e *cachedEntry) isExpired() bool {
28-
return time.Now().Unix()-e.fetchUnixTime > int64(e.ttl)
28+
return time.Now().Unix()-e.fetchUnixTime > e.ttlSeconds
2929
}
3030

3131
// ExtendedClient is an extended client that is capable of caching multiple secrets without relying on informers
@@ -71,6 +71,28 @@ func (e *ExtendedClient) Get(
7171
return e.Client.Get(ctx, key, obj, opts...)
7272
}
7373

74+
// addTypeInformationToObject adds TypeMeta information to a client.Object based upon the client Scheme
75+
// inspired by: https://github.com/kubernetes/cli-runtime/blob/v0.19.2/pkg/printers/typesetter.go#L41
76+
func (e *ExtendedClient) addTypeInformationToObject(obj client.Object) error {
77+
gvks, _, err := e.Client.Scheme().ObjectKinds(obj)
78+
if err != nil {
79+
return fmt.Errorf("missing apiVersion or kind and cannot assign it; %w", err)
80+
}
81+
82+
for _, gvk := range gvks {
83+
if len(gvk.Kind) == 0 {
84+
continue
85+
}
86+
if len(gvk.Version) == 0 || gvk.Version == runtime.APIVersionInternal {
87+
continue
88+
}
89+
obj.GetObjectKind().SetGroupVersionKind(gvk)
90+
break
91+
}
92+
93+
return nil
94+
}
95+
7496
func (e *ExtendedClient) getCachedObject(
7597
ctx context.Context,
7698
key client.ObjectKey,
@@ -81,6 +103,12 @@ func (e *ExtendedClient) getCachedObject(
81103
WithName("extended_client").
82104
WithValues("name", key.Name, "namespace", key.Namespace)
83105

106+
// Make sure the object has GVK information
107+
// This is needed to compare the object type with the cached one
108+
if err := e.addTypeInformationToObject(obj); err != nil {
109+
return fmt.Errorf("cannot add type metadata to object of type %T: %w", obj, err)
110+
}
111+
84112
contextLogger.Trace("locking the cache")
85113
e.mux.Lock()
86114
defer e.mux.Unlock()
@@ -120,9 +148,16 @@ func (e *ExtendedClient) getCachedObject(
120148
return err
121149
}
122150

151+
// Populate the GKV information again, as the client.Get() may have
152+
// returned an object without this information set
153+
if err := e.addTypeInformationToObject(obj); err != nil {
154+
return fmt.Errorf("cannot add type metadata to object of type %T: %w", obj, err)
155+
}
156+
123157
cs := cachedEntry{
124-
entry: obj.(runtime.Object).DeepCopyObject().(client.Object),
158+
entry: obj.DeepCopyObject().(client.Object),
125159
fetchUnixTime: time.Now().Unix(),
160+
ttlSeconds: DefaultTTLSeconds,
126161
}
127162

128163
contextLogger.Debug("setting object in the cache")
@@ -143,7 +178,7 @@ func (e *ExtendedClient) removeObject(object client.Object) {
143178
for i, cache := range e.cachedObjects {
144179
if cache.entry.GetNamespace() == object.GetNamespace() &&
145180
cache.entry.GetName() == object.GetName() &&
146-
cache.entry.GetObjectKind().GroupVersionKind() != object.GetObjectKind().GroupVersionKind() {
181+
cache.entry.GetObjectKind().GroupVersionKind() == object.GetObjectKind().GroupVersionKind() {
147182
e.cachedObjects = append(e.cachedObjects[:i], e.cachedObjects[i+1:]...)
148183
return
149184
}

0 commit comments

Comments
 (0)