UMIhelp

Разработка дополнительного функционала => Custom макросы => Тема начата: atach от 19 Апреля 2016, 15:14:44

Название: Кастомные макрос не справляется с обработкой
Отправлено: atach от 19 Апреля 2016, 15:14:44
Подскажите как можно разделить выполнение кастомного макроса или разбить его. Постоянно таймаут.
Макрос по выборки "new selector('pages');" и дальнейшей обработки страниц участвующей в этой выборке.
В результате под обработку попадает в среднем около 9-11 тыс. объектов.
В обработки идет простой перебор, с сохранение данных, пример:
$pages = new selector('pages');
$pages->types('hierarchy-type')->name('catalog', 'object');
foreach($pages as $page) {
    $page->setValue("fieldname", $newValue);
    $page->commit();
}
Соответвенно обработать такой объем не получается, постоянно таймаут.
Запускается не по крону, а по требованию, в момент отправки POST запроса с другого приложения.

Подскажите как правильно сделать, куда смотреть?
Название: Re: Кастомные макрос не справляется с обработкой
Отправлено: aghigay от 19 Апреля 2016, 15:45:32
Ограничение размера выборки:
http://api.docs.umi-cms.ru/spravochnik_po_klassam_yadra_umicms/vyborki/selector/#sel=11:1,11:7
Название: Re: Кастомные макрос не справляется с обработкой
Отправлено: atach от 24 Апреля 2016, 12:53:43
Благодарю, вопрос был правда не в этом. Моя ошибка не правильно сформулировал.
Название: Re: Кастомные макрос не справляется с обработкой
Отправлено: aghigay от 24 Апреля 2016, 12:59:28
Если речь о том, чтобы запускать скрипт порционно, то нужно придумать (или скопировать из ЮМИ) механизм порционного запуска.

Я использую обычно какой-нибудь JS скрипт, который последовательно вызывает некоторый скрипт на стороне сервера и говорит ему с какой по какую запись нужно обработать. Под рукой такого скрипта нет, но он пишется несложно. Посмотрите в сторону http://javascript.ru/setInterval

В ЮМИ реализован и подобный механизм и механизм запуска одного PHP-скрипта из другого. Для этого передаваемые переменные с идентификаторами записей передаются через сессию.

Но, в любом случае вам потребуется скрипт, которые как-то ограничивает обрабатываемую выборку.
Название: Re: Кастомные макрос не справляется с обработкой
Отправлено: atach от 24 Апреля 2016, 15:57:51
Наверно надо поподробнее описать. Не правильно вопрос изначально задал.

Из сторонего приложения в систему загружался файлик CSV, с id объектами и данными для из изменения. В файлики около 9-11 тыс. строк.

Изначально было так. На html страничке, была форма загрузки файла и он обработался через JS. Т.е. человек получал файл заходил на страницу и загружал его, после загрузки ajax ом, отправлялись данные на url (на кастомный скрипт) с параметрами ограничения выборки. А в самом кастомном скрипте был простой код который перебирал эти строки. Отправляли с ограничением выборки по 50 шт. И всё прекрасно работало.
// Приблизительно вот так:
$actionFile = file_get_contents($fileImport);
$lines = explode("\n", $actionFile);
$i = 0;
$step = 50;
$offset_next = $offset + $step;
foreach ($lines as $line) {
if($i >= $offset and $i <= $offset_next) {    
$pages = new selector('pages');
$pages->types('hierarchy-type')->name('catalog', 'object');
$pages->where('is_active')->equals(array(0,1));
$pages->where('id')->equals(...);
$result = $pages->result();
$total_findpage = $pages->length();    
..... сама обработка .....    
}
$i++;   
}

Сейчас задача изменилась, и файл для импорта ложится на сервер автоматом, по расписанию. И теперь надо по расписанию (CRON) вызывать его обработку. Как теперь сделать ограничение по выборке - непонятно. Целиком, весь этот файл при запуске через CRON не обрабатывается. Я так понимаю что в расписание я же не могу поставить файл в котором точно так же будет при помощи JS обрабатываться с ограничением выборки.

Вот в этом и стоит проблема. Если вообще не правильный подход - подскажите, направьте.
Название: Re: Кастомные макрос не справляется с обработкой
Отправлено: aghigay от 24 Апреля 2016, 19:19:08
Ничего не выдумывайте - открывайте файл /classes/modules/exchange/__import.php

В нем ЮМИ уже все придумали: и как по частям импортировать и как запускать и как проверять что скрипт закончился. Делайте по аналогии. Это второй вариант из предложенных мной в посте чуть выше (скрипт на PHP с фиксацией текущего обрабатываемого элемента в сессии)
Название: Re: Кастомные макрос не справляется с обработкой
Отправлено: Vladimir от 23 Мая 2016, 20:38:16
Сейчас задача изменилась, и файл для импорта ложится на сервер автоматом, по расписанию. И теперь надо по расписанию (CRON) вызывать его обработку. Как теперь сделать ограничение по выборке - непонятно. Целиком, весь этот файл при запуске через CRON не обрабатывается.

Очень даже обрабатывается. Вам нужно разбить скрипт на два независимых файла, например, cron1.php и cron2.php.
В первом вы получаете выборку и в цикле ее перебираете. Внутри цикла вы вызываете cron2.php, в который передаете нужные параметры, например, id элемента, и уже в этом файле идет обработка выбранного элемента.
ваш изначальный пример выглядеть будет примерно так:
#!/usr/local/bin/php
<?php

    ## Подключаем систему ##
   
    //говорим ЮМИ, что работаем из консоли
    define("UMICMS_CLI_MODE", "1");
   
    //Определяем _SERVER-переменные, не существующие в CLI
    // имитируем для ЮМИ работу по http
$_SERVER['DOCUMENT_ROOT'] = dirname(dirname(__FILE__));
    $_SERVER['SERVER_ADDR'] = '127.0.0.1';// UMI.CMS licensing
    $_SERVER['HTTP_HOST'] = 'site.ru';

    ini_set('include_path', $_SERVER['DOCUMENT_ROOT'].'/');
   
$_REQUEST['path'] = "/admin/";
   
//переходим скриптом в корень сайта, чтобы иметь возможность
    //указывать пути от корня сайта, а не сервера
    chdir($_SERVER['DOCUMENT_ROOT'].'/');
   
include $_SERVER['DOCUMENT_ROOT']."/config.php"; //ПРИМЕР ДЛЯ ВЕРСИИ 2.7 !!!!!

## Ваш скрипт ##

    $pages = new selector('pages');
    $pages->types('hierarchy-type')->name('catalog', 'object');
    foreach($pages as $page) {

        shell_exec("./cron2.php " . $page->id);
    }
?>
#!/usr/local/bin/php
<?php

    ## Подключаем систему ##   
    // Все то же, что в первом скрипте

## Ваш скрипт ##
   
        $id = (int) $argv[1];
       
        $page = umiHierarchy::getInstance()->getElement($id);

        $page->setValue("fieldname", $newValue);
        $page->commit();
?>
Для сервера при вызове shell_exec создается новый процесс, ресурсы и время выполнения которого не суммируются с родительским. Поэтому даже на виртуальном хостинге можно постепенно, очень неспешно, перебрать все элементы.
Я же, для ускорения процесса, добавлял в первый скрипт еще один цикл, чтобы передавать не один элемент, а несколько.