OLD | NEW |
1 // Copyright 2016 The LUCI Authors. All rights reserved. | 1 // Copyright 2016 The LUCI Authors. All rights reserved. |
2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
4 | 4 |
5 package datastorecache | 5 package datastorecache |
6 | 6 |
7 import ( | 7 import ( |
8 "math" | 8 "math" |
9 "time" | 9 "time" |
10 | 10 |
11 "github.com/luci/luci-go/common/clock" | 11 "github.com/luci/luci-go/common/clock" |
12 "github.com/luci/luci-go/common/data/rand/mathrand" | 12 "github.com/luci/luci-go/common/data/rand/mathrand" |
13 "github.com/luci/luci-go/common/errors" | 13 "github.com/luci/luci-go/common/errors" |
14 log "github.com/luci/luci-go/common/logging" | 14 log "github.com/luci/luci-go/common/logging" |
15 "github.com/luci/luci-go/common/retry" | 15 "github.com/luci/luci-go/common/retry" |
| 16 "github.com/luci/luci-go/common/retry/transient" |
16 "github.com/luci/luci-go/server/router" | 17 "github.com/luci/luci-go/server/router" |
17 | 18 |
18 "github.com/luci/gae/impl/prod/constraints" | 19 "github.com/luci/gae/impl/prod/constraints" |
19 "github.com/luci/gae/service/datastore" | 20 "github.com/luci/gae/service/datastore" |
20 "github.com/luci/gae/service/info" | 21 "github.com/luci/gae/service/info" |
21 | 22 |
22 "golang.org/x/net/context" | 23 "golang.org/x/net/context" |
23 ) | 24 ) |
24 | 25 |
25 const ( | 26 const ( |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 // We'll try a few times, sleeping a short time in between if we fail to
get | 290 // We'll try a few times, sleeping a short time in between if we fail to
get |
290 // the lock. We don't want to wait too long and stall our parent applica
tion, | 291 // the lock. We don't want to wait too long and stall our parent applica
tion, |
291 // though. | 292 // though. |
292 var ( | 293 var ( |
293 attempts = 0 | 294 attempts = 0 |
294 acquiredLock = false | 295 acquiredLock = false |
295 refreshValue Value | 296 refreshValue Value |
296 delta time.Duration | 297 delta time.Duration |
297 ) | 298 ) |
298 err := retry.Retry(clock.Tag(c, "datastoreCacheLockRetry"), | 299 err := retry.Retry(clock.Tag(c, "datastoreCacheLockRetry"), |
299 » » retry.TransientOnly(bci.refreshRetryFactory), func() error { | 300 » » transient.Only(bci.refreshRetryFactory), func() error { |
300 | 301 |
301 // This is a retry. If the entry was missing before, che
ck to see if some | 302 // This is a retry. If the entry was missing before, che
ck to see if some |
302 // other process has since added it to the datastore. | 303 // other process has since added it to the datastore. |
303 // We only check this on the 2+ retry because we already
checked this | 304 // We only check this on the 2+ retry because we already
checked this |
304 // condition above in the initial datastore Get. | 305 // condition above in the initial datastore Get. |
305 // | 306 // |
306 // If this fails, we'll continue to try and perform the
Refresh. | 307 // If this fails, we'll continue to try and perform the
Refresh. |
307 if entryWasMissing && attempts > 0 { | 308 if entryWasMissing && attempts > 0 { |
308 switch err := datastore.Get(c, &e); err { | 309 switch err := datastore.Get(c, &e); err { |
309 case nil: | 310 case nil: |
(...skipping 19 matching lines...) Expand all Loading... |
329 refreshValue, delta, err = doRefresh(c, bci.h, &
e, userNS) | 330 refreshValue, delta, err = doRefresh(c, bci.h, &
e, userNS) |
330 return | 331 return |
331 }) | 332 }) |
332 switch err { | 333 switch err { |
333 case nil: | 334 case nil: |
334 // Successfully loaded. | 335 // Successfully loaded. |
335 return nil | 336 return nil |
336 | 337 |
337 case ErrFailedToLock: | 338 case ErrFailedToLock: |
338 // Retry after delay. | 339 // Retry after delay. |
339 » » » » return errors.WrapTransient(err) | 340 » » » » return transient.Tag.Apply(err) |
340 | 341 |
341 default: | 342 default: |
342 log.WithError(err).Warningf(c, "Unexpected failu
re obtaining initial load lock.") | 343 log.WithError(err).Warningf(c, "Unexpected failu
re obtaining initial load lock.") |
343 return err | 344 return err |
344 } | 345 } |
345 }, func(err error, d time.Duration) { | 346 }, func(err error, d time.Duration) { |
346 log.WithError(err).Debugf(c, "Failed to acquire initial
refresh lock. Retrying...") | 347 log.WithError(err).Debugf(c, "Failed to acquire initial
refresh lock. Retrying...") |
347 }) | 348 }) |
348 if err != nil { | 349 if err != nil { |
349 // If we actually acquired the lock, then this refresh was a fai
lure, and | 350 // If we actually acquired the lock, then this refresh was a fai
lure, and |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
455 // delta is a factor representing the amount of time that it takes to | 456 // delta is a factor representing the amount of time that it takes to |
456 // recalculate the value. Higher delta values allow for earlier recomputation | 457 // recalculate the value. Higher delta values allow for earlier recomputation |
457 // for values that take longer to calculate. | 458 // for values that take longer to calculate. |
458 // | 459 // |
459 // beta can be set to >1 to favor earlier recomputations; however, in practice | 460 // beta can be set to >1 to favor earlier recomputations; however, in practice |
460 // beta=1 works well. | 461 // beta=1 works well. |
461 func xFetch(now, expiry time.Time, delta time.Duration, beta float64, rf randFun
c) bool { | 462 func xFetch(now, expiry time.Time, delta time.Duration, beta float64, rf randFun
c) bool { |
462 offset := time.Duration(float64(delta) * beta * math.Log(rf())) | 463 offset := time.Duration(float64(delta) * beta * math.Log(rf())) |
463 return !now.Add(-offset).Before(expiry) | 464 return !now.Add(-offset).Before(expiry) |
464 } | 465 } |
OLD | NEW |