Использовать обработку координат мьютекса данных и тайм-аут.
Определить тип для хранения мьютекса, ввода, результата, канала, сигнализирующего о завершении работы, и флага, указывающего, что работа, если таковая имеется, завершено.
type work struct {
sync.Mutex
input InputType
result ResultType
signal chan struct {}
done bool
}
Обработчик запросов создает и ставит в очередь рабочий элемент и ожидает истечения времени ожидания или сигнала от процессора очереди.В любом случае обработчик запроса проверяет, выполнил ли процессор очереди работу, и отвечает соответствующим образом.
func handler(resp http.ResponseWriter, req *http.Request) {
w := &queueElement{
input: computeInputFromRequest(req)
signal: make(chan struct{})
}
enqueue(w)
// Wait for timeout or for queue processor to signal that the work is complete.
select {
case <-time.After(5 * time.Second):
case <-w.signal:
}
w.Lock()
done := w.done // Record state of the work item.
w.done = true // Mark the work item as complete.
w.Unlock()
if !done {
http.Error(w, "Timeout", http.StatusGatewayTimeout)
} else {
respondWithResult(resp, w.result)
}
}
Процессор очереди будет выглядеть примерно так:
for {
w := dequeue()
w.Lock()
if !w.done {
w.done = true
w.result = computeResultFromInput(w.input)
close(w.signal)
}
w.Unlock()
}
Чтобы убедиться, чточто обработчик запроса ожидает результата, процессор очереди удерживает блокировку при обработке рабочего элемента.