mirror of
https://github.com/zeromicro/go-zero.git
synced 2026-05-10 16:30:01 +08:00
fix: resolve concurrent get may lead to empty result in ImmutableResource (#5065)
Co-authored-by: hsun <hsun@apac.freewheel.com> Co-authored-by: Kevin Wan <wanjunfeng@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -47,30 +47,32 @@ func (ir *ImmutableResource) Get() (any, error) {
|
||||
return resource, nil
|
||||
}
|
||||
|
||||
ir.maybeRefresh(func() {
|
||||
res, err := ir.fetch()
|
||||
ir.lock.Lock()
|
||||
if err != nil {
|
||||
ir.err = err
|
||||
} else {
|
||||
ir.resource, ir.err = res, nil
|
||||
}
|
||||
ir.lock.Unlock()
|
||||
})
|
||||
ir.lock.Lock()
|
||||
defer ir.lock.Unlock()
|
||||
|
||||
ir.lock.RLock()
|
||||
resource, err := ir.resource, ir.err
|
||||
ir.lock.RUnlock()
|
||||
return resource, err
|
||||
// double check
|
||||
if ir.resource != nil {
|
||||
return ir.resource, nil
|
||||
}
|
||||
if ir.err != nil && !ir.shouldRefresh() {
|
||||
return ir.resource, ir.err
|
||||
}
|
||||
|
||||
res, err := ir.fetch()
|
||||
ir.lastTime.Set(timex.Now())
|
||||
if err != nil {
|
||||
ir.err = err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ir.resource, ir.err = res, nil
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (ir *ImmutableResource) maybeRefresh(execute func()) {
|
||||
func (ir *ImmutableResource) shouldRefresh() bool {
|
||||
now := timex.Now()
|
||||
lastTime := ir.lastTime.Load()
|
||||
if lastTime == 0 || lastTime+ir.refreshInterval < now {
|
||||
ir.lastTime.Set(now)
|
||||
execute()
|
||||
}
|
||||
return lastTime == 0 || lastTime+ir.refreshInterval < now
|
||||
}
|
||||
|
||||
// WithRefreshIntervalOnFailure sets refresh interval on failure.
|
||||
|
||||
Reference in New Issue
Block a user