Skip to content

Commit

Permalink
updated readme
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed Jan 3, 2022
1 parent 07eba89 commit 3706405
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 32 deletions.
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "nette/safe-stream",
"description": "Nette SafeStream: atomic and safe manipulation with files via native PHP functions.",
"keywords": ["nette", "atomic", "safe", "filesystem"],
"description": "Nette SafeStream: provides isolation for thread safe manipulation with files via native PHP functions.",
"keywords": ["nette", "isolation", "thread safe", "atomic", "safe", "filesystem"],
"homepage": "https://nette.org",
"license": ["BSD-3-Clause", "GPL-2.0-only", "GPL-3.0-only"],
"authors": [
Expand Down
57 changes: 27 additions & 30 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Nette SafeStream: Atomic Operations
===================================
SafeStream: Safety for Files
============================

[![Downloads this Month](https://img.shields.io/packagist/dm/nette/safe-stream.svg)](https://packagist.org/packages/nette/safe-stream)
[![Tests](https://github.com/nette/safe-stream/workflows/Tests/badge.svg?branch=master)](https://github.com/nette/safe-stream/actions)
Expand All @@ -11,66 +11,63 @@ Nette SafeStream: Atomic Operations
Introduction
------------

The Nette SafeStream protocol for file manipulation guarantees atomicity and isolation of every file operation.

Documentation can be found on the [website](https://doc.nette.org/safestream). If you like it, **[please make a donation now](https://github.com/sponsors/dg)**. Thank you!
SafeStream guarantees that every read and write to a file is isolated. This means that no thread will start reading a file that is not yet fully written, or multiple threads will not overwrite the same file.

Installation:

```shell
composer require nette/safe-stream
```

It requires PHP version 7.1 and supports PHP up to 8.1.

What is it good for?
--------------------

What exactly are atomic operations good for? Let's start with a simple example that repeatedly writes the same string to a file and then reads it:
What are isolated operations actually good for? Let's start with a simple example that repeatedly writes to a file and then reads the same string from it:

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

$counter = 1000;
while ($counter--) {
file_put_contents('file', $s); // write it
file_put_contents('file', $s); // write it
$readed = file_get_contents('file'); // read it
if ($s !== $readed) { // check it
echo 'Strings are different!';
if ($s !== $readed) { // check it
echo 'strings are different!';
}
}
```

It may seem that the `echo 'Strings are different!'` command can't ever get executed. The opposite is true. Try to run this script in two browsers tabs simultaneously. The error occurs almost immediately.
It may seem that `echo 'strings differ!'` can never occur. The opposite is true. Try running this script in two browser tabs at the same time. The error will occur almost immediately.

One tab reads the file at the moment when the other has not yet finished writing it.
One of the tabs will read the file at a time when the other hasn't had a chance to write it all, so the content will not be complete.

Therefore, the code is not safe when performed multiple at the same time (ie, in multiple threads). And that is nothing unusual on the Internet, where several people often connect to one website at the same time. Therefore, it's very important to ensure that your application can handle multiple threads at once - that it's *thread-safe* because native PHP functions are not. Otherwise, you can expect data loss and strange errors occurring.
Therefore, the code is not safe if it is executed multiple times at the same time (i.e. in multiple threads). Which is not uncommon on the internet, often a server is responding to a large number of users at one time. So ensuring that your application works reliably even when executed in multiple threads (thread-safe) is very important. Otherwise, data will be lost and hard-to-detect errors will occur.

The SafeStream offers solution: its secure protocol, through which we can atomically manipulate files through standard PHP functions. You just need prefix the filename with `nette.safe://`.
But as you can see, PHP's native file read and write functions are not isolated and atomic.

```php
file_put_contents('nette.safe://file', $s);
```

If we used the secure protocol in the first example, there would never be an error.
How to use SafeStream?
----------------------

All known functions can be used with the protocol, for example:
SafeStream creates a secure protocol to read and write files in isolation using standard PHP functions. All you need to do is to specify `nette.safe://` before the file name:

```php
$handle = fopen('nette.safe://file.txt', 'x');

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

How does it Work?
-----------------
SafeStream ensures that at most one thread can write to the file at a time. The other threads are waiting in the queue. If no thread is writing, any number of threads can read the file in parallel.

SafeStream guarantees:
All common PHP functions can be used with the protocol, for example:

- **Atomicity**: The file is written either as a whole or not written at all.
- **Isolation**: No one can start to read a file that is not yet fully written.
```php
// 'r' means open read-only
$handle = fopen('nette.safe://file.txt', 'r');

To ensure both it uses file locks and temporary files.
$ini = parse_ini_file('nette.safe://translations.neon');
```

Writing is done to temporary files and they are renamed only after successful writing. If the write fails for any reason, such as a script error or insufficient disk space, it will be discarded and an incomplete file will not be created.
-----

If you write to an existing file in `a` (append) mode, SafeStream will create a copy of it. Writing in this mode therefore has a higher overhead than writing in other modes.
Documentation can be found on the [website](https://doc.nette.org/safe-stream). If you like it, **[please make a donation now](https://github.com/sponsors/dg)**. Thank you!

0 comments on commit 3706405

Please sign in to comment.