Skip to content

Разделение YML на части #84

Open
freimaks opened this issue Sep 17, 2020 · 2 comments
Open

Разделение YML на части #84

freimaks opened this issue Sep 17, 2020 · 2 comments

Comments

@freimaks
Copy link

freimaks commented Sep 17, 2020

Всем привет!

Недавно тут задавали вопрос про белый экран и в общем-то напрашивается простое решение - сегментировать YML файл на части подобно тому как это делается для сайтмапов.

Причем тоже самое нам говорит документация самого Яндекса:

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

Хотя речь конечно может идти и не про 500 тысяч, а даже про пару-тройку десятков тысяч товаров, чтобы гарантировать обработку запроса со стороны вашего сервера.

Коррекции затрагивают только контроллер yandex_money.php и больше никаких правок не делает (можно оформить и в виде ocmod):

public function market() {
        $per_page = 0;
        if(isset($this->request->get['per_page'])) {
            $per_page = $this->request->get['per_page'];
        }

        $page = 0;
        if(isset($this->request->get['page'])) {
            $page = $this->request->get['page'];
        }        
        
        $xml = $this->getMarketXml($per_page, $page);

        $this->response->addHeader('Content-Type: application/xml; charset=utf-8');
        $this->response->setOutput($xml);
    }
private function getMarketXml($per_page, $page) {
        $cache     = new Cache("file");
        $marketXml = $cache->get("ym_market_xml");

        $marketXml = ''; // Вопрос с кэшем нужно решать дополнительно

        if (empty($marketXml)) {
            $marketXml = $this->generateMarketXml($per_page, $page);
            $cache->set("ym_market_xml", $marketXml);
        }

        return $marketXml;
    }
private function generateMarketXml($per_page, $page) {
$this->setDelivery()
             ->setCurrencies($currency_default, $offers_currency)
             ->setCategories($categories, $allowCategories)
             ->setProducts($currency_default, $strCategoryIds, $additionalConditionMap, $per_page, $page);
}
    private function setProducts($currency_default, $strCategoryIds, $additionalConditionMap, $per_page, $page)
    {
        $this->load->model('catalog/product');
        $this->load->model('tool/image');

        $nameTemplate = explode('%', $this->config->get('yandex_money_market_name_template'));
        $products     = $this->getMarketModel()->getProducts($strCategoryIds, false);
        $length       = new \Cart\Length($this->registry);

        $startFor = 0;
        $endFor = 0;

        if($per_page <= 0 || $page <= 0 || $per_page >= count($products)) {
            $startFor = 0;
            $endFor = count($products);
        } else {
            // $per_page = 1000, $page = 1: $startFor = 0, $endFor = 1000 (999)
            // $per_page = 1000, $page = 17: $startFor = 16000, $endFor = 17000 (16999)
            $startFor = $page * $per_page - $per_page;
            $endFor = $page * $per_page;

            if($startFor > count($products)){
                $startFor = count($products);
            }

            if($endFor > count($products)){
                $endFor = count($products);
            }
        }

        //foreach ($products as $product) {
        for($i = $startFor; $i < $endFor; $i++) {
            $product = $products[$i];
}

При таких изменениях адрес к YML будет выглядеть так:
https://tratata.ta/index.php?route=extension/payment/yandex_money/market&per_page=1000&page=24

В ином случае нужны слишком большие таймауты для NGINX и PHP, чтобы дождаться генерации единого YML-файла.

P.S. Нагрузку на сервер может вызывать не только перебор товаров, но и к примеру выполнение операции $offer->addPicture($this->model_tool_image->resize($product['image'], 600, 600)); в случае, если у вас очищен кэш изображений (бонусом resize часто не только делает саму обрезку, но и генерирует дополнительное изображение в каком-нибудь WebP, чтобы обрадовать Google использованием современных форматов изображений).
P.P.S. На скорость выборки (в особенности товаров со всеми атрибутами, опциями и изображениями) может влиять отсутствие дополнительных индексов в БД. Но это уже не относится напрямую к этому модулю.

@ostulov
Copy link

ostulov commented Sep 18, 2020

Добрый день!

Благодарю за подробное описание, рассмотрим Ваше предложение!

@freimaks
Copy link
Author

Добрый день!

Благодарю за подробное описание, рассмотрим Ваше предложение!

@ostulov, здравствуйте! Если Вы рассматриваете предложения по доработкам, то есть еще пара моментов:

  1. В админке для Маркета сделать настройку размеров изображений. У Яндекса, судя по документации, есть ограничения - не менее 300 пикселей (по любой из сторон) и не более 3500 пикселей (по большей из сторон). Сейчас в Вашем модуле жестко зашиты размеры 600x600 (рекомендуемые Яндексом) и это не очень удобно в том случае, если используемый шаблон устанавливает другие размеры (например, 800x800, 1200x1200 и т.п.). Соответственно получается, что лишние изображения и отъедают время на генерацию, и занимают лишнее место на диске, при этом никакого смысла в них нет.

  2. Сделать для Маркета использование кэша опциональным с управлением через ту же админку. Тут проблема только для тех, у кого идет постоянная синхронизация складских остатков. Соответственно приходится либо после каждой синхронизации чистить кэш, либо просто глушить его использование в модуле. Если генерация YML по ссылке оптимизирована и укладывается в требуемые 150 секунд, то пусть сервер и генерирует его постоянно при каждом запросе робота.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Development

No branches or pull requests

2 participants