我有一个 API 可以接收要处理的 CSV 文件。我希望能够在后台处理文件时发回 202 Accepted
(或任何真正的状态)。我有一个处理程序来检查请求,写入成功标头,然后通过生产者/消费者模式继续处理。问题是,由于 WaitGroup.Wait()
调用,接受的标头没有发回。处理程序验证中的错误正确发送回,但这是因为 return
语句。
是否可以像我希望的那样将 202 Accepted
与等待组一起发送回去(如果是这样,我错过了什么)?
func SomeHandler(w http.ResponseWriter, req *http.Request) {
endAccepted := time.Now()
err := verifyRequest(req)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
data := JSONErrors{Errors: []string{err.Error()}}
json.NewEncoder(w).Encode(data)
return
}
// ...FILE RETRIEVAL CLIPPED (not relevant)...
// e.g. csvFile, openErr := os.Open(tmpFile.Name())
//////////////////////////////////////////////////////
// TODO this isn't sending due to the WaitGroup.Wait()s below
w.WriteHeader(http.StatusAccepted)
//////////////////////////////////////////////////////
// START PRODUCER/CONSUMER
jobs := make(chan *Job, 100) // buffered channel
results := make(chan *Job, 100) // buffered channel
// start consumers
for i := 0; i < 5; i++ { // 5 consumers
wg.Add(1)
go consume(i, jobs, results)
}
// start producing
go produce(jobs, csvFile)
// start processing
wg2.Add(1)
go process(results)
wg.Wait() // wait for all workers to finish processing jobs
close(results)
wg2.Wait() // wait for process to finish
log.Println("===> Done Processing.")
}
答案 0 :(得分:1)
您正在后台进行所有处理,但您仍在等待它完成。解决办法就是不要等待。最好的解决方案是将所有处理移至其他地方的函数,您只需使用 go
调用即可在后台运行它,但最简单的解决方案是将其置于内联
w.WriteHeader(http.StatusAccepted)
go func() {
// START PRODUCER/CONSUMER
jobs := make(chan *Job, 100) // buffered channel
results := make(chan *Job, 100) // buffered channel
// start consumers
for i := 0; i < 5; i++ { // 5 consumers
wg.Add(1)
go consume(i, jobs, results)
}
// start producing
go produce(jobs, csvFile)
// start processing
wg2.Add(1)
go process(results)
wg.Wait() // wait for all workers to finish processing jobs
close(results)
wg2.Wait() // wait for process to finish
log.Println("===> Done Processing.")
}()
请注意,您省略了 CSV 文件处理,因此您需要确保使用这种方式是安全的(即您没有defer
关闭或删除文件,否则会导致处理程序返回后立即发生)。