Выполнить функцию, если не удается выполнить другую функцию в течение периода времени

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

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

Так что мне нужно сделать, это завернуть 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;
    }
Другие вопросы по тегам