Реализация простого опроса файла результатов

Для одного из моих модулей сбора данных диссертации я реализовал простой механизм опроса. Это необходимо, потому что я делаю каждый запрос на сбор данных (один из многих) в виде SQL-запроса, представленный через веб-форму, который имитируется кодом RCurl. Сервер обрабатывает каждый запрос и генерирует текстовый файл с результатами по определенному URL-адресу (RESULTS_URL в коде ниже). Независимо от запроса, URL и имя файла совпадают (я не могу это изменить). Поскольку время обработки для разных запросов данных, разумеется, различно, и некоторые запросы могут занимать значительное количество времени, мой код R должен "знать", когда результаты готовы (файл сгенерирован), чтобы он мог извлеките их. Следующее - мое решение для этой проблемы.

POLL_TIME <- 5 # polling timeout in seconds

В функции srdaRequestData() перед выполнением запроса данных:

# check and save 'last modified' date and time of the results file
# before submitting data request, to compare with the same after one
# for simple polling of results file in srdaGetData() function
beforeDate <- url.exists(RESULTS_URL, .header=TRUE)["Last-Modified"]
beforeDate <<- strptime(beforeDate, "%a, %d %b %Y %X", tz="GMT")

<making data request is here>

В функции srdaGetData(), вызываемой после srdaRequestData()

# simple polling of the results file
repeat {
  if (DEBUG) message("Waiting for results ...", appendLF = FALSE)
  afterDate <- url.exists(RESULTS_URL, .header=TRUE)["Last-Modified"]
  afterDate <-  strptime(afterDate, "%a, %d %b %Y %X", tz="GMT")
  delta <- difftime(afterDate, beforeDate, units = "secs")
  if (as.numeric(delta) != 0) { # file modified, results are ready
    if (DEBUG) message(" Ready!")
    break
  }
  else { # no results yet, wait the timeout and check again
    if (DEBUG) message(".", appendLF = FALSE)
    Sys.sleep(POLL_TIME)
  }
}

<retrieving request results is here>

Основной поток/последовательность событий модуля является линейным, следующим образом:

Read/update configuration file
Authenticate with the system
Loop through data requests, specified in configuration file (via lapply()),
  where for each request perform the following:
  {
    ...
    Make request: srdaRequestData()
    ...
    Retrieve results: srdaGetData()
    ...
  }

Проблема с приведенным выше кодом заключается в том, что она не работает , как ожидалось: при выполнении запроса данных код должен печатать "Ожидание результатов"...", а затем, периодически проверяя файл результатов для изменения (сгенерированный), печатайте точки выполнения до тех пор, пока результаты не будут готовы, когда он распечатает подтверждение. Однако фактическое поведение заключается в том, что код ждет много времени (я намеренно сделал один запрос долговременным), а не печатал что-либо, но затем, по-видимому, извлекает результаты и печатает как "Ожидание результатов".. "и "Готов" в то же время.

Мне кажется, что это какая-то проблема синхронизации, но я не могу понять, что именно. Или, может быть, это что-то еще, и я как-то пропустил это. Ваши советы и помощь будут очень благодарны!

Ответ 1

В комментарии к вопросу, я считаю, что MrFlick решил проблему: логика опроса кажется функциональной, но проблема в том, что сообщения о ходе не синхронизируются с текущими событиями в системе.

По умолчанию вывод консоли R буферизируется. Это по дизайну: ускорить работу и избежать отвлекающего мерцания, которое может быть связано с частыми сообщениями и т.д. Мы склонны забывать об этом факте, особенно после того, как мы использовали R в очень интерактивном режиме, запуская различные объявления ad-hoc на консоли (консольный буфер автоматически размывается перед возвратом приглашения >).

Однако можно получить message() и более общий вывод консоли в "реальном времени" путем явного промывания консоли после каждого критического оператора вывода с использованием функции flush.console() или путем отключения буферизации на уровне R GUI (щелкните правой кнопкой мыши на консоли, см. Пункт Buffered output Ctrl W. Это также доступно в меню Misc)

Здесь показан пример использования явного использования flush.console. Обратите внимание на использование cat(), а не message(), поскольку первое не добавляет CR/LF к выходу автоматически. Последнее, однако, полезно, однако, поскольку его сообщения могут быть подавлены с помощью suppressMessages() и тому подобного. Также, как показано в комментарии, вы можете нарисовать символ "\ b" (backspace), чтобы номер перезаписывался.

CountDown <- function() {
  for (i in 9:1){
    cat(i)
    # alternatively to cat(i) use:  message(i)
    flush.console()    # <<<<<<<  immediate ouput to console.
    Sys.sleep(1)
    cat(" ")   # also try cat("\b") instead ;-)
  }
  cat("... Blast-off\n")
}

Вывод следующий: в этом распечатке, конечно, не видно, что в течение всего 10 секунд каждое число было напечатано, прежде чем окончательный "Blast off"; удалите инструкцию flush.console(), и вывод будет выполнен сразу, через 10 секунд, то есть когда функция завершится (если консоль не буферизована на уровне графического интерфейса пользователя).

CountDown()  9 8 7 6 5 4 3 2 1... Взрыв