В настоящее время я пишу некоторый сетевой код, и мне нужно отправить большое количество сообщений, а затем дождаться одного ответа.
Учитывая, что у меня есть функция, которая возвращает входные и выходные каналы дляу меня есть сокет:
let resps = List.map uris ~f:(fun uri ->
let%lwt (ic,oc) = connect uri in
let%lwt () = Lwt_io.write_value oc msg in
Lwt_io.read_value ic
) in
Lwt.pick resps
Насколько я понимаю, выбор должен отменять все текущие запросы после того, как он выполнит обещание в resps
. Проблема заключается в том, что если какое-либо из этих соединений не удается / отказывается, возникает исключение Unix.ECONNREFUSED
.
Мой вопрос: какова правильная семантика, чтобы заставить Lwt.pick
игнорировать исключения?
Опции, о которых я до сих пор думал, заключаются в том, чтобы отследить исключительность в запросах:
let resps = List.map uris ~f:(fun uri ->
try
let%lwt (ic,oc) = connect uri in
let%lwt () = Lwt_io.write_value oc msg in
Lwt_io.read_value ic
with Unix_error (e,_,_) -> ...
) in
Lwt.pick resps
Но я не уверен, при каких условиях Lwt.pick
будет просматривать эти обещания, отклоненные?
Обновление: теперь я обрабатываю ошибки с помощью отменяемых, невыполняемых обещаний:
fst @@ Lwt.task ()
Это кажется хакерским, но, похоже, работает до сих пор.