Objective:
Return the *Channel object, containing metadata about the Channel, corresponding to the given ID. The cache must be updated from a network service every 24 hours, but it’s okay to return stale data.
Unusual design decisions:
If we get an explicit “that ID does not exist” from the network service, a .NotExist = true object with a valid CacheTS is stored in the map.
If the ID is missing from the map, we do a synchronous network fetch (!)
The function feels really messy. Any tips on how to clean it up? I need to repeat the function for other types, as well.
type DataCache struct {
// ...
channelLock sync.RWMutex
channelInfo map[ChannelID]*Channel
// ...
}
func (c *DataCache) ChannelInfo(channel ChannelID) (*Channel) {
c.channelLock.RLock()
defer c.channelLock.RUnlock()
ch, ok := c.channelInfo[channel]
needsUpdate := 0
if !ok {
needsUpdate = 2
} else if ch.CacheTS.Before(time.Now().Add(-24 * time.Hour)) {
needsUpdate = 1
}
if needsUpdate == 2 {
// new stack frame to protect against panic causing double-unlock
func() {
c.channelLock.RUnlock()
defer c.channelLock.RLock()
_, _ = c.updateChannelInfo(channel)
}()
ch, ok = c.channelInfo[channel]
if !ok {
return nil
}
} else if needsUpdate == 1 {
go c.updateChannelInfo(channel)
}
if ch.NotExist {
return nil
}
return ch
}