У меня есть базовый HTTP-сервер, который принимает запрос и возвращает данные из хранилища данных.
Каждый HTTP-запрос выполняет следующие действия:
- Создать контекст с тайм-аутом
- Создать запрос на чтение (пользовательский тип)
- Отправить запрос на чтение на канал
- Дождитесь ответа и отправьте данные
Вот основной псевдокод:
package main
import (
"context"
"net/http"
"time"
)
type dataRequest struct {
data chan string
ctx context.Context
}
func handler(reqStream chan dataRequest) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second)
defer cancel()
req := dataRequest{
data: make(chan string),
ctx: ctx,
}
select {
case reqStream <- req:
// request pushed to que
case <-ctx.Done():
// don't push onto reqStream if ctx done
}
select {
case <-ctx.Done():
// don't try and serve content if ctx done
case data := <-req.data:
// return data to client
}
}
}
func main() {
dataReqs := make(chan dataRequest)
go func() {
for {
select {
case req := <-dataReqs:
select {
case <-req.ctx.Done():
// don't push onto data channel if ctx done
case req.data <- "some data":
// get data from store
}
}
}
}()
http.HandleFunc("/", handler(dataReqs))
http.ListenAndServe(":8080", nil)
}
Мой вопрос в том, что контекст может завершиться в любое время из-за превышения крайнего срока или отмены запроса клиентом, правильный ли мой текущий подход для обработки этого в нескольких местах или есть более элегантное решение?