Всем привет!
Недавно тут задавали вопрос про белый экран и в общем-то напрашивается простое решение - сегментировать 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. На скорость выборки (в особенности товаров со всеми атрибутами, опциями и изображениями) может влиять отсутствие дополнительных индексов в БД. Но это уже не относится напрямую к этому модулю.