9999 }
100100
101101 resolverCacheValue struct {
102+ mu sync.RWMutex
102103 IPs []resolverCacheValueIP `json:"ips"`
103104 RefreshAfter time.Time `json:"refresh_after"`
104105 ExpiredAt time.Time `json:"expired_at"`
@@ -225,24 +226,30 @@ func (resolver *cacheResolver) Resolve(ctx context.Context, host string) ([]net.
225226 rcv = cacheValue .(* resolverCacheValue )
226227 }
227228 now := time .Now ()
229+ rcv .mu .RLock ()
228230 ips := make ([]net.IP , 0 , len (rcv .IPs ))
231+ expiredCount := 0
229232 for _ , cacheValueIP := range rcv .IPs {
230233 if cacheValueIP .ExpiredAt .After (now ) {
231234 ips = append (ips , cacheValueIP .IP )
235+ } else {
236+ expiredCount ++
232237 }
233238 }
234- if len (ips ) < len (rcv .IPs ) {
235- newCacheValue := & resolverCacheValue {
236- IPs : make ([]resolverCacheValueIP , 0 , len (rcv .IPs )),
237- RefreshAfter : rcv .RefreshAfter ,
238- ExpiredAt : rcv .ExpiredAt ,
239- }
239+ rcv .mu .RUnlock ()
240+
241+ // If some IPs expired, clean them up
242+ if expiredCount > 0 {
243+ rcv .mu .Lock ()
244+ // Double-check after acquiring write lock
245+ validIPs := make ([]resolverCacheValueIP , 0 , len (rcv .IPs )- expiredCount )
240246 for _ , cacheValueIP := range rcv .IPs {
241247 if cacheValueIP .ExpiredAt .After (now ) {
242- newCacheValue . IPs = append (newCacheValue . IPs , cacheValueIP )
248+ validIPs = append (validIPs , cacheValueIP )
243249 }
244250 }
245- resolver .cache .Set (cacheKey , newCacheValue )
251+ rcv .IPs = validIPs
252+ rcv .mu .Unlock ()
246253 }
247254
248255 return ips , nil
@@ -260,26 +267,20 @@ func (resolver cacheResolver) FeedbackGood(ctx context.Context, host string, ips
260267 if status == cache .GetResultFromCache || status == cache .GetResultFromCacheAndRefreshAsync {
261268 rcv := cacheValue .(* resolverCacheValue )
262269 now := time .Now ()
263- anyIPLiveLonger := false
264270
265- // Create a copy of the cache value to avoid race conditions
266- newRcv := & resolverCacheValue {
267- IPs : make ([]resolverCacheValueIP , len (rcv .IPs )),
268- RefreshAfter : rcv .RefreshAfter ,
269- ExpiredAt : rcv .ExpiredAt ,
270- }
271- copy (newRcv .IPs , rcv .IPs )
271+ rcv .mu .Lock ()
272+ defer rcv .mu .Unlock ()
272273
273- for i := range newRcv .IPs {
274- if isIPContains (ips , newRcv .IPs [i ].IP ) {
275- newRcv .IPs [i ].ExpiredAt = now .Add (resolver .cacheLifetime )
274+ anyIPLiveLonger := false
275+ for i := range rcv .IPs {
276+ if isIPContains (ips , rcv .IPs [i ].IP ) {
277+ rcv .IPs [i ].ExpiredAt = now .Add (resolver .cacheLifetime )
276278 anyIPLiveLonger = true
277279 }
278280 }
279281 if anyIPLiveLonger {
280- newRcv .RefreshAfter = now .Add (resolver .cacheRefreshAfter )
281- newRcv .ExpiredAt = now .Add (resolver .cacheLifetime )
282- resolver .cache .Set (cacheKey , newRcv )
282+ rcv .RefreshAfter = now .Add (resolver .cacheRefreshAfter )
283+ rcv .ExpiredAt = now .Add (resolver .cacheLifetime )
283284 }
284285 }
285286}
@@ -288,6 +289,11 @@ func (resolver cacheResolver) FeedbackBad(context.Context, string, []net.IP) {}
288289
289290func (left * resolverCacheValue ) IsEqual (rightValue cache.CacheValue ) bool {
290291 if right , ok := rightValue .(* resolverCacheValue ); ok {
292+ left .mu .RLock ()
293+ defer left .mu .RUnlock ()
294+ right .mu .RLock ()
295+ defer right .mu .RUnlock ()
296+
291297 if len (left .IPs ) != len (right .IPs ) {
292298 return false
293299 }
@@ -302,10 +308,14 @@ func (left *resolverCacheValue) IsEqual(rightValue cache.CacheValue) bool {
302308}
303309
304310func (left * resolverCacheValue ) IsValid () bool {
311+ left .mu .RLock ()
312+ defer left .mu .RUnlock ()
305313 return time .Now ().Before (left .ExpiredAt )
306314}
307315
308316func (left * resolverCacheValue ) ShouldRefresh () bool {
317+ left .mu .RLock ()
318+ defer left .mu .RUnlock ()
309319 return time .Now ().After (left .RefreshAfter )
310320}
311321
0 commit comments