Как связать Long Poling обработчик и обычный http обработчик
Есть серверное приложение, главная проблема которого - обработка долгих (длинных) запросов. Время обработки файла для клиента может быть довольно большим (несколько минут) и это нормально для специфики сервиса. Но хостинг ограничивает время коннекта до 30 сек, после чего разрывает простаивающее (не было передачи ни одного байта с сервера) соединение. Его тоже можно понять.
Поэтому решил использовать Long Polling. Нашел для Go и используемого мной фреймворка (fiber) готовую библиотеку: https://github.com/LdDl/fiber-long-poll Но из примеров совершенно не смог понять как соединить этот вариант обработки запросов с моими обработчиками маршрутов. То есть на маршрут:
fileAPI.Post(`/to/text/longpoll`,t.LongPollFileHandler())
вырисовывается что-то подобное
func (t *Translator) LongPollFileHandler(manager *lp.LongpollManager) func(ctx *fiber.Ctx)
return func(c *fiber.Ctx) error {
t.FileHandler(c) // это мой стандартный обработчик
....
return manager.SubscriptionHandler(c)
}
}
Но что при этом нужно менять в моем обработчике, переписывать ли его заново и как-то подстраивать - непонятно.
В конечно итоге хочется получить такой вариант: клиент делает запрос, отправляет файл и в цикле while получает ответы от сервера о промежуточных этапах обработки файла (json в котором указывается какая часть файла обработана и сколько всего частей - при выводе в html можно для прогресс-бара эту информацию использовать). Как только файл обработан - присылается финальное сообщение, в котором будет динамический url по которому данный файл клиент сможет скачать. Клиент завершает цикл и следующим запросом скачивает готовый файл, который на сервере будет какое-то время храниться или в ОЗУ или на диске (не суть). В общем, ничего особенного - такой подход используется на многих аналогичных сайтах.
Да, понимаю, что четкого вопроса нет - поэтому любые советы, ссылки на примеры с применением подобных подходов на Go, дополнительные примеры Long Polling с данной библиотекой и т.д. могут мне помочь.
func (t *Translator) FileHandler(c *fiber.Ctx) error {
....
/*тут много кода для предварительной обработки файла и отправки его промежуточному ПО,
дальше здесь все таски после обработки окажутся в структуре MainTask, которая везде передается по указателю
*/
// читаем из канала куда пишутся все таски
YAPI = t.WaitAll(ctx, main)
if YAPI.Err != nil {
cancel()
httpCode := YAPI.Code
if httpCode == 0 {
httpCode = http.StatusInternalServerError
}
resp := &ClientResponse{Status: httpCode, Error: YAPI.Err}
return t.SendJson(c, resp)
} else {
t.Log.Infof("[WAIT ALL ][%d] ALL DONE!", main.TaskCount)
main.As = as
switch do {
case "docx":
result = t.ReplyDocx(c, main)
case "text":
result = t.ReplyText(c, main)
case "html":
result = t.ReplyHtml(c, main)
case "samehtml":
result = t.ReplySameHtml(c, main)
default:
result = t.ReplyHtml(c, main)
}
}
// чистим за unioffice в TEMP
if main.Doc != nil {
if main.Doc.TmpPath != "" {
tmpPath := main.Doc.TmpPath
go utils.CleanTmp(tmpPath)
}
}
return result
}