7
7
8
8
"github.com/solo-io/go-utils/contextutils"
9
9
"k8s.io/apimachinery/pkg/types"
10
+ "k8s.io/utils/lru"
10
11
11
12
"github.com/solo-io/gloo/projects/gateway2/proxy_syncer"
12
13
gwplugins "github.com/solo-io/gloo/projects/gateway2/translator/plugins"
@@ -39,22 +40,22 @@ type GatewayStatusSyncer interface {
39
40
type statusSyncerFactory struct {
40
41
// maps a proxy sync action to the plugin registry that produced it
41
42
// sync iteration -> plugin registry
42
- registryPerSync map [int ]* registry.PluginRegistry
43
+ registryPerSyncCache * lru. Cache // map[int]*registry.PluginRegistry
43
44
// maps a proxy to the sync iteration that produced it
44
45
// only the latest sync iteration is stored and used to apply status plugins
45
46
resyncsPerProxy map [types.NamespacedName ]int
46
47
// proxies left to sync
47
- resyncsPerIteration map [int ][]types.NamespacedName
48
-
49
- lock * sync.Mutex
48
+ resyncsPerIterationCache * lru.Cache // map[int][]types.NamespacedName
49
+ lock * sync.Mutex
50
50
}
51
51
52
52
func NewStatusSyncerFactory () GatewayStatusSyncer {
53
53
return & statusSyncerFactory {
54
- registryPerSync : make (map [int ]* registry.PluginRegistry ),
55
- resyncsPerProxy : make (map [types.NamespacedName ]int ),
56
- resyncsPerIteration : make (map [int ][]types.NamespacedName ),
57
- lock : & sync.Mutex {},
54
+ // Set a max value of 3 for n-2 iterations. Ideally we should only care about n-1 but playing it safe
55
+ registryPerSyncCache : lru .New (3 ),
56
+ resyncsPerIterationCache : lru .New (3 ),
57
+ resyncsPerProxy : make (map [types.NamespacedName ]int ),
58
+ lock : & sync.Mutex {},
58
59
}
59
60
}
60
61
@@ -70,21 +71,20 @@ func (f *statusSyncerFactory) QueueStatusForProxies(
70
71
71
72
contextutils .LoggerFrom (ctx ).Debugf ("queueing %v proxies for sync %d" , len (proxiesToQueue ), totalSyncCount )
72
73
74
+ resyncsPerIteration := make ([]types.NamespacedName , len (proxiesToQueue ))
73
75
// queue each proxy for a given sync iteration
74
76
for _ , proxy := range proxiesToQueue {
75
77
proxyKey := getProxyNameNamespace (proxy )
76
78
// overwrite the sync count for the proxy with the most recent sync count
77
79
f .resyncsPerProxy [proxyKey ] = totalSyncCount
78
80
79
81
// keep track of proxies to check all proxies are handled in debugger
80
- f . resyncsPerIteration [ totalSyncCount ] = append (f . resyncsPerIteration [ totalSyncCount ] , proxyKey )
82
+ resyncsPerIteration = append (resyncsPerIteration , proxyKey )
81
83
}
84
+ f .resyncsPerIterationCache .Add (totalSyncCount , resyncsPerIteration )
82
85
83
86
// the plugin registry that produced the proxies is the same for all proxies in a given sync
84
- f .registryPerSync [totalSyncCount ] = pluginRegistry
85
-
86
- delete (f .resyncsPerIteration , totalSyncCount - 2 )
87
- delete (f .registryPerSync , totalSyncCount - 2 )
87
+ f .registryPerSyncCache .Add (totalSyncCount , pluginRegistry )
88
88
}
89
89
90
90
// HandleProxyReports is a callback that applies status plugins to the proxies that have been queued
@@ -113,39 +113,40 @@ func (f *statusSyncerFactory) HandleProxyReports(ctx context.Context, proxiesWit
113
113
continue
114
114
}
115
115
116
- if len (f .resyncsPerIteration [proxySyncCount ]) == 0 {
117
- // remove the key so the map does not indefinitely grow
118
- delete (f .resyncsPerIteration , proxySyncCount )
119
- // re-sync already happened, nothing to do
116
+ // If the proxy does not exist in the cache, or the cache is empty, the re-sync already happened, nothing to do
117
+ resyncsPerIterationIface , ok := f .resyncsPerIterationCache .Get (proxySyncCount )
118
+ if ! ok {
120
119
continue
121
- } else {
122
- updatedList := make ([]types.NamespacedName , 0 )
123
- for _ , proxyNameNs := range f .resyncsPerIteration [proxySyncCount ] {
124
- if proxyNameNs != proxyKey {
125
- updatedList = append (updatedList , proxyNameNs )
126
- }
127
- }
128
- f .resyncsPerIteration [proxySyncCount ] = updatedList
120
+ }
121
+ resyncsPerIteration := resyncsPerIterationIface .([]types.NamespacedName )
122
+ if len (resyncsPerIteration ) == 0 {
123
+ f .resyncsPerIterationCache .Remove (proxySyncCount )
124
+ continue
125
+ }
129
126
130
- if len (f .resyncsPerIteration [proxySyncCount ]) == 0 {
131
- // remove the key so the map does not indefinitely grow
132
- delete (f .resyncsPerIteration , proxySyncCount )
127
+ updatedList := make ([]types.NamespacedName , 0 )
128
+ for _ , proxyNameNs := range resyncsPerIteration {
129
+ if proxyNameNs != proxyKey {
130
+ updatedList = append (updatedList , proxyNameNs )
133
131
}
134
132
}
133
+ f .resyncsPerIterationCache .Add (proxySyncCount , updatedList )
135
134
136
135
proxiesToReport [proxySyncCount ] = append (proxiesToReport [proxySyncCount ], proxyWithReport )
137
136
// remove the proxy from the queue
138
137
delete (f .resyncsPerProxy , proxyKey )
139
138
}
140
139
141
140
for syncCount , proxies := range proxiesToReport {
142
- if plugins , ok := f .registryPerSync [ syncCount ] ; ok {
143
- newStatusSyncer (plugins ).applyStatusPlugins (ctx , proxies )
141
+ if plugins , ok := f .registryPerSyncCache . Get ( syncCount ) ; ok {
142
+ newStatusSyncer (plugins .( * registry. PluginRegistry ) ).applyStatusPlugins (ctx , proxies )
144
143
}
145
144
146
145
// If there are no more proxies for the sync iteration, delete the sync count
147
- if len (f .resyncsPerIteration [syncCount ]) == 0 {
148
- delete (f .registryPerSync , syncCount )
146
+ resyncsPerIterationIface , _ := f .resyncsPerIterationCache .Get (syncCount )
147
+ resyncsPerIteration := resyncsPerIterationIface .([]types.NamespacedName )
148
+ if len (resyncsPerIteration ) == 0 {
149
+ f .registryPerSyncCache .Remove (syncCount )
149
150
}
150
151
}
151
152
}
0 commit comments