SafeStream: Segurança para arquivos

Nette SafeStream garante que cada leitura e escrita em um arquivo seja isolada. Isto significa que nenhum thread começará a ler um arquivo que ainda não está totalmente escrito, ou múltiplos threads não sobregravarão o mesmo arquivo.

Instalação:

composer require nette/safe-stream

Para que é bom?

Para que servem de fato as operações isoladas? Comecemos com um exemplo simples que escreve repetidamente em um arquivo e depois lê a mesma seqüência a partir dele:

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

$counter = 1000;
while ($counter--) {
	file_put_contents('file', $s); // escreva-o
	$readed = file_get_contents('file'); // leia-o
	if ($s !== $readed) { // verifique
		echo 'as cordas são diferentes';
	}
}

Pode parecer que echo 'strings differ!' nunca poderá ocorrer. O oposto é verdade. Tente executar este script em duas abas do navegador ao mesmo tempo. O erro ocorrerá quase imediatamente.

Uma das abas lerá o arquivo em um momento em que a outra não teve a chance de escrevê-lo todo, portanto o conteúdo não estará completo.

Portanto, o código não é seguro se ele for executado várias vezes ao mesmo tempo (ou seja, em vários fios). O que não é incomum na Internet, muitas vezes um servidor responde a um grande número de usuários ao mesmo tempo. Portanto, é muito importante garantir que sua aplicação funcione de forma confiável mesmo quando executada em vários threads (thread-safe). Caso contrário, os dados serão perdidos e erros difíceis de serem detectados ocorrerão.

Mas como você pode ver, as funções de leitura e escrita do arquivo nativo do PHP não são isoladas e atômicas.

Como usar o SafeStream?

SafeStream cria um protocolo seguro para ler e escrever arquivos isoladamente usando funções PHP padrão. Tudo o que você precisa fazer é especificar nette.safe:// antes do nome do arquivo:

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

SafeStream garante que no máximo um thread possa escrever no arquivo de cada vez. Os outros threads estão esperando na fila. Se nenhuma thread estiver escrevendo, qualquer número de threads pode ler o arquivo em paralelo.

Todas as funções comuns do PHP podem ser usadas com o protocolo, por exemplo:

// 'r' significa somente leitura aberta
$handle = fopen('nette.safe://file.txt', 'r');

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