Hey folks, I definitely need a help - looks like I have collisions in my mind
I have HTTP server written in go (via std lib), and one handler is for metadata generation.
func handler(w http.ResponseWriter, r *http.Request) {
path, ok := r.URL.Query()["path"]
// ....
// checks and
// other stuff
err := BuildMetadata(path)
// ....
// checks and
// other stuff
}
Each client can trigger metadata generation, but I have to be sure, that the only 1 process of metadata generation is running at the same time for then particular path, and it could be multiple for different paths.
My BuildMetadata()
signature looks like the following:
func BuildMetadata(path string) error {
tasks := make(chan string, 1)
done := make(chan struct{})
errors := make(chan error, 1)
tasks <- path
go func(tasks chan string, done chan struct{}, errors chan error) {
fp := <-tasks
log.Printf("New task for %s metadata has been created\n", fp)
// the less interesting happens here
if err := rebuildMeta(fp); err != nil {
errors <- err
}
done <- struct{}{}
}(tasks, done, errors)
select {
case err := <-errors:
return err
case <-done:
log.Printf("Metadata has been created\n")
return nil
}
}
I’m not sure that I’ve satisfied my own requirement (only a single metadata generation is possible for the particular path)
AFAIK, each handle is running in its own goroutine:
https://go.dev/src/net/http/server.go#L3071
I’m afraid of I’m doing wrong with concurrency - when BuildMetadata will be performed, a bunch of new channels will be created for each goroutine, independently of each other, isn’t it?
How do can I control such case and not reinvent the wheel (most important for me as for Go learner)
I appreciate any suggestion, link, blame - please help me to understand Go.
Thank you,
Pash