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

Асинхронная работа ZipArchive (::addFromString) теряет файлы, как победить?

Входные данные:
OS: Debian 9
PHP: v7.4
Есть директория с ~1КК файлов {unixtime}.json размером до 1Мб.
Делаю переименование файлов с его изменением внутреннего содержимого, а потом пытаюсь запаковать их все в один архив с помощью метода addFromString.
Суть проблемы в том, что при асинхронном использовании методов ZipArchive, на выходе я получаю нужных архив, но только с последним обработанным файлом в рамках асинхронности (Если быть совсем точным, то в архив попадает N/t файлов, где N - всего файлов к добавлению, t - количество потоков обработки)

Привожу ниже упрощенную схему работы ($dir,$newFileName, $stringData определены к этому моменту ):

$za = new \ZipArchive();
 ($za->open($zipFile, \ZipArchive::CREATE) !== TRUE) {
      throw new \Exception('Cannot create a zip file');
 } 
$arFile = $dir . '/' . $newFileName . '.json';
$result = $za->addFromString($arFile, $stringData);
$error = $za->getStatusString( );
$arIndex = $za->locateName($arFile);
$arInfo = $za->statName($arFile);
$closeResult = $za->close();
 var_dump($error, $arIndex, $arInfo, $closeResult);

Вывод
4 => string(8) "No error"
int(0)
array(8) {
["name"]=>
string(23) "/orders/01_01_2021.json"
["index"]=>
int(0)
["crc"]=>
int(0)
["size"]=>
int(1006)
["mtime"]=>
int(1617438268)
["comp_size"]=>
int(1006)
["comp_method"]=>
int(0)
["encryption_method"]=>
int(0)
}
bool(true)


Как видно, файл успешно добавляется , имеет свой индекс и существует до момента закрытия архива.
Еще момент, при асинхронном добавлении получается, что в рамках числа потоков добавляемые файлы имеют один и тот же индекс (в моем случае 0), что по видимому и приводит к "потере" добавляемых файлов. Возможно это не правильное назначение индексов , но повлиять я на нее не могу. Как это можно победить?
PS- записывать промежуточные файлы не хотелось бы. Изначальное наличие архива не меняет ситуацию.
Спасибо за помощь!
  • Вопрос задан
  • 154 просмотра
Подписаться 2 Средний 11 комментариев
Пригласить эксперта
Ответы на вопрос 1
s5656
@s5656
Ну давайте обратимся к документации и попробуем понять в какой момент происходят изменения в конечном файле:

ZipArchive::close — Close opened or created archive and save changes. This method is automatically called at the end of the script.

То есть либо при вызове ZipArchive::close, либо в конце скрипта (так как автоматически вызывается ZipArchive::close).

Сам по себе ZipArchive — синхронный.
Если в одном потоке, то вы создаете и редактируете один архив, через один объект ZipArchive и когда вызываете close — все сохраняется в файл, на диск.
Если вы работаете в нескольких потоках, то у вас создается несколько ZipArchive, которые друг о друге ничего не знают и когда вы вызываете close — каждый из них пытается сохранить свои изменения и здесь уже кто последний тот и папа сохранил свою версию.

Нужно либо как-то передавать экземпляр ZipArchive между вашими потоками, либо писать свою (или найти готовую) библиотеку для асинхронной работы с zip архивами.

Как более простой вариант — делать работу с файлами асинхронно (во временной директории?), а затем их архивировать через тот же zip (консольную утилиту).
Ответ написан
Ваш ответ на вопрос

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

Похожие вопросы
22 дек. 2024, в 10:44
15000 руб./за проект
22 дек. 2024, в 10:12
10000 руб./за проект
22 дек. 2024, в 09:51
3000 руб./за проект