loong / go-concurrency-exercises

Hands on exercises with real-life examples to study and practice Go concurrency patterns. Test-cases are provided to verify your answers.
Other
1.11k stars 378 forks source link

Exercise 1: Tests fail even with a 5 second delay #42

Open p-duke opened 1 month ago

p-duke commented 1 month ago

Hey @loong - love this repo and its helping me improve my Go skills

After adding what I think is the desired solution the tests continue to fail. Even when I include a 5 second delay.

func Crawl(url string, depth int, wg *sync.WaitGroup) {
+   rateLimit := time.Second * 5
+   throttle := time.NewTicker(rateLimit)
+   defer throttle.Stop()
    defer wg.Done()

    if depth <= 0 {
        return
    }

    body, urls, err := fetcher.Fetch(url)
    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Printf("found: %s %q\n", url, body)

    wg.Add(len(urls))
    for _, u := range urls {
        // Do not remove the `go` keyword, as Crawl() must be
        // called concurrently
+       <-throttle.C // rate limit client calls
        go Crawl(u, depth-1, wg)
    }
    return
}
Screenshot 2024-08-18 at 11 21 24 AM

Go version go version go1.21.0 darwin/amd64

Please let me know if I'm missing something here. Thanks!

loong commented 1 week ago

@p-duke Hi! Have you figured it out by now?

The issue is that the throttle ticker gets initialized each time Crawl() is called. Meaning you are creating a new ticker every time!

You can initialize one ticker and pass it down to Crawl() as a parameter. Here is an example: https://github.com/loong/go-concurrency-exercises/pull/19/files