I have a resource that needs to be loaded before any access is allowed to it. It also needs to be updated every minute.
The channels are of length 1 struct{}, so the loop will be blocked if the resource has not been loaded.
This code below started to use 100% of my cpu, I tried adding
time.Sleep(10 * time.Millisecond)
Which made the application cpu consumption drop to 1%
I am thinking a ticker would be a better option for the timed collection.
Any ideas why it would consume 100% cpu or any better ideas for implemention?
func (al *AsyncLoop) Run() {
go func() {
for {
select {
case <-al.chanFetchRequest:
if al.fetched == false {
al.fetchData()
} else if al.lastUpdated.Add(1*time.Minute).Unix() < time.Now().Unix() && al.fetching == false {
go al.fetchData()
}
al.chanFetchResponse <- struct{}{}
continue
default:
continue
}
}
}()
}
I think you just post to al.chanFetchRequest when there is new data so I think you have to keep reading from this channel all the time. Adding a ticker to the select might cause you to fetch the data even if it has not changed or (worse) before it has even loaded. Why not, in the normal case, take the time whenever you fetch the data then the next time make sure you have waited enough time before fetching again. Something like this:
var nextFetch time.Time
for {
select {
case <-al.chanFetchRequest:
if al.fetched == false {
al.fetchData()
nextFetch = time.Now().Add(1 * time.Minute)
} else if time.Now().After(nextFetch) {
al.fetchData()
nextFetch = time.Now().Add(1 * time.Minute)
}
al.chanFetchResponse <- struct{}{}
}
}