@@ -7,14 +7,14 @@ import (
77 "log/slog"
88 "slices"
99 "strings"
10- "sync"
1110 "time"
1211
1312 "github.com/github/deployment-tracker/pkg/deploymentrecord"
1413 "github.com/github/deployment-tracker/pkg/image"
1514 "github.com/github/deployment-tracker/pkg/metrics"
1615 "k8s.io/apimachinery/pkg/runtime/schema"
1716 "k8s.io/apimachinery/pkg/types"
17+ amcache "k8s.io/apimachinery/pkg/util/cache"
1818 "k8s.io/client-go/metadata"
1919
2020 corev1 "k8s.io/api/core/v1"
@@ -37,6 +37,12 @@ const (
3737 RuntimeRiskAnnotationKey = "github.com/runtime-risks"
3838)
3939
40+ type ttlCache interface {
41+ Get (k any ) (any , bool )
42+ Set (k any , v any , ttl time.Duration )
43+ Delete (k any )
44+ }
45+
4046// PodEvent represents a pod event to be processed.
4147type PodEvent struct {
4248 Key string
@@ -60,7 +66,7 @@ type Controller struct {
6066 // best effort cache to avoid redundant posts
6167 // post requests are idempotent, so if this cache fails due to
6268 // restarts or other events, nothing will break.
63- observedDeployments sync. Map
69+ observedDeployments ttlCache
6470}
6571
6672// New creates a new deployment tracker controller.
@@ -96,12 +102,13 @@ func New(clientset kubernetes.Interface, metadataClient metadata.Interface, name
96102 }
97103
98104 cntrl := & Controller {
99- clientset : clientset ,
100- metadataClient : metadataClient ,
101- podInformer : podInformer ,
102- workqueue : queue ,
103- apiClient : apiClient ,
104- cfg : cfg ,
105+ clientset : clientset ,
106+ metadataClient : metadataClient ,
107+ podInformer : podInformer ,
108+ workqueue : queue ,
109+ apiClient : apiClient ,
110+ cfg : cfg ,
111+ observedDeployments : amcache .NewExpiring (),
105112 }
106113
107114 // Add event handlers to the informer
@@ -395,6 +402,8 @@ func (c *Controller) deploymentExists(ctx context.Context, namespace, name strin
395402
396403// recordContainer records a single container's deployment info.
397404func (c * Controller ) recordContainer (ctx context.Context , pod * corev1.Pod , container corev1.Container , status , eventType string , runtimeRisks []deploymentrecord.RuntimeRisk ) error {
405+ var cacheKey string
406+
398407 dn := getARDeploymentName (pod , container , c .cfg .Template )
399408 digest := getContainerDigest (pod , container .Name )
400409
@@ -409,22 +418,21 @@ func (c *Controller) recordContainer(ctx context.Context, pod *corev1.Pod, conta
409418 return nil
410419 }
411420
412- cacheKey := getCacheKey (dn , digest )
413-
414421 // Check if we've already recorded this deployment
415422 switch status {
416423 case deploymentrecord .StatusDeployed :
417- if _ , exists := c .observedDeployments .Load (cacheKey ); exists {
424+ cacheKey = getCacheKey (EventCreated , dn , digest )
425+ if _ , exists := c .observedDeployments .Get (cacheKey ); exists {
418426 slog .Debug ("Deployment already observed, skipping post" ,
419427 "deployment_name" , dn ,
420428 "digest" , digest ,
421429 )
422430 return nil
423431 }
424432 case deploymentrecord .StatusDecommissioned :
425- // For delete, check if we've seen it - if not, no need to decommission
426- if _ , exists := c .observedDeployments .Load (cacheKey ); ! exists {
427- slog .Debug ("Deployment not in cache , skipping decommission " ,
433+ cacheKey = getCacheKey ( EventDeleted , dn , digest )
434+ if _ , exists := c .observedDeployments .Get (cacheKey ); exists {
435+ slog .Debug ("Deployment already deleted , skipping post " ,
428436 "deployment_name" , dn ,
429437 "digest" , digest ,
430438 )
@@ -488,8 +496,16 @@ func (c *Controller) recordContainer(ctx context.Context, pod *corev1.Pod, conta
488496 // Update cache after successful post
489497 switch status {
490498 case deploymentrecord .StatusDeployed :
491- c .observedDeployments .Store (cacheKey , true )
499+ cacheKey = getCacheKey (EventCreated , dn , digest )
500+ c .observedDeployments .Set (cacheKey , true , 2 * time .Minute )
501+ // If there was a previous delete event, remove that
502+ cacheKey = getCacheKey (EventDeleted , dn , digest )
503+ c .observedDeployments .Delete (cacheKey )
492504 case deploymentrecord .StatusDecommissioned :
505+ cacheKey = getCacheKey (EventDeleted , dn , digest )
506+ c .observedDeployments .Set (cacheKey , true , 2 * time .Minute )
507+ // If there was a previous created event, remove that
508+ cacheKey = getCacheKey (EventCreated , dn , digest )
493509 c .observedDeployments .Delete (cacheKey )
494510 default :
495511 return fmt .Errorf ("invalid status: %s" , status )
@@ -586,8 +602,8 @@ func (c *Controller) getOwnerMetadata(ctx context.Context, namespace string, own
586602 return obj , nil
587603}
588604
589- func getCacheKey (dn , digest string ) string {
590- return dn + "||" + digest
605+ func getCacheKey (ev , dn , digest string ) string {
606+ return ev + "||" + dn + "||" + digest
591607}
592608
593609// createInformerFactory creates a shared informer factory with the given resync period.
0 commit comments