Выполнить функцию, если не удается выполнить другую функцию в течение периода времени
У меня уже есть функция на веб-сайте для клиента, которая получает данные с живого сервера для локального сохранения, но чего-то, чего я не ожидал, было то, что иногда эти локальные серверы не находятся в зоне с хорошим обслуживанием, поэтому каждый сейчас и затем сценарий умирает через определенное время, потому что не удалось подключиться.
У меня уже есть система, реализованная для отключения внешних вызовов для таких ситуаций, но клиенты не могут получить возможность установить этот "автономный режим" для начала, потому что служба плохая, и сервер пытается выйти в прямом эфире. сервер.
Так что мне нужно сделать, это завернуть SyncTable
функция с такой функцией, как set_time_limit(8)
которая вызывает другую функцию, которая автоматически устанавливает "автономный режим", если SyncTable
Функция не завершается в течение 8 секунд.
Возможно ли что-то подобное? Если это так, я хотел бы знать, как я могу сэкономить этим клиентам некоторое время в районах с грубым обслуживанием.
1 ответ
Вы можете сделать это, используя proc_open, proc_get_status и proc_terminate, чтобы запустить операцию SyncTable как процесс, отслеживать ее и завершать при необходимости. Примечание: вам может понадобиться создать простой скрипт-обертку, чтобы вы могли запустить функцию SyncTable как самостоятельный процесс.
Вот функция, которую я использую, чтобы сделать это и установить таймаут:
/// Executes a command and returns the output
/// If the timeout value (in seconds) is reached, it terminates the process
/// and returns FALSE
function exec_timeout($cmd, $timeout=30)
{
$descriptors = array(
0 => array('pipe', 'r'), // stdin
1 => array('pipe', 'w'), // stdout
2 => array('pipe', 'w') // stderr
);
$pipes = Array();
$process = proc_open($cmd, $descriptors, $pipes);
$result = '';
$end_time = time() + $timeout;
if (is_resource($process))
{
// set the streams to non-blocking
stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
$timeleft = $end_time - time();
while ($timeleft > 0)
{
$status = proc_get_status($process);
$result .= stream_get_contents($pipes[1]);
// leave the loop if the process has already finished
if (!$status['running'])
break;
$timeleft = $end_time - time();
}
if ($timeleft <= 0)
{
proc_terminate($process);
$result = FALSE;
}
}
// check for errors
$errors = stream_get_contents($pipes[2]);
if (!empty($errors))
fwrite(STDERR, "$errors\n");
// close streams
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);
return $result;
}