SafeStream: безопасна работа с файлове

Nette SafeStream гарантира, че всяко четене и запис във файл протича изолирано. Това означава, че никоя нишка няма да започне да чете файл, който още не е изцяло записан, или повече нишки няма да презаписват същия файл.

Инсталация:

composer require nette/safe-stream

За какво е полезно това?

За какво са полезни изолираните операции всъщност? Да започнем с прост пример, който многократно записва във файл и впоследствие чете от него същия низ:

$s = str_repeat('Long String', 10000);

$counter = 1000;
while ($counter--) {
	file_put_contents('soubor', $s); // запишете го
	$readed = file_get_contents('soubor'); // прочетете го
	if ($s !== $readed) { // проверете го
		echo 'низовете се различават!'; // низовете се различават!
	}
}

Може да изглежда, че извикването echo 'низовете се различават!' никога не може да настъпи. Обратното е истина. Нарочно опитайте да стартирате този скрипт в два таба на браузъра едновременно. Грешката ще се появи практически незабавно.

Един от табовете ще прочете файла в момент, когато другият още не е успял да го запише изцяло, така че съдържанието няма да бъде пълно.

Следователно посоченият код не е безопасен, ако се изпълнява повече от веднъж в един момент (т.е. в повече нишки). Което в интернет не е нищо необичайно, често в един момент сървърът отговаря на голям брой потребители. Така че осигуряването на надеждна работа на вашето приложение дори при изпълнение в повече нишки (thread-safe) е много важно. Иначе ще настъпи загуба на данни и възникване на трудно откриваеми грешки.

Както виждате обаче, нативните PHP функции за четене и запис на файлове не са изолирани и атомни.

Как да използваме SafeStream?

SafeStream създава безопасен протокол, чрез който може изолирано да се четат и записват файлове посредством стандартни PHP функции. Достатъчно е само да посочите nette.safe:// пред името на файла:

file_put_contents('nette.safe://soubor', $s);
$s = file_get_contents('nette.safe://soubor');

SafeStream осигурява, че в един момент може да записва във файла максимално една нишка. Останалите нишки чакат на опашка. Ако никоя нишка не записва, файлът може да бъде четен паралелно от произволен брой нишки.

С протокола могат да се използват всички обикновени PHP функции, например:

// 'r' означава отваряне само за четене
$handle = fopen('nette.safe://file.txt', 'r');

$ini = parse_ini_file('nette.safe://translations.neon');
версия: 3.0