Проблема в том, что нужно чтение с тайм-аутом . Если firehose
ничего не отправляет, ваш цикл блокируется на неопределенное время , и когда он это делает, он не может отправить последнюю полученную строку. Bash имеет аргумент -t для чтения по времени -. Если у zsh read
есть это, то это то, что нужно использовать.
Алгоритм заключается в том, чтобы продолжать чтение строк с тайм-аутом, который всегда повторно -вычисляется (укорачивается все больше и больше )до истечения одной секунды (или любого другого )интервала. Когда этот интервал наступит, тогда, если одна или несколько строк были прочитаны, отправьте последнюю. В противном случае ничего не отправляйте и начинайте читать строки для следующего интервала.
Вы можете реализовать «мгновенный проход» для самой первой полученной строки или для первой строки, полученной по прошествии периода времени, превышающего интервал. Например, если интервал равен 1 секунде, и ничего не пришло из firehose
в течение 1,5 с момента последнего вывода строки, то эту строку можно пройти, и механизм может сбросить, чтобы начать новый интервал в одну секунду в этой точке..
Это доказательство -реализации концепции -в TXR Lisp работает для меня, подтверждая базовый алгоритм:
(defvarl %interval% 1000000) ;; us
(defun epoch-usec ()
(tree-bind (sec. usec) (time-usec)
(+ (* 1000000 sec) usec)))
(let ((now (epoch-usec))
(*stdin* (open-fileno (fileno *stdin*) "rl")) ;; line buffered
remaining-time next-time line done)
(while (not done)
(set next-time (+ now %interval%))
(set remaining-time (- next-time now))
(while (poll (list (cons *stdin* poll-in))
(trunc remaining-time 1000))
;; got a line or EOF poll: no timeout
(iflet ((nline (get-line)))
(set line nline) ;; got line
(progn (flip done) (return))) ;; EOF poll
(set now (epoch-usec))
(when (minusp (set remaining-time (- next-time now)))
(return)))
;; timeout, past deadline or exit: flush line, if any:
(when line
(put-line line)
(set line nil))))
Настроен небуферизованный поток, так как poll
используется для считывания по времени -вывода, а poll
не видит буферов потока. Идея состоит в том, что мы не хотим опрашивать ввод, пока в потоке есть непрочитанные буферизованные данные. Это придирка. При тестировании я не увидел качественной разницы в поведении между этим и просто использованием буферизованного исходного потока *stdin*
. Если мы тратим время на опрос, когда в потоке есть буферизованные данные, а в дескрипторе файла их нет, мы гарантированно не будем ждать дольше, чем наш интервал времени, и меньше, если новые данные поступят раньше.
Мы предполагаем, что успешное выполнение poll
означает, что мы можем прочитать всю строку. poll
не гарантирует этого, конечно, но хорошо -работающие источники ввода текстового потока должны обеспечивать гарантию того, что если один байт ввода доступен для пробуждения poll
, за этим байтом следует полная строка. без неоправданной задержки.
При расчете оставшегося времени используется календарное время, тогда как poll
просто используется относительное ожидание, которое, вероятно, нечувствительно к корректировкам времени. Поэтому применяются обычные предостережения. Если часы вдруг прыгнут назад, опа!
Эти тестовые примеры выполняются без заметной задержки:
$ echo foo | txr throttle.txr
foo
$ (echo foo; echo bar) | txr throttle.tl
bar
$ (echo foo; echo bar; echo xyzzy) | txr throttle.tl
xyzzy
Тогда:
$ (echo foo; sleep 2; echo bar; sleep 2; echo xyzzy) | txr throttle.tl
foo
bar
xyzzy
Я тестировал find / | txr throttle.tl
и тому подобное.
Пакеты, созданные Nix, обычно используют DT_RUNPATH
запись в файлах ELF для поиска общих библиотек. Вы можете использовать, например, nix run -f. patchelf -c patchelf --print-rpath app
для просмотра записей. В вашем случае он вернет что-то вроде этого:
/nix/store/7gx4kiv5m0i7d7qkixq2cwzbr10lvxwc-glibc-2.27/lib:/nix/store/sf3jq8d81gx6fmxsi0mhagpgsgpnxf6m-postgresql-9.6.12-lib/lib
Поскольку это абсолютные пути, вам потребуются соответствующие пути в магазине Nix для поиска библиотек.
Если вы знаете коммит nixpkgs
, который вы использовали для сборки программы, вы можете запустить nix-build -f https://github.com/NixOS/nixpkgs/archive/${commit}.tar.gz -A postgresql.lib
на втором компьютере, чтобы добавить библиотеку в хранилище. Но имейте в виду, что если вы не добавите его в корень GC, он может быть очищен сборщиком мусора.
Если вы построили свою программу как выражение Nix, довольно легко экспортировать все замыкание и импортировать его на другой компьютер.