SafeStream: bezpiecznie do plików

Nette SafeStream gwarantuje, że każdy odczyt i zapis do pliku jest izolowany. Oznacza to, że żaden wątek nie rozpocznie czytania pliku, który nie jest jeszcze w pełni zapisany, lub wiele wątków nadpisze ten sam plik.

Instalacja:

composer require nette/safe-stream

Do czego się nadaje?

Do czego przydaje się izolowana chirurgia? Zacznijmy od prostego przykładu, który wielokrotnie zapisuje do pliku, a następnie odczytuje z niego ten sam ciąg znaków:

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

$counter = 1000;
while ($counter--) {
	file_put_contents('soubor', $s); // zapisujemy
	$readed = file_get_contents('soubor'); // czytaj
	if ($s !== $readed) { // sprawdź to
		echo 'řetězce se liší!'
	}
}

Może się wydawać, że wezwanie na echo 'řetězce se liší!' nigdy nie może mieć miejsca. Jest wręcz przeciwnie. Spróbuj uruchomić ten skrypt w dwóch zakładkach przeglądarki jednocześnie. Błąd pojawi się niemal natychmiast.

Jedna z zakładek odczyta plik, gdy druga zakładka nie zapisała jeszcze całego pliku, więc zawartość nie będzie kompletna.

Dlatego kod nie jest bezpieczny, jeśli jest wykonywany wielokrotnie w tym samym czasie (tj. W wielu wątkach). Co nie jest rzadkością w internecie, często serwer odpowiada na dużą liczbę użytkowników w jednym czasie. Tak więc zapewnienie, że twoja aplikacja działa niezawodnie nawet podczas wykonywania w wielu wątkach (thread-safe) jest bardzo ważne. W przeciwnym razie dane zostaną utracone i pojawią się trudne do wykrycia błędy.

Ale jak widać, natywne funkcje odczytu i zapisu plików w PHP nie są izolowane i atomowe.

Jak korzystać z SafeStream?

SafeStream tworzy bezpieczny protokół, który może być używany do odczytu i zapisu plików w izolacji przy użyciu standardowych funkcji PHP. Wystarczy umieścić nette.safe:// przed nazwą pliku:

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

SafeStream zapewnia, że nie więcej niż jeden wątek może pisać do pliku w tym samym czasie. Pozostałe wątki ustawiają się w kolejce. Jeśli żaden wątek nie pisze, dowolna liczba wątków może czytać plik równolegle.

Wszystkie popularne funkcje PHP mogą być używane z protokołem, na przykład:

// 'r' oznacza otwarcie tylko do odczytu
$handle = fopen('nette.safe://file.txt', 'r');

$ini = parse_ini_file('nette.safe://translations.neon');
wersja: 3.0