Увечиличаем скорость синхронизации 1С с minishop2 в 3-5 раз. mSklad/mSync

Не давно обнаружил что во время синхронизации с 1С, есть возможность указать 1С-ке: упаковать в архив все файлы выгрузки и отправить на сервер.

Из-за того что 1С отправляет import.xml, offers.xml и изображения по одному файлу, синхронизация с сайтом довольно надолго затягивается.

К примеру: если у вас 1000 изображений (а время на отправку изображения минимум 1-2 секунды) то нетрудно подсчитать что в итоге ваша загрузка займет минимум 16 минут, это только на отправку файлов на сервер не считая самой обработки файлов.

Эта небольшая доработка класса, скажет 1С отправлять файлы в архиве со всеми данными целиком.
После чего архив будет слаться частями (размер архива указывается в file_limit).
Допустим что интернет у нас слабенький и укажим чтобы часть архива была максимум 10мб.

Внимание!!! Этот метод использовался для синхронизации через mSklad, так что ваш класс может чем то отличатся. Не советую пробовать на боевом сайте.

После того как 1С отправит все части архива на сайт, 1С будет запускать функцию import до тех пор, пока та не ответить ей success. Таким образом через добавленную функцию extractZIP распакуется весь архив и как только все файлы из архива будут распакованы, архив будет удален и начнется стандартная синхронизация.

Доработка класса


Необходимо добавить в класс: mskladCatalogHandler/msyncCatalogHandler наши новые функции которые будут искать и распаковывать файлы на сервер:
/** @var int $file_limit - максимальный лимит в байтах передаваемый 1С (1000000 байт/1 мб) */
    protected $file_limit = 10000000;

    /**
     * @var string $zip
     * no - передача файлов по одному
     * yes - передача файлов в zip архиве
     */
    protected $zip = 'yes';

    /* @var ZipArchive|null $ZipArchive */
    protected $zipArchive = null;


    /**
     * Поиск архива в директории
     * @return null|string
     */
    private function findZIP()
    {
        $path = $this->config['temp_dir'];
        $filePath = null;
        $files = scandir($path);
        foreach ($files as $file) {
            if (preg_match('/.*?\.zip/i', $file)) {
                $filePath = $path . $file;
                break;
            }
        }
        return $filePath;
    }

    /**
     * Распаковка архива в случае если он есть директории
     * @return string
     */
    private function extractZIP($filePath)
    {
        $path = $this->config['temp_dir'];
        $start_records = empty($_SESSION['start_records_zip']) ? 0 : $_SESSION['start_records_zip'];

        // распаковываем
        if (file_exists($filePath)) {
            // работаем с zip
            $this->zipArchive = new ZipArchive;
            if ($this->zipArchive->open($filePath) == TRUE) {
                for ($i = $start_records; $i < $this->zipArchive->numFiles; $i++) {
                    if (!$name = $this->zipArchive->getNameIndex($i)) {
                        $this->modx->log(modX::LOG_LEVEL_ERROR, "Не удалось получить имя файла index {$i} zip архив {$filePath}", '', __METHOD__, __FILE__, __LINE__);
                    }

                    if (!$this->zipArchive->extractTo($path, $name)) {
                        $this->modx->log(modX::LOG_LEVEL_ERROR, "Не удалось распаковать файл {$name} в директорию {$path} zip архив {$filePath}", '', __METHOD__, __FILE__, __LINE__);
                    }

                    $exec_time = microtime(true) - $this->config['start_time'];
                    if($exec_time+1>=$this->config['max_exec_time']){
                        return true;
                        #return 'progress'.PHP_EOL.'Распаковка архива'.$start_records.PHP_EOL;
                    }

                    $start_records++;
                    $_SESSION['start_records_zip'] = $start_records;

                }
            } else {
                $this->modx->log(modX::LOG_LEVEL_ERROR, "Не удалось открыть архив {$filePath}. Возможно он поврежден", '', __METHOD__, __FILE__, __LINE__);
                return false;
            }

            // Удаление файла
            unlink($filePath);
        }

        return true;
    }


Чтобы 1С запаковала наши файлы в архив, модифицируем функцию init, заменяем последнюю строку на::

///////////public function init() {

        // Заменить
        return 'zip=no' . PHP_EOL . 'file_limit=' . $this->modx->getOption('upload_maxsize', null, 1000000) . PHP_EOL;
        
        //  На
        unset($_SESSION['start_records_zip']);
        return 'zip='.$this->zip.PHP_EOL.'file_limit='.$this->file_limit.PHP_EOL;

Чтобы распаковать архив с файлами, добавляем в начало функции import следующие код:
////////// public function import(
        
        if ($this->zip == 'yes') {
            // Поиск файла архива
            if ($filePath = $this->findZIP()) {
                if (!$this->extractZIP($filePath)) {
                    $response = 'failure'.PHP_EOL.'Please see errors in MODX log'.PHP_EOL;
                } else {
                    $response = 'progress' . PHP_EOL;
                }
                // Закрытие архива если была остановка
                if ($this->zipArchive) {
                    $this->zipArchive->close();
                }
                return $response;
            }
        }

Заключение


Таким не очень сложным способом можно довольно таки хорошо ускорить синхронизацию.

Например у моего заказчика слабый интернет и выгрузка 5000 товаров занимала 2.5 — 3 часа, сейчас время на выгрузку занимает 40-60 минут.

— Еще есть несколько моментов касаемо удаления файлов. Если папка import_images не удаляется сама то в функцию init нужно добавить код
// Этот код нужен для отчистики диретории с файлами.
    $cachemanager = $this->modx->getCacheManager();
    $cachemanager->deleteTree($this->config['temp_dir'], ['deleteTop' => false, 'extensions' => []]);
— Так же возможны проблемы с загрузка изображений в товаров. Так как в старых версиях mSklad все файлы складывались в папку temp и использовалось базовое имя изобрежения в место пути к нем.
Для исправления нужно залезть функцию uploadImagesMsProduct и найти basename().
Андрей Степаненко
01 апреля 2019, 13:45
6
346
+10
Поблагодарить автора Отправить деньги

Комментарии: 0

Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.