Настроить время ожидания запроса в Фениксе?
Я хочу, чтобы запросы истекали через некоторое время, скажем, 20 секунд. Если для отправки ответа приложению требуется более 20 секунд, Phoenix должен отменить выполнение и немедленно ответить с некоторой ошибкой (предпочтительно HTTP 503).
Я просмотрел документы по Фениксу, но не нашел упоминаний о параметре тайм-аута запроса. Похоже, у Ковбоя есть :timeout
параметр, который я попытался установить на 10 мс, но он все еще позволил запросу занять 8951 мс:
config :app, SomeApp.Endpoint,
http: [port: 4000, timeout: 10]
Оказывается, документы Cowboy определяют эту опцию как:
Время в мс без запросов перед тем, как Cowboy закроет соединение.
это не то, что я ищу.
Можно ли установить тайм-аут запроса в Фениксе?
1 ответ
Это ни в коем случае не является обязанностью веб-сервера / фреймворка. Ковбой понятия не имеет (и не должен знать!) О том, что происходит в приложении, он обслуживает соединения. Феникс может позаботиться об этом, но это нарушит SRP. В конце концов, вышеупомянутый тайм-аут больше относится к бизнес-логике. Представьте, что ковбой / феникс будет пытаться справиться с таймаутом: что должно произойти с выполняемым в настоящее время обработчиком?
Тем не менее, приложение должно обрабатывать такие тайм-ауты, и это относительно просто: нужно просто обернуть базовое выполнение в задачу желаемым таймаутом. Таким образом, он будет гибким, надежным, и вы можете указать, какие контроллеры / действия должны вести себя таким образом, а какие - нет.
В псевдокоде (это реальный код, но я его не тестировал):
def create(conn, params) do # or any other action
fn -> prepare_result end
|> Task.async()
|> Task.yield(10) # ⇐ HERE!!!
|> case do
{:ok, result} -> # success
conn
|> put_status(200)
|> json(%{ok: result})
nil -> # not finished yet; do smth with the task itself!
conn
|> put_status(503)
|> json(%{error: :timeout})
{:exit, reason} -> # should not happen [see Task.yield/2 docs]
conn
|> put_status(500) # internal server error; unexpected
|> json(%{error: reason})
end
end
Task.yield/2
,
Sidenote: конечно, если вам нужно такое поведение во всем приложении, просто объявите макрос, делающий это или что-то подобное.
Если это..
config :app, SomeApp.Endpoint,
http: [port: 4000, timeout: 10]
не работает.. Попробуйте изменить на..
config :app, SomeApp.Endpoint,
http: [port: 4000, protocol_options: [idle_timeout: 10_000]]