Skip to content

Commit

Permalink
feat: refactor article fetching with singleflight
Browse files Browse the repository at this point in the history
- Update logging message to indicate usage of `singleflight Do` instead of `singleflight`
- Replace `GetArticleNew` function calls with `GetArticleDo` and add logging for data and request information
- Introduce a new `GetArticleDoChan` function with cache hit logging, a timeout mechanism, and simulated data retrieval delay
- Add a new loop to demonstrate the usage of `singleflight DoChan` with a wait group and a timeout for each request

Signed-off-by: Bo-Yi Wu <[email protected]>
  • Loading branch information
appleboy committed Feb 3, 2024
1 parent 5f5e068 commit 874ab81
Showing 1 changed file with 44 additions and 3 deletions.
47 changes: 44 additions & 3 deletions example55-cache-hotspot-invalid/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,26 @@ func main() {
}
wg.Wait()

slog.Info("================== using singleflight ===================")
slog.Info("================== using singleflight Do ===================")

wg.Add(5)
for i := 5; i < 10; i++ {
go func(req int) {
defer wg.Done()
data := db.GetArticleNew(req, 2)
data := db.GetArticleDo(req, 2)
slog.Info("data info", "data", data, "req", req)
}(i)
}
wg.Wait()

slog.Info("================== using singleflight DoChan ===================")

wg.Add(5)
for i := 10; i < 15; i++ {
go func(req int) {
defer wg.Done()
t := time.Duration(time.Duration(int64(req*10)) * time.Millisecond)
data := db.GetArticleDoChan(req, 3, t)
slog.Info("data info", "data", data, "req", req)
}(i)
}
Expand Down Expand Up @@ -64,7 +77,7 @@ func (db *DB) GetArticleOld(req int, id int) *Article {
return data
}

func (db *DB) GetArticleNew(req int, id int) *Article {
func (db *DB) GetArticleDo(req int, id int) *Article {
data := db.cache.Get(id)
if data != nil {
slog.Info("cache hit", "id", id, "req", req)
Expand All @@ -90,3 +103,31 @@ func (db *DB) GetArticleNew(req int, id int) *Article {

return row.(*Article)
}

func (db *DB) GetArticleDoChan(req int, id int, t time.Duration) *Article {
data := db.cache.Get(id)
if data != nil {
slog.Info("cache hit", "id", id, "req", req)
return data
}

key := fmt.Sprintf("article:%d", id)
dataChan := db.engine.DoChan(key, func() (interface{}, error) {
slog.Info("missing cache", "id", id, "req", req)
data := &Article{
ID: id,
Content: "FooBar",
}
db.cache.Set(id, data)
time.Sleep(115 * time.Millisecond)
return data, nil
})

select {
case <-time.After(t):
slog.Info("timeout", "id", id, "req", req)
return nil
case res := <-dataChan:
return res.Val.(*Article)
}
}

0 comments on commit 874ab81

Please sign in to comment.