在后台处理时响应 HTTP 请求

时间:2021-01-25 21:11:57

标签: http go

我有一个 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.")
}

1 个答案:

答案 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关闭或删除文件,否则会导致处理程序返回后立即发生)。