Задать вопрос

Как реализовать выполнение кода, когда одна из функций в нём исполняется не сразу?

Допустим, есть такая задача: получить страницу, вырезать теги, вернуть результат.

Как это делается стандартно:

function get_url_without_tags($url) {
    $content = download_page($url);
    $content_without_tags = remove_tags($content);

    return $content_without_tags;
}


Всё просто, наглядно, логично.


В моём же случае, функция download_page не будет скачивать страницу, а будет добавлять её в очередь на скачку. Сама скачка идёт в другом процессе. Т.е. результат выполнения функции download_page мы получим не сразу.


Пришло в голову что-то типа событийной модели:

function get_url_without_tags($url) {
    task::add('download_page', $url, function ($content) {
        $content_without_tags = remove_tags($content);
        return $content_without_tags;
    });
}


Но реализовывать такое оказалось жутко неудобно: такая обертка task::add нужна для разных функций с разными параметрами, внутри анонимной функции нет доступа к изначальным параметрам (в данном случае к $url), для большого кол-ва вложенных task::add код становится нечитаемым и т.д.


Как реализовать подобное?

Есть ли готовые решения?


Хотелось бы реализации максимально близкой к простоте первого варианта.
  • Вопрос задан
  • 3390 просмотров
Подписаться 3 Оценить 2 комментария
Решения вопроса 1
kuzemchik
@kuzemchik
внутри анонимной функции нет доступа к изначальным параметрам (в данном случае к $url)

Эмм? www.php.net/manual/en/functions.anonymous.php
function get_url_without_tags($url) {
    task::add('download_page', $url, function ($content)  use ($url)  {
        $content_without_tags = remove_tags($content);
        return $content_without_tags;
    });
}
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 4
@Vampiro
Сделайте вторую очередь на парсинг результатов и туда добавляйте задания в обработчике загрузки.
Ответ написан
Комментировать
serverok
@serverok
Сделайте так:
— функция download_page($url) добавляет УРЛ на закачивание и получает некий ID этой урла в очереди;
— также добавте статус закачивания каждого урла в очередь;
— потом в цыкле проверяйте статус по ID: если статус «ждем» — то и вы ждете, если статус «завершено» — выполняете остальной код.
Ответ написан
Комментировать
AmdY
@AmdY
PHP и прочие вебштучки
Вам нужно использоватm, но в очередь замыкание не передашь, пjэтому у вас должен быть таск из нахвания и серриализируемого массива, чтобы его мог восстановить воркер, обрабатывающий задачу
Task::add('task_name', ['url' => $url, .....]);
Ответ написан
Комментировать
@boodda
Вам дали ответ, но вот у меня был опыт изготовления именно этой функции, задание на скачивание URL, его обработку и выдачу данных в аккаунт. Решил это так немогу конкретный код сейчас привести, но суть такова:

Скрипт получая все параметры
1. вставляет все данные в MySQL со статусом «Ожидает», получает id
2. скрипт скрипт лочит файл .lock(php ждет если он в данный момент залочен)
3. открывает файл urls пишет туда ID:URL (ID это который от базы получили) в режиме APPEND
4. снимает лок с файла
5. выдает статус «ID: Ожидается» во фронтэнд
6. завершает свою работу.

По крону каждые 3 секунды запускается bash скрипт который:
1. лочит файл .lock
2. читает файл urls, отрезает оттуда 10 урлов, остальные складывает обратно в файл
3. снимает лок.
4. С помощью lynx качается урл, и сразу скидывается на диск (есть ключ для lynx, хотя вы можете закачать wget, смотря какая у вас задача).

По крону каждые 10 секунд, запускается PHP скрипт который:
1. открывает папку и получает её листинг
2. выбираются все задания, статус которых «ожидается»
3. 30 записей из них помечаются статусом «обработка»
4. 30 этих файлов обрабатываются, результат по ID(из имени файла) присваивает статус в MySQL «готово», туда же вставляются все данные, которые были получены при обработке
5. скрипт завершается, удаляя все обработаные файлы.

Ajax скрипт периодически узнает не готовы ли файлы которые в очереди.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы