Как реализовать таймаут с фрагментированным выводом для дракмы
Drakma в настоящее время не поддерживает тайм-ауты для SBCL, но мне нужен тайм-аут, который возвращает контент, перенесенный до момента времени, когда истек тайм-аут.
Это моя текущая рабочая попытка, но, вероятно, она подходит для thedailywtf вместо производственного кода:
(defun perform-request (url parameters method)
(let ((string nil))
(restart-case
(sb-ext:with-timeout 20
(let ((stream (drakma:http-request url
:method method
:parameters parameters
:want-stream T)))
(unwind-protect
(do ((char (read-char stream nil nil)
(read-char stream nil nil)))
(nil nil)
(when char
(push char string)))
(close stream))))
(ignore ()
"")
(default ()
(coerce (reverse string) 'string)))))
Попытка имеет некоторые серьезные недостатки:
- метод не может работать короче указанного времени ожидания
- используя взлом с таймаутом, чтобы вернуться из цикла while-true и убить
restart-case
чтобы получить соответствующее возвращаемое значение просто чувствует себя неправильно - символьное считывание потока вызывает значительную нагрузку на ЦП (вместо того, чтобы просто ждать завершения загрузки и затем выполнять массовое чтение)
Как я могу правильно читать из потока drakma до определенного времени ожидания (или EOF) и затем возвращать чтение в строке?