GithubHelp home page GithubHelp logo

filesystem's Introduction

ReactPHP Logo

Event-driven, non-blocking I/O with PHP.

Build Status

ReactPHP is a low-level library for event-driven programming in PHP. At its core is an event loop, on top of which it provides low-level utilities, such as: Streams abstraction, async DNS resolver, network client/server, HTTP client/server and interaction with processes. Third-party libraries can use these components to create async network clients/servers and more.

<?php

// $ composer require react/http react/socket # install example using Composer
// $ php example.php # run example on command line, requires no additional web server

require __DIR__ . '/vendor/autoload.php';

$server = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) {
    return React\Http\Message\Response::plaintext(
        "Hello World!\n"
    );
});

$socket = new React\Socket\SocketServer('127.0.0.1:8080');
$server->listen($socket);

echo "Server running at http://127.0.0.1:8080" . PHP_EOL;

This simple web server written in ReactPHP responds with "Hello World!" for every request.

ReactPHP is production ready and battle-tested with millions of installations from all kinds of projects around the world. Its event-driven architecture makes it a perfect fit for efficient network servers and clients handling hundreds or thousands of concurrent connections, long-running applications and many other forms of cooperative multitasking with non-blocking I/O operations. What makes ReactPHP special is its vivid ecosystem with hundreds of third-party libraries allowing you to integrate with many existing systems, such as common network services, database systems and other third-party APIs.

  • Production ready and battle-tested.
  • Rock-solid with stable long-term support (LTS) releases.
  • Requires no extensions and runs on any platform - no excuses!
  • Takes advantage of optional extensions to get better performance when available.
  • Highly recommends latest version of PHP 7+ for best performance and support.
  • Supports legacy PHP 5.3+ and HHVM for maximum compatibility.
  • Well designed and reusable components.
  • Decoupled parts so they can be replaced by alternate implementations.
  • Carefully tested (unit & functional).
  • Promotes standard PSRs where possible for maximum interoperability.
  • Aims to be technology neutral, so you can use your preferred application stack.
  • Small core team of professionals supported by large network of outside contributors.

ReactPHP is non-blocking by default. Use workers for blocking I/O. The event loop is based on the reactor pattern (hence the name) and strongly inspired by libraries such as EventMachine (Ruby), Twisted (Python) and Node.js (V8).

This repository you're currently looking at is mostly used as a meta repository to discuss and plan all things @ReactPHP. See the individual components linked below for more details about each component, its documentation and source code.

Core Components

Network Components

Utility Components

Built with ReactPHP

  • Thruway PHP Client and Router Library for Autobahn and WAMP (Web Application Messaging Protocol) for Real-Time Application Messaging voryx/Thruway

  • PPM - PHP Process Manager PPM is a process manager, supercharger and load balancer for modern PHP applications. php-pm/php-pm

  • php-ar-drone 🚁 Port of node-ar-drone which allows user to control a Parrot AR Drone over PHP jolicode/php-ar-drone

  • Ratchet Asynchronous WebSocket server ratchetphp/Ratchet

  • Predis\Async Asynchronous PHP client library for Redis built on top of ReactPHP nrk/predis-async

  • clue/redis-server A Redis server implementation in pure PHP clue/redis-server

And many more on our wiki page Β»

Articles

  • Sergey Zhuk A series of articles covering ReactPHP: from the basics to the real application examples. sergeyzhuk.me

  • Cees-Jan Kiewiet Blog series about several ReactPHP components and how they work. blog.wyrihaximus.net

  • LoΓ―c Faugeron Super Speed Symfony - ReactPHP. gnugat.github.io

  • Marc J. Schmidt Bring High Performance Into Your PHP App (with ReactPHP). marcjschmidt.de

  • Marc Morera When ReactPHP meet Symfony medium.com/@apisearch

Talks

Getting started

ReactPHP consists of a set of individual components. This means that instead of installing something like a "ReactPHP framework", you actually pick only the components that you need.

This project follows SemVer for all its stable components. The recommended way to install these components is through Composer. New to Composer?

For example, this may look something like this:

# recommended install: pick required components
composer require react/event-loop react/http

As an alternative, we also provide a meta package that will install all stable components at once. Installing this is only recommended for quick prototyping, as the list of stable components may change over time. This meta package can be installed like this:

# quick protoyping only: install all stable components
composer require react/react:^1.4

For more details, check out ReactPHP's homepage for quickstart examples and usage details.

See also the combined changelog for all ReactPHP components for details about version upgrades.

Support

Do you have a question and need help with ReactPHP? Don't worry, we're here to help!

As a first step, check the elaborate documentation that comes with each component (see links to individual documentation for each component above). If you find your question is not answered within the documentation, there's a fair chance that it may be relevant to more people. Please do not hesitate to file your question as an issue in the relevant component so others can also participate.

You can also check out our official Gitter chat room. Most of the people involved in this project are available in this chat room, so many questions get answered in a few minutes to some hours. We also use this chat room to announce all new releases and ongoing development efforts, so consider staying in this chat room for a little longer.

Also follow @reactphp on Twitter for updates. We use this mostly for noteworthy, bigger updates and to keep the community updated about ongoing development efforts. You can always use the #reactphp hashtag if you have anything to share!

We're a very open project and we prefer public communication whenever possible, so that more people can participate and help getting the best solutions available. At the same time, we realize that some things are better addressed in private. Whether you just want to say thank you, want to report a security issue or want to help sponsor a certain feature development, you can reach out to the core team in private by sending an email to [email protected]. Please keep in mind that we're a small team of volunteers and do our best to support anybody reaching out.

Do you want to support ReactPHP? Awesome! Let's start with letting the the world know why you think ReactPHP is awesome and try to help others getting on board! Send a tweet, write a blog post, give a talk at your local user group or conference or even write a book. There are many ways you can help. You can always reach out to us in private and help others in our support channels. Thank you!

Tests

To run the test suite, you first need to clone this repo and then install all dependencies through Composer:

composer install

To run the test suite, go to the project root and run:

vendor/bin/phpunit

The test suite also contains a number of functional integration tests that rely on a stable internet connection. Due to the vast number of integration tests, these are skipped by default during CI runs. If you also do not want to run these, they can simply be skipped like this:

vendor/bin/phpunit --exclude-group internet

License

MIT, see LICENSE.

filesystem's People

Contributors

carusogabriel avatar cboden avatar clue avatar e3betht avatar ishanvyas22 avatar jsor avatar localheinz avatar nhedger avatar reedy avatar seregazhuk avatar simonfrings avatar wyrihaximus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

filesystem's Issues

Unknown error calling "eio_open"

I faced an issue with eio adapter. Simple snippet to reproduce:

$loop = \React\EventLoop\Factory::create();

$contents = '123';

$filesystem = \React\Filesystem\Filesystem::create($loop);
echo 'Using ', get_class($filesystem->getAdapter()), PHP_EOL;

$j = 0;

$loop->addPeriodicTimer(1, function () use ($filesystem, $contents, &$j) {
    for ($i = $j; $i <= $j+9; $i++) {
        $filename = __DIR__ . '/test/'.$i.'.txt';
        $filesystem->file($filename)->putContents($contents)->then(function () use ($filename) {
            echo $filename.' written'.PHP_EOL;
        }, function (Exception $e) {
            echo $e->getMessage(), PHP_EOL;
            echo $e->getTraceAsString(), PHP_EOL;
        });
    }
    $j += 10;
});

$loop->run();

First tick written ok, others cause an error:

php test.php 
Using React\Filesystem\Eio\Adapter
/root/www/test/1.txt written
/root/www/test/2.txt written
/root/www/test/3.txt written
/root/www/test/4.txt written
/root/www/test/5.txt written
/root/www/test/6.txt written
/root/www/test/7.txt written
/root/www/test/8.txt written
/root/www/test/9.txt written
/root/www/test/10.txt written
/root/www/test/11.txt written
Unknown error calling "eio_open"
#0 /root/www/vendor/react/filesystem/src/Eio/Adapter.php(385): React\Filesystem\Eio\Adapter->executeDelayedCall('eio_open', Array, -1, Object(React\Promise\Deferred))
#1 /root/www/vendor/react/filesystem/src/InstantInvoker.php(39): React\Filesystem\Eio\Adapter->callFilesystem('eio_open', Array, -1)
#2 /root/www/vendor/react/filesystem/src/Eio/Adapter.php(271): React\Filesystem\InstantInvoker->invokeCall('eio_open', Array)
#3 /root/www/vendor/react/promise/src/FulfilledPromise.php(25): React\Filesystem\Eio\Adapter->React\Filesystem\Eio\{closure}(NULL)
#4 /root/www/vendor/react/filesystem/src/Eio/Adapter.php(273): React\Promise\FulfilledPromise->then(Object(Closure))
#5 /root/www/vendor/react/filesystem/src/Node/File.php(123): React\Filesystem\Eio\Adapter->open('/root/www/avtos...', 'cw', 496)
#6 /root/www/vendor/react/filesystem/src/Node/File.php(161): React\Filesystem\Node\File->open('cw')
#7 /root/www/test.php(16): React\Filesystem\Node\File->putContents('123')
#8 /root/www/vendor/react/event-loop/src/Timer/Timers.php(89): {closure}(Object(React\EventLoop\Timer\Timer))
#9 /root/www/vendor/react/event-loop/src/StreamSelectLoop.php(177): React\EventLoop\Timer\Timers->tick()
#10 /root/www/test.php(26): React\EventLoop\StreamSelectLoop->run()
#11 {main}

Opened files number growing and when reach system limits causing other errors e.g. DNS query failed or ssl handshake failed.

Here is another strange thing - eio_open causes an error, but ls -l /proc/23566/fd shows opened files, e.g. (but no real files created):

l-wx------ 1 root root 64 Aug 27 20:08 10 -> /root/www/data/13703540.json
l-wx------ 1 root root 64 Aug 27 20:07 11 -> /root/www/data/13493179.json

It works fine at my local deepin linux (based on debian 8), but can not make it work at any server with ubuntu 16.04/18.04. Any ideas how to debug it?

php -v
PHP 7.2.9-1+ubuntu16.04.1+deb.sury.org+1 (cli) (built: Aug 19 2018 07:16:12) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.2.9-1+ubuntu16.04.1+deb.sury.org+1, Copyright (c) 1999-2018, by Zend Technologies
composer info
aws/aws-sdk-php                           3.64.12 AWS SDK for PHP - Use Amazon Web Services in your PHP project
cakephp/core                              3.6.10  CakePHP Framework Core classes
cakephp/utility                           3.6.10  CakePHP Utility classes such as Inflector, String, Hash, and Security
campo/random-user-agent                   1.3.0   Generate real random user-agents.
clue/buzz-react                           v2.3.0  Simple, async PSR-7 HTTP client for concurrently processing any number of HTTP requests, built on top of ReactPHP
clue/http-proxy-react                     v1.3.0  Async HTTP proxy connector, use any TCP/IP-based protocol through an HTTP CONNECT proxy server, built on top of ReactPHP
clue/socks-react                          v0.8.7  Async SOCKS4, SOCKS4a and SOCKS5 proxy client and server implementation, built on top of ReactPHP
doctrine/inflector                        v1.3.0  Common String Manipulations with regard to casing and singular/plural rules.
doctrine/instantiator                     1.1.0   A small, lightweight utility to instantiate objects in PHP without invoking their constructors
evenement/evenement                       v3.0.1  Γ‰vΓ©nement is a very simple event dispatching library for PHP
guzzlehttp/guzzle                         6.3.3   Guzzle is a PHP HTTP client library
guzzlehttp/promises                       v1.3.1  Guzzle promises library
guzzlehttp/psr7                           1.4.2   PSR-7 message implementation that also provides common utility methods
hotrush/scrapoxy-react-client             1.1.0   Async client for Scrapoxy and ReactPHP
hotrush/stealer                           0.1.9   Async website scrapper tool like scrapy built with reactphp.
hotrush/stealer-scrapoxy-client           0.1.2  
indigophp/hash-compat                     v1.1.0  Backports hash_* functionality to older PHP versions
josegonzalez/dotenv                       2.1.0   dotenv file parsing for PHP
m1/env                                    2.1.2   Env is a lightweight library bringing .env file parser compatibility to PHP. In short - it enables you to read .env files with PHP.
monolog/monolog                           1.23.0  Sends your logs to files, sockets, inboxes, databases and various web services
mtdowling/jmespath.php                    2.4.0   Declaratively specify how to extract elements from a JSON document
nikic/fast-route                          v1.3.0  Fast request router for PHP
paragonie/random_compat                   v2.0.17 PHP 5.x polyfill for random_bytes() and random_int() from PHP 7
psr/http-message                          1.0.1   Common interface for HTTP messages
psr/log                                   1.0.2   Common interface for logging libraries
react/cache                               v0.5.0  Async, Promise-based cache interface for ReactPHP
react/child-process                       v0.5.2  Event-driven library for executing child processes with ReactPHP.
react/dns                                 v0.4.15 Async DNS resolver for ReactPHP
react/event-loop                          v0.5.3  ReactPHP's core reactor event loop that libraries can use for evented I/O.
react/filesystem                          v0.1.1  Asynchronous filesystem abstraction.
react/http                                v0.8.3  Event-driven, streaming plaintext HTTP and secure HTTPS server for ReactPHP
react/http-client                         v0.5.9  Event-driven, streaming HTTP client for ReactPHP
react/promise                             v2.7.0  A lightweight implementation of CommonJS Promises/A for PHP
react/promise-stream                      v1.1.1  The missing link between Promise-land and Stream-land for ReactPHP
react/promise-timer                       v1.5.0  A trivial implementation of timeouts for Promises, built on top of ReactPHP.
react/socket                              v0.8.12 Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for ReactPHP
react/stream                              v0.7.7  Event-driven readable and writable streams for non-blocking I/O in ReactPHP
ringcentral/psr7                          1.2.2   PSR-7 message implementation
symfony/css-selector                      v3.4.14 Symfony CssSelector Component
symfony/dom-crawler                       v3.4.14 Symfony DomCrawler Component
symfony/polyfill-ctype                    v1.9.0  Symfony polyfill for ctype functions
symfony/polyfill-mbstring                 v1.9.0  Symfony polyfill for the Mbstring extension
tivie/php-os-detector                     1.1.0   A small utility library that detects the OS the server is running on
wyrihaximus/cpu-core-detector             1.0.1  
wyrihaximus/json-throwable                2.0.0   JSON encode and decode throwables and exceptions
wyrihaximus/json-utilities                1.0.0   Utilities for php-json-* packages
wyrihaximus/react-child-process-messenger 2.8.2   Messenger decorator for react/child-process
wyrihaximus/react-child-process-pool      1.4.2  
wyrihaximus/react-child-process-promise   2.0.1   Wrapping ticks into a promise
wyrihaximus/react-guzzle-http-client      4.0.1   Asynchronous adapter for different Guzzle versions powered by react/http-client
wyrihaximus/react-guzzle-psr7             2.1.0   Asyncronous Guzzle (PSR7) adapter powered by react/http-client
wyrihaximus/ticking-promise               1.6.3   Wrapping ticks into a promise

not supported in windows machine

while i got free time i decided to make a php code to do a scaning in my directory using scandir().and loop it to find duplicates .if found any duplicates i wanted to move them to another folder.as this is a time taking task and was freezing my pc for long time i decided to try react php.but while trying react php i faced so much trouble and later i found there are no adaptors on windows machines.i think i wasted a lot of time on this library and feel bad about trying it at the first place...

ChildProcessAdapter cannot read/write binary files

This is caused by WyriHaximus/reactphp-child-process-messenger use of json_encode/json_decode which does not support binary strings.

I'd make a pull request but I'm not sure if this should be fixed here by (probably base64) encoding the payloads or if it should be fixed in WyriHaximus/reactphp-child-process-messenger by moving to a binary format for rpc

Example:

$loop = \React\EventLoop\Factory::create();
$filesystem = \React\Filesystem\Filesystem::create($loop);

$contents = base64_decode('UEsDBAoAAAAAAEw400'); // start of zip header
$filename = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'bin.data';

echo 'Using ', get_class($filesystem->getAdapter()), PHP_EOL;
$filesystem->file($filename)->putContents($contents)->then(function ($contents) use ($filename) {
    echo file_get_contents($filename), PHP_EOL;
}, function (Exception $e) {
    echo $e->getMessage(), PHP_EOL;
    echo $e->getTraceAsString(), PHP_EOL;
});

$loop->run();

file()->stat() not working as expected when file is symlink

I'm using dir()->ls() to create an array of nodes which I then stat, unfortunately stat() does not work as expected on symlinks: it returns the size of the symlink file (and not the target), and does not hint it is a symlink.
Neither does the nodelist ls() generates hint any of the files are symlinks: when I echo the class they are all File class.

multiple different solutions exist:
-ls() returns different nodes for files and links

-the file node has an isLink method, returning true or false

-hide the fact that the file is a symlink completely and return properties of target

-return an islink value (with target) when doing stat()

Reading a file throws error or hangs

With the following code:

<?php
require "vendor/autoload.php";

$loop = \React\EventLoop\Factory::create();
$filesystem = \React\Filesystem\Filesystem::create($loop);
$loaded = [];

// I have "big_file_5.txt" and "big_file_7.txt".
// Both with about 6 MB.
foreach (['5', '7'] as $num) {
    $filename = __DIR__.'/resources/big_file_'.$num.'.txt';

    $file = $filesystem->file($filename);
    $file->getContents()->then(
        function ($content) use ($filename, &$loaded) {
            echo "Got contents of $filename\n";
            $loaded[] = $content;
        },
        function ($error) use ($filename, &$loaded) {
            echo "Error when reading $filename\n";
            echo $error;
        }
    );
}

$loop->addPeriodicTimer(1, function () use (&$loaded) {
    echo count($loaded)." loaded files\n";
    echo "tick-tack\n";
});

echo "Running. Press CTRL+C to exit\n";
$loop->run();

The output should be something along the lines of:

$ php main.php
Running. Press CTRL+C to exit
Got contents of <project_path>/resources/big_file_7.txt
Got contents of <project_path>/resources/big_file_5.txt
2 loaded files
tick-tack
2 loaded files
tick-tack
2 loaded files
tick-tack
2 loaded files
tick-tack
^C

But sometimes the Eio throws an unknown error

$ php main.php 
Running. Press CTRL+C to exit
Error when reading <project_path>/resources/big_file_7.txt
exception 'React\Filesystem\Eio\RuntimeException' with message 'Unknown error calling "eio_open"' in <project_path>/vendor/react/filesystem/src/EioAdapter.php:280
Stack trace:
#0 <project_path>/vendor/react/filesystem/src/EioAdapter.php(254): React\Filesystem\EioAdapter->executeDelayedCall('eio_open', Array, -1, Object(React\Promise\Deferred))
#1 [internal function]: React\Filesystem\EioAdapter->React\Filesystem\{closure}(Object(React\EventLoop\LibEventLoop))
#2 <project_path>/vendor/react/event-loop/Tick/FutureTickQueue.php(46): call_user_func(Object(Closure), Object(React\EventLoop\LibEventLoop))
#3 <project_path>/vendor/react/event-loop/LibEventLoop.php(202): React\EventLoop\Tick\FutureTickQueue->tick-tack()
#4 <project_path>/main.php(32): React\EventLoop\LibEventLoop->run()
#5 {main}Got contents of <project_path>/resources/big_file_5.txt
1 loaded files
tick-tack
1 loaded files
tick-tack
^C

Or one or both reads hangs forever

Running. Press CTRL+C to exit
Got contents of <project_path>/resources/big_file_7.txt
1 loaded files
tick-tack
1 loaded files
tick-tack
1 loaded files
tick-tack
1 loaded files
tick-tack
1 loaded files
tick-tack
1 loaded files
tick-tack
1 loaded files
tick-tack
1 loaded files
tick-tack
1 loaded files
tick-tack
1 loaded files
tick-tack
1 loaded files
tick-tack
... (forever)

Every time I run the script I got one of the results randomly(?). I'm running Ubuntu 14.04.1 LTS.

@WyriHaximus, do you have an idea of what may be causing the problem?

Roadmap to stable v1.0.0

Let's face it, this project is currently beta, but has been used in production for years :shipit:

We're currently following a v0.X.Y release scheme (http://sentimentalversioning.org/).

We should finally make this stable and fully adhere to SemVer and release a stable v1.0.0.

To a large extend, a stable v1.0.0 helps making BC breaks more explicit and thus the whole project more reliable from a consumer perspective. This project is actively maintained and has received some major updates in the last months and has some major updates planned in the next months. Given our current versioning scheme, we'd like to ensure all anticipated BC breaks will be merged before the planned v1.0.0 release.

As such, I've set up a roadmap that enlists only the major changes for each version among with planned release dates towards a stable v1.0.0 release:

v0.1.0 βœ…

  • Released 2017-05-28
  • Release as is

v0.1.1 βœ…

  • Released 2018-08-09
  • Support latest react/stream

v0.1.2 βœ…

  • Released 2018-10-27
  • Several bug fixes

v0.2.0

  • Released 2019-?-?
  • Interface documentation
  • Drop PHP 5.x support
  • Clean up internally
  • Replace Object stream with RxPHP
  • Remove call invokers #61

v0.3.0

  • Released 2019-?-?
  • ext-pthreads adapter
  • ext-uv adapter #9

v1.0.0

  • Planned 2019-?
  • No new changes planned, this should merely mark the previous release as "stable"

This ticket aims to serve as a basic overview and does not contain every single change. Please also see the milestone links and the CHANGELOG for more details.

Obviously, this roadmap is subject to change and I'll try to keep it updated as we progress. In order to avoid cluttering this, please keep discussion in this ticket to a minimum and consider reaching out to us through new tickets or Twitter etc.

version 0.2.x

after years, this package version is still is under 1.
Is this package is reliable enough to use production environment ?

Add a synchronous adapter

While I recognize that the primary purpose of reactphp/filesystem is to have non-blocking io, it does have some other benefits:

  • Event / promise based
  • Abstraction from filesystem functions

In some cases the potential gains from non-blocking io are not worth guaranteed costs. In such scenarios it would still be nice to have a synchronous adapter that allows us to use the same code.

From a consumer point of view as long as the functions return promises it doesn't matter if it is blocking or not.

Tail example not working

Hey all,

Even when using the master version (which has #56 included), the tail example does not work. The error is exactly as mentioned in #81.

PHP Notice:  Undefined offset: 0 in /root/chatlogs/vendor/react/filesystem/src/ChildProcess/Adapter.php on line 226
PHP Notice:  Undefined offset: 0 in /root/chatlogs/vendor/react/filesystem/src/ChildProcess/Adapter.php on line 226
PHP Notice:  Undefined offset: 0 in /root/chatlogs/vendor/react/filesystem/src/ChildProcess/Adapter.php on line 226
PHP Notice:  Undefined offset: 0 in /root/chatlogs/vendor/react/filesystem/src/ChildProcess/Adapter.php on line 226
PHP Notice:  Undefined offset: 0 in /root/chatlogs/vendor/react/filesystem/src/ChildProcess/Adapter.php on line 226

I checked vendor/react/filesystem/src/ChildProcess/Adapter.php and the open() function is identical to #56, so something else must be causing this specfic issue.

ext-eio support

I can see the support was dropped in #79. But there is only a claim that the extension is "unreliable" without any specific problem.

What's the reason? The author of ext-eio told me that you never reported any bug there.

Certainly it's better and faster to use such extension than spawning subprocesses for each filesystem operation, right?

Unable to Install this Package

Trying to install this package in a Laravel project with other reactphp packages and there seems to be a problem somewhere.

Tried dev-master branch as well. Any idea where the issue could be?

Problem 1
    - Conclusion: remove evenement/evenement v3.0.1
    - Conclusion: don't install evenement/evenement v3.0.1
    - wyrihaximus/react-child-process-messenger 2.7.1 requires react/child-process ^0.4 -> satisfiable by react/child-process[v0.4.0, v0.4.1, v0.4.2, v0.4.3].
    - wyrihaximus/react-child-process-messenger 2.7.2 requires react/child-process ^0.4 -> satisfiable by react/child-process[v0.4.0, v0.4.1, v0.4.2, v0.4.3].
    - wyrihaximus/react-child-process-messenger 2.7.3 requires react/child-process ^0.4 -> satisfiable by react/child-process[v0.4.0, v0.4.1, v0.4.2, v0.4.3].
    - react/child-process v0.4.3 requires evenement/evenement ^2.0 || ^1.0 -> satisfiable by evenement/evenement[1.0.x-dev, 2.0.x-dev, v1.0.0, v1.1.0, v2.0.0, v2.1.0].
    - wyrihaximus/react-child-process-pool 1.3.0 requires evenement/evenement ^2.0 -> satisfiable by evenement/evenement[2.0.x-dev, v2.0.0, v2.1.0].
    - wyrihaximus/react-child-process-pool 1.4.0 requires evenement/evenement ^2.0 -> satisfiable by evenement/evenement[2.0.x-dev, v2.0.0, v2.1.0].
    - react/child-process v0.4.0 requires evenement/evenement ~2.0 -> satisfiable by evenement/evenement[2.0.x-dev, v2.0.0, v2.1.0].
    - react/child-process v0.4.1 requires evenement/evenement ~2.0 -> satisfiable by evenement/evenement[2.0.x-dev, v2.0.0, v2.1.0].
    - react/child-process v0.4.2 requires evenement/evenement ~2.0 -> satisfiable by evenement/evenement[2.0.x-dev, v2.0.0, v2.1.0].
    - Can only install one of: evenement/evenement[1.0.x-dev, v3.0.1].
    - Can only install one of: evenement/evenement[2.0.x-dev, v3.0.1].
    - Can only install one of: evenement/evenement[v1.0.0, v3.0.1].
    - Can only install one of: evenement/evenement[v1.1.0, v3.0.1].
    - Can only install one of: evenement/evenement[v2.0.0, v3.0.1].
    - Can only install one of: evenement/evenement[v2.1.0, v3.0.1].
    - Installation request for evenement/evenement (locked at v3.0.1) -> satisfiable by evenement/evenement[v3.0.1].
    - Installation request for react/filesystem dev-master -> satisfiable by react/filesystem[dev-master].
    - Conclusion: don't install paragonie/random_compat v9.99.99|install wyrihaximus/react-child-process-pool 1.3.0|install wyrihaximus/react-child-process-pool 1.4.0|install wyrihaximus/react-child-process-messenger 2.7.1|install wyrihaximus/react-child-process-messenger 2.7.2|install wyrihaximus/react-child-process-messenger 2.7.3
    - Conclusion: remove paragonie/random_compat v9.99.99|install wyrihaximus/react-child-process-pool 1.3.0|install wyrihaximus/react-child-process-pool 1.4.0|install wyrihaximus/react-child-process-messenger 2.7.1|install wyrihaximus/react-child-process-messenger 2.7.2|install wyrihaximus/react-child-process-messenger 2.7.3
    - react/filesystem dev-master requires wyrihaximus/react-child-process-pool ^1.3 -> satisfiableby wyrihaximus/react-child-process-pool[1.3.0, 1.4.0, 1.4.1, 1.4.2].
    - wyrihaximus/react-child-process-pool 1.4.2 requires wyrihaximus/react-child-process-messenger^2.7.1 -> satisfiable by wyrihaximus/react-child-process-messenger[2.7.1, 2.7.2, 2.7.3, 2.8.0, 2.8.1, 2.8.2].
    - wyrihaximus/react-child-process-pool 1.4.1 requires wyrihaximus/react-child-process-messenger^2.7.1 -> satisfiable by wyrihaximus/react-child-process-messenger[2.7.1, 2.7.2, 2.7.3, 2.8.0, 2.8.1, 2.8.2].
    - wyrihaximus/react-child-process-messenger 2.8.0 requires paragonie/random_compat ^2.0 -> satisfiable by paragonie/random_compat[v2.0.0, v2.0.1, v2.0.10, v2.0.11, v2.0.12, v2.0.13, v2.0.14, v2.0.15, v2.0.16, v2.0.17, v2.0.2, v2.0.3, v2.0.4, v2.0.5, v2.0.6, v2.0.7, v2.0.8, v2.0.9].
    - wyrihaximus/react-child-process-messenger 2.8.1 requires paragonie/random_compat ^2.0 -> satisfiable by paragonie/random_compat[v2.0.0, v2.0.1, v2.0.10, v2.0.11, v2.0.12, v2.0.13, v2.0.14, v2.0.15, v2.0.16, v2.0.17, v2.0.2, v2.0.3, v2.0.4, v2.0.5, v2.0.6, v2.0.7, v2.0.8, v2.0.9].
    - wyrihaximus/react-child-process-messenger 2.8.2 requires paragonie/random_compat ^2.0 -> satisfiable by paragonie/random_compat[v2.0.0, v2.0.1, v2.0.10, v2.0.11, v2.0.12, v2.0.13, v2.0.14, v2.0.15, v2.0.16, v2.0.17, v2.0.2, v2.0.3, v2.0.4, v2.0.5, v2.0.6, v2.0.7, v2.0.8, v2.0.9].
    - Can only install one of: paragonie/random_compat[v2.0.0, v9.99.99].
    - Can only install one of: paragonie/random_compat[v2.0.1, v9.99.99].
    - Can only install one of: paragonie/random_compat[v2.0.10, v9.99.99].
    - Can only install one of: paragonie/random_compat[v2.0.11, v9.99.99].
    - Can only install one of: paragonie/random_compat[v2.0.12, v9.99.99].
    - Can only install one of: paragonie/random_compat[v2.0.13, v9.99.99].
    - Can only install one of: paragonie/random_compat[v2.0.14, v9.99.99].
    - Can only install one of: paragonie/random_compat[v2.0.15, v9.99.99].
    - Can only install one of: paragonie/random_compat[v2.0.16, v9.99.99].
    - Can only install one of: paragonie/random_compat[v2.0.17, v9.99.99].
    - Can only install one of: paragonie/random_compat[v2.0.2, v9.99.99].
    - Can only install one of: paragonie/random_compat[v2.0.3, v9.99.99].
    - Can only install one of: paragonie/random_compat[v2.0.4, v9.99.99].
    - Can only install one of: paragonie/random_compat[v2.0.5, v9.99.99].
    - Can only install one of: paragonie/random_compat[v2.0.6, v9.99.99].
    - Can only install one of: paragonie/random_compat[v2.0.7, v9.99.99].
    - Can only install one of: paragonie/random_compat[v2.0.8, v9.99.99].
    - Can only install one of: paragonie/random_compat[v2.0.9, v9.99.99].
    - Installation request for paragonie/random_compat (locked at v9.99.99) -> satisfiable by paragonie/random_compat[v9.99.99].

Seek support on read operations

I'm implementing a service using reactphp/filesystem that allows for data transfer supporting resume operations. In order to accomplish this, I need to be able to seek() to a particular offset in the file.

I've found that the Adapter::read method contains a reference to the offset, passed in as the third parameter.

    public function read($fileDescriptor, $length, $offset)
    {
        return $this->fileDescriptors[$fileDescriptor]->rpc(Factory::rpc('read', [
            'length' => $length,
            'offset' => $offset,
        ]))->then(function ($payload) {
            return \React\Promise\resolve(base64_decode($payload['chunk']));
        });
    }

However, this $offset seems to only be used internally by the ReadableStreamTrait class, by keeping a reference to the current readCursor and incrementing this by chunkSize each read operation.

Is there any way to set the reacCursor position manually or do I need to look into using the Adapter / filesystem class directly? Would it be worth adding a new method to the ReadableStreamTrait to set the readCursor directly in order to set the offset?

PHP 8 support

I'm trying to use react/filesystem with PHP 8:

PHP 8.0.0RC3 (cli) (built: Oct 29 2020 21:25:02) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.0-dev, Copyright (c) Zend Technologies

But on composer install I got:

 Problem 1
    - wyrihaximus/react-child-process-pool[1.3.0, ..., 1.4.2] require php ^5.4||^7.0 -> your php version (8.0.0RC3) does not satisfy that requirement.
    - wyrihaximus/react-child-process-pool[1.5.0, ..., 1.6.0] require php ^7.0 || ^5.4 -> your php version (8.0.0RC3) does not satisfy that requirement.
    - react/filesystem v0.1.2 requires wyrihaximus/react-child-process-pool ^1.3 -> satisfiable by wyrihaximus/react-child-process-pool[1.3.0, ..., 1.6.0].
    - Root composer.json requires react/filesystem ^0.1.2 -> satisfiable by react/filesystem[v0.1.2].

It seems that the transitive dependency wyrihaximus/react-child-process-pool can't be used with PHP 8.

Do you have any plan on supporting PHP 8? Thanks.

Idea: ChildProcessAdapter

@WyriHaximus What do you think of creating an adapter (ChildProcessAdapter) that runs a script within the package as a child process using react/child-process to read/write/list files asynchronously?

This way the package would not depend on Eio, also wouldn't it be more stable?

putContents doesn't truncate the file like file_put_contents

React\Filesystem\Node\File::putContents @ line 158 opens without truncating option t. Hence, it writes the length of the content and leaves previous existing bytes.

It kinda goes against the regular behaviour of file_put_contents, is this intended?

$file = 'tmp.txt';
file_put_contents( $file, '000');
$promise = $fs->file( $file )->putContents( '11' );
$res = Block\await($promise, $loop);
var_dump( file_get_contents( $file ));
// returns 110 instead of 11

Missing error handling (e.g. files that do not exist)

I'm trying to read the contents of a file that does not exist, for example like this:

$filesystem->getContents('does-not-exist.txt')->then(
    function($contents) {
        echo $contents
    },
    function($error) {
        echo 'ERROR: ' . $error;
    }
);

Now, since the file does not exist, I would expect the promise to be rejected and thus the second function to be called (and an error message printed). However, nothing happens.

Quickly browsing through the code, I couldn't see any error handling / rejecting of promises at all. Am I missing something? How should I handle errors when reading files?

500 internal server error

I tried a basic test by attempting to use the React/Filesystem to load a file and return it as a stream, but it still returns a 500 internal server error. Right now I am not sure if this is dependency-related. I am currently running this under PHP 8.0.1 alongside discord-php/DiscordPHP.
image
image

$filesystem = \React\Filesystem\Filesystem::create($discord->getLoop()); //Awaiting full PHP 8 support
$rtmp = new Server($discord->getLoop(), function (ServerRequestInterface $request) use ($filesystem) {
	$file = $filesystem->file(__DIR__ . '/media/SpaceEngineers.mp4');
	return $file->exists()
		->then(
			function () use ($file) {
				return $file->open('r', true)
					->then(function ($stream) {
						echo '[TEST]' . __FILE__ . ':' . __LINE__ . PHP_EOL;
						file_put_contents('stream.txt', $stream); //0 bytes
						file_put_contents('stream.mp4', $stream); // 0 bytes
						return new Response(200, ['Content-Type' => 'video/mp4'], $stream);
					});
			},
			function () {
				return new Response(404, ['Content-Type' => 'text/plain'], "This video doesn't exist on server.");
			});
});
$rsocket = new \React\Socket\Server(sprintf('%s:%s', '0.0.0.0', '55554'), $discord->getLoop());
$rtmp->listen($rsocket);

Release composer package?

Just noticed this doesn't have a tagged release yet, so it can't be included in packages marked stable!

Tail example not work

Hi! I check tail example and it is not working for me.

I got:

PHP Warning:  Illegal offset type in /var/www/vendor/react/filesystem/src/ChildProcess/Adapter.php on line 198
PHP Warning:  Illegal offset type in /var/www/vendor/react/filesystem/src/ChildProcess/Adapter.php on line 198
PHP Warning:  Illegal offset type in /var/www/vendor/react/filesystem/src/ChildProcess/Adapter.php on line 198
PHP Warning:  Illegal offset type in /var/www/vendor/react/filesystem/src/ChildProcess/Adapter.php on line 198

After checking Adapter, i got nothing in $this->fileDescriptors[$fileDescriptor] in method read.

Inside loop addPeriodicTimer $adapter has

  #fileDescriptors: []

Undefined constant EIO_O_FSYNC

PHP : 7.2.6
EIO: 2.0.3
the code above produce the following output

<?php

$flagMapping = [
  '+' => EIO_O_RDWR,
  'a' => EIO_O_APPEND,
  'c' => EIO_O_CREAT,
  'e' => EIO_O_EXCL,
  'f' => EIO_O_SYNC,
  'n' => EIO_O_NONBLOCK,
  'r' => EIO_O_RDONLY,
  't' => EIO_O_TRUNC,
  'w' => EIO_O_WRONLY,
];
print_r($flagMapping);
 $ docker exec -it react-cli sh -c 'php ./a.php'                                                                                                            [17:56:51]

Warning: Use of undefined constant EIO_O_SYNC - assumed 'EIO_O_SYNC' (this will throw an Error in a future version of PHP) in /var/www/html/a.php on line 8

Call Stack:
    0.0002     387648   1. {main}() /var/www/html/a.php:0

Array
(
    [+] => 2
    [a] => 1024
    [c] => 64
    [e] => 128
    [f] => EIO_O_SYNC
    [n] => 2048
    [r] => 0
    [t] => 512
    [w] => 1
)

List of defined constants for EIO

<?php

print_r(get_defined_constants(true));
...
    [eio] => Array
        (
            [EIO_SEEK_SET] => 0
            [EIO_SEEK_CUR] => 1
            [EIO_SEEK_END] => 2
            [EIO_PRI_MIN] => -4
            [EIO_PRI_DEFAULT] => 0
            [EIO_PRI_MAX] => 4
            [EIO_READDIR_DENTS] => 1
            [EIO_READDIR_DIRS_FIRST] => 2
            [EIO_READDIR_STAT_ORDER] => 4
            [EIO_READDIR_FOUND_UNKNOWN] => 128
            [EIO_DT_UNKNOWN] => 0
            [EIO_DT_FIFO] => 1
            [EIO_DT_CHR] => 2
            [EIO_DT_MPC] => 3
            [EIO_DT_DIR] => 4
            [EIO_DT_NAM] => 5
            [EIO_DT_BLK] => 6
            [EIO_DT_MPB] => 7
            [EIO_DT_REG] => 8
            [EIO_DT_NWK] => 9
            [EIO_DT_CMP] => 9
            [EIO_DT_LNK] => 10
            [EIO_DT_SOCK] => 12
            [EIO_DT_DOOR] => 13
            [EIO_DT_WHT] => 14
            [EIO_DT_MAX] => 15
            [EIO_O_RDONLY] => 0
            [EIO_O_WRONLY] => 1
            [EIO_O_RDWR] => 2
            [EIO_O_NONBLOCK] => 2048
            [EIO_O_APPEND] => 1024
            [EIO_O_CREAT] => 64
            [EIO_O_TRUNC] => 512
            [EIO_O_EXCL] => 128
            [EIO_S_IRUSR] => 256
            [EIO_S_IWUSR] => 128
            [EIO_S_IXUSR] => 64
            [EIO_S_IRGRP] => 32
            [EIO_S_IWGRP] => 16
            [EIO_S_IXGRP] => 8
            [EIO_S_IROTH] => 4
            [EIO_S_IWOTH] => 2
            [EIO_S_IXOTH] => 1
            [EIO_S_IFREG] => 32768
            [EIO_S_IFCHR] => 8192
            [EIO_S_IFBLK] => 24576
            [EIO_S_IFIFO] => 4096
            [EIO_S_IFSOCK] => 49152
            [EIO_SYNC_FILE_RANGE_WAIT_BEFORE] => 1
            [EIO_SYNC_FILE_RANGE_WRITE] => 2
            [EIO_SYNC_FILE_RANGE_WAIT_AFTER] => 4
            [EIO_FALLOC_FL_KEEP_SIZE] => 1
        )
...

What kind of version EIO must be used for this library?

UPD.

https://pecl.php.net/package-changelog.php?package=eio&release=2.0.3


2.0.2 | Fixed build error due to undefined O_FSYNC in musl libc

0.2.x: error saving binary data.

I'm having some issues saving binary data with the child process adapter in the 0.2.x branch.

Upon calling json_encode to pipe the contents of the file from the parent process to the child process the following error occurs:

Malformed UTF-8 characters, possibly incorrectly encoded

Would it be an idea to encode the contents of the file to Base64 first and decode it in the child process?

Something like this:

\React\Filesystem\ChildProcess\File::putContents

$contents = base64_encode($contents);
return childProcessPromiseClosure(Loop::get(), function () use ($path, $contents, $flags): array {
    return ['size_written' => file_put_contents($path, base64_decode($contents), $flags)];
})->then(static fn (array $data) => (int)$data['size_written']);

Async polling slower then sync polling

I am experimenting with reading the content of a bunch of files async. While doing some tests I notice that reading the files sync is a lot faster (+10 times) then doing this async with this library (using ext-eio)

Experiment:

I am monitoring (polling) 32 different sysfs files used for digital inputs (kinda like the raspberry pi). If I read them with file_get_content it takes about 2-4 milliseconds in total to read them, one by one, sync. If I use $filesystem->file($file)->getContents() and use \React\Promise\all() on all the promises, it takes something between 35-120 milliseconds. I would expect that reading them async would be faster, when reading multiple files.

Could somebody explain me why this is so slow?

Fatal exception within EIO Adapter eio_poll handler

Within the Adapter.php closure defined in function executeDelayedCall

function ($data, $result, $req) use ($deferred, $errorResultCode, $function, $args) {
            if ($result == $errorResultCode) {
-->                $exception = new UnexpectedValueException(@eio_get_last_error($req));
                $exception->setArgs($args);
                $deferred->reject($exception);
                return;
            }

I get the following fatal exception on occasion.

Line: 401
Message: Class 'React\Filesystem\Eio\UnexpectedValueException' not found
Trace:
#0 [internal function]: React\Filesystem\Eio\Adapter->React\Filesystem\Eio\{closure}(NULL, -1, Resource id #42794)
#1 /var/www/html/vendor/react/filesystem/src/Eio/Adapter.php(448): eio_poll()
#2 /var/www/html/vendor/react/event-loop/src/ExtEvLoop.php(95): React\Filesystem\Eio\Adapter->handleEvent(Resource id #83)
#3 [internal function]: React\EventLoop\ExtEvLoop->React\EventLoop\{closure}()
#4 /var/www/html/vendor/react/event-loop/src/ExtEvLoop.php(207): EvLoop->run(2)
#5 /var/www/html/event_engine/import_engine.php(143): React\EventLoop\ExtEvLoop->run()
#6 {main}

I do not have a way of reproducing this expect running the script for a long time.

Error when copying file to file

I've tried to run this example with copying one file to another. It fails with:

Notice: Undefined offset: 1 in vendor/react/filesystem/src/ChildProcess/Adapter.php on line 225

I thinks this happens because we try to close() destination file twice. The first attempt happens here, when are done with reading:

$readStream->on('end', function () use ($deferred, $writeStream, &$writePromises) {
\React\Promise\all($writePromises)->then(function ()use ($deferred, $writeStream) {
$writeStream->end();
$deferred->resolve();
});
});

We call end() which implicitly closes the file.

And then in always() handler:

})->always(function () use ($node) {
$node->close();
});

We again try to close the same file and it fails. Should this always handler be removed or there is another solution?

racing condition while writing to file

    $this->file->open('a' )->then(
        function(\React\Stream\WritableStreamInterface $stream) use ($msg) {
            $stream->end("{$msg}\n");
        },
        function( $e ) use ($msg) {
            echo "error in log: {$e->getMessage()}\n";
            if ($e->getPrevious()) {
                echo "\t".$e->getPrevious()->getMessage() . PHP_EOL;
            }
            echo ".. while writing msg: {$msg}\n";
        }
    );

working as expected, adding line after line. Except in case, when many objects use the same code, to write to same file at the same time.
Errors shown are "timeouts after 15 sec" or "file already open".
I implemented singleton locking, but with no effect, due to async working of ReactPHP.

Possible solution would be locking at file->open() (per file) or adding some flags to this call.
Maybe even file->lock() / unlock() / isLocked() implementation.
Or file->isOpen(), to wait, until it closed by other async thread.

If my understanding is wrong, please, correct me, how to avoid racing conditions, as I need frequent open+write+close cycles for my use.

OSX Compatibility

On PHP 5.5.21 on OSX, this is what sometimes happens when I run (it doesn't always) https://github.com/reactphp/filesystem/blob/master/examples/directory_ls_recursive.php

Fatal error: Cannot use object of type React\Filesystem\Eio\RuntimeException as array in ... vendor/react/filesystem/src/Node/Directory.php on line 73

This is the exception:

class React\Filesystem\Eio\RuntimeException#1039 (8) {
  protected $message =>
  string(35) "Unknown error calling "eio_readdir""
...

If I check to see if $result is an array on https://github.com/reactphp/filesystem/blob/master/src/Node/Directory.php#L73, it works, but I'm guessing that it's missing some files or directories when that exception is thrown.

Create ext-uv adapter

With ext-uv event loop merged into react/event-loop (via reactphp/event-loop#112) this opens the door to an ext-uv filesystem adapter. I've already started working on it and will open a PR as soon as I have something to share.

Unable to extend React\Filesystem\ChildProcess\Proces

I need to implement @flock() on file but I couldn't find the way to do it.

I already try to extend React\Filesystem\ChildProcess\Adapter and React\Filesystem\ChildProcess\Proces to owerride React\Filesystem\ChildProcess\Process::open() but I get error:

Call to undefined method React\Filesystem\ChildProcess\Process::open()

Class React\Filesystem\ChildProcess\Proces is called even if I extend this class.

My Adapter class look like this:

class Adapter extends  React\Filesystem\ChildProcess\Adapter
{
    const CHILD_CLASS_NAME = '\MyNamespace\ChildProcess\Process';
}

and I extend ``Process` class with:

public function open(array $payload)
{
    $this->fd = @fopen($payload['path'], $payload['flags']);
    // here I could set fopen()
    return \React\Promise\resolve([
        'result' => (string)$this->fd,
    ]);
}

I'm not sure if this is an actual problem or if I missed something

Filesystem `exists()` file method stopped working with last child-process versions

Having this example

https://gist.github.com/mmoreram/6323b9bf536ba5346e5a26117512c208

Have different results when changing the wyrihaximus/react-child-process-pool dependency:

  • Version 1.6.* work properly in PHP7, composed doesn't update in PHP8
  • Version 1.7.* doesn't work in PHP7 and PHP8 due to compatibility class issues (we already know that issue),
  • Version 1.8.* doesn't work in PHP7 nor in PHP8. The exists() method keeps waiting until the infinite in both PHP versions.

I don't know if some other methods are affected by this update.

PHP-FPM compatibility

Hi,

I'm stacked at situation where I can't use this beautiful library.

I have PHP 7.0.32 with php-fpm enabled.
Here is additional information about extensions directly from phpinfo:

//
PHP libuv Extension
libuv Support enabled
Version 0.2.2
libuv Version 1.26

//
eio
eio support enabled
Debug support disabled
Version 2.0.4

//
event
Event support enabled
Sockets support enabled
Debug support disabled
Extra functionality support including HTTP, DNS, and RPC enabled
OpenSSL support enabled
Thread safety support disabled
Extension version 2.4.2
libevent2 headers version 2.0.19-stable

//
libevent
libevent support enabled
extension version 0.2.0-dev
Revision $Revision$
libevent version 2.1.8-stable

Here is the code I'm using:

<?php

require __DIR__ . '/vendor/autoload.php';

$loop = \React\EventLoop\Factory::create();

// I tried various loop implementations, but all next produce 'Timed out after 15 seconds' error message
//
//$loop = new \React\EventLoop\ExtUvLoop();
//$loop = new \React\EventLoop\StreamSelectLoop();
//$loop = new \React\EventLoop\ExtEventLoop();

// This loop implementations doesn't work at all
//
//$loop = new \React\EventLoop\ExtEvLoop();// Class 'EvLoop' not found
//$loop = new \React\EventLoop\ExtLibevLoop();// Fatal error: Uncaught BadMethodCallException: Cannot create ExtLibevLoop, ext-libev extension missing
//$loop = new \React\EventLoop\ExtLibeventLoop();// 502

// With default adapter it hangs forever
//
//$filesystem = \React\Filesystem\Filesystem::create($loop);

// With this adapter it produce 'Timed out after 15 seconds' error message
$adapter = new \React\Filesystem\ChildProcess\Adapter($loop);
$filesystem = \React\Filesystem\Filesystem::createFromAdapter($adapter);

echo 'Using ', get_class($filesystem->getAdapter()), '<br/>';

$filename = __DIR__ . '/test_putcontents.txt';

$contents = 'contents';

$filesystem->file($filename)
->putContents($contents)
->then(
	function () use ($filename)
	{
		echo "filename {$filename} written<br/>";
	},
	function (Exception $e)
	{
		echo $e->getMessage() . '<br/>';
		echo $e->getTraceAsString() . '<br/>';
	}
)
->done(
	function($someValue)
	{
		$error_or_not = "error_or_not resolved with someValue: {$someValue}<br/>";
		
		echo $error_or_not."<br/>";
	},
	function($someReason) use ($filename)
	{
		$error_or_not = "error_or_not rejected with someReason: {$someReason}<br/>";
		
		echo $error_or_not."<br/>";
	}
);

$loop->run();

?>

Here are my results with various loop implementations

Using React\Filesystem\ChildProcess\Adapter
Timed out after 15 seconds
#0 /var/www/user/data/www/vendor/react/event-loop/src/ExtUvLoop.php(119): React\Promise\Timer\{closure}(Object(React\EventLoop\Timer\Timer)) #1 [internal function]: React\EventLoop\ExtUvLoop->React\EventLoop\{closure}(Object(UVTimer)) #2 /var/www/user/data/www/vendor/react/event-loop/src/ExtUvLoop.php(230): uv_run(Object(UVLoop), 1) #3 /var/www/user/data/www/test_write_file_new.php(88): React\EventLoop\ExtUvLoop->run() #4 {main}
error_or_not resolved with someValue:
Using React\Filesystem\ChildProcess\Adapter
Timed out after 15 seconds
#0 /var/www/user/data/www/vendor/react/event-loop/src/Timer/Timers.php(96): React\Promise\Timer\{closure}(Object(React\EventLoop\Timer\Timer)) #1 /var/www/user/data/www/vendor/react/event-loop/src/StreamSelectLoop.php(184): React\EventLoop\Timer\Timers->tick() #2 /var/www/user/data/www/test_write_file_new.php(88): React\EventLoop\StreamSelectLoop->run() #3 {main}
error_or_not resolved with someValue:
Using React\Filesystem\ChildProcess\Adapter
Timed out after 15 seconds
#0 /var/www/user/data/www/vendor/react/event-loop/src/ExtEventLoop.php(243): React\Promise\Timer\{closure}(Object(React\EventLoop\Timer\Timer)) #1 [internal function]: React\EventLoop\ExtEventLoop->React\EventLoop\{closure}(-1, 1, Object(React\EventLoop\Timer\Timer)) #2 /var/www/user/data/www/vendor/react/event-loop/src/ExtEventLoop.php(204): EventBase->loop(1) #3 /var/www/user/data/www/test_write_file_new.php(92): React\EventLoop\ExtEventLoop->run() #4 {main}
error_or_not resolved with someValue:

I'm using next versions of libraries:

  • react/event-loop v1.1.0 a0ecac955c67b57c40fe4a1b88a7cca1b58c982d
  • react/filesystem v0.1.2 766cdef

Do you need any additional information?

Putting all adapters in their own repositories

One of the things I have been thinking about for v0.2 is pulling all adapters out of this repository and putting them child process one under reactphp and others either under reactphp and/or friends-of-reactphp.

Pros:

  • Each adapter can set it's own required extensions needed for it to function
  • Stimulates a ecosystem of adapters by leading the way
  • Each adapter can be developed/maintained at it's own pace and has it's own releases without blocking this repository
  • Users can require only what they need for their environment

Cons:

  • Each adapter can set it's own required extensions needed for it to function
  • Users might not know what they need for the best performance for their environment and when not including/requiring all adapters they might miss out on that better performance.

What are your opinions about this @clue, @jsor, and @cboden?

Dependency Versions

Hello

For my asynchronous project, I want to utilize reactphp/filesystem to asynchronously interface with the filesystem. But I'm having troubles installing it, due to the package locking itself to old versions of its dependencies, thus being uninstallable. According to the roadmap, there were already new releases planned, but I assume they weren't do-able.

I'm stuck with evenement being installed as v3.0, but reactphp/filesystem requires v2.x. evenement is downgradable, but there's another package locking, which is reactphp/stream. This package requires it to be v0.4.x, but reactphp/socket requires at least v0.7 (or v1.0), thus conflicts not being resolvable.

Is there any way you guys can release a new version with the dependencies updated?

Best Regards
Charlotte

Reliability issues when writing multiple files at the same time

Hi, we've been working on an export, which should export 5 files (relatively at the same time).

However we've been experiencing some reliability issues, sometimes a file is being fully written, sometimes not and sometimes the export just gets stuck.
We're running every test with the same data, but we get different results every time. This issue is especially noticable for OSX, but we're now experiencing the same issue with Linux.

The way we have written it in the code is like this:

public function export(FilesystemInterface $filesystem, File $file): PromiseInterface
{
    return new Promise(function (callable $resolve) use ($filesystem, $file) {
        $fullPath = $this->fullPath($file);
        $filesystem->file($fullPath)->open('cwt')->then(function ($stream) use ($resolve, $file) {
            // This part is simplified, just to show an example.
            foreach ($file->lines() as $line) {
                $stream->write($this->format($line));
            }
            $stream->end();
            $resolve();
        });
    });
}

This method gets called 5 times, we collect all the promises and then we start the export with \Clue\React\Block\awaitAll($promises, $loop);.

Is it possible to write multiple files at the same time? Are we doing something wrong here?

Update: We've temporarily modified the export to only export one file, but even this seems to not work. Even on Linux we're experiencing more misfires now, the files are just empty.

What should be the `getContents()` behavior when a file doesn't exist?

Right now, when a file is not found and we access to its content, the method just keeps waiting. Instead of that, we can make an exists call before it.

Is it a good behavior to let a method keep waiting until the infinite? I understand that this action is not blocking at all, but what is the point?

Move examples to a new markdown file or to `README.md`

The example code raise some "bad practice warnings" (which is understandable as the purpose of then is simply to illustrate the context of use). It would be nice to have an examples.md file that would explain and contain each of the examples.

See insight analysis:
https://insight.sensiolabs.com/projects/ce37859a-e3a3-42b5-8d97-455465dc5c6f/analyses/2

By doing this, we will be able to focus in fix/solve the more complicated issues raised by the Insight.

edit: I can send a PR on this if you wish (:

ext-eio readlink not (always?) returning

I've noticed that ls does not list (all?) my symlinks in a certain dir when using eio adapter.

It seems to be due to eio_readlink in the cases of these files returning only the pointed file as a result (instead of a full path), as the files are relatively linked

Error while running tail example

While running the example for tailing the file.

Notice: Undefined offset: 0 in /Users/Extras/project/vendor/react/filesystem/src/ChildProcess/Adapter.php on line 198

Call Stack:
    0.0007     405784   1. {main}() /Users/Extras/project/index.php:0
    0.0181    2787608   2. React\EventLoop\StreamSelectLoop->run() /Users/Extras/project/index.php:40
   26.2127    3339672   3. React\EventLoop\StreamSelectLoop->waitForStreamActivity() /Users/Extras/project/vendor/react/event-loop/src/StreamSelectLoop.php:212
   26.2131    3340152   4. React\Stream\DuplexResourceStream->handleData() /Users/Extras/project/vendor/react/event-loop/src/StreamSelectLoop.php:245
   26.2131    3410184   5. React\Stream\DuplexResourceStream->emit() /Users/Extras/project/vendor/react/stream/src/DuplexResourceStream.php:193
   26.2131    3410184   6. React\Stream\Util::React\Stream\{closure:/Users/Extras/project/vendor/react/stream/src/Util.php:70-72}() /Users/Extras/project/vendor/evenement/evenement/src/Evenement/EventEmitterTrait.php:123
   26.2131    3410560   7. React\Socket\Connection->emit() /Users/Extras/project/vendor/react/stream/src/Util.php:71
   26.2132    3410560   8. WyriHaximus\React\ChildProcess\Messenger\Messenger->WyriHaximus\React\ChildProcess\Messenger\{closure:/Users/Extras/project/vendor/wyrihaximus/react-child-process-messenger/src/Messenger.php:67-71}() /Users/Extras/project/vendor/evenement/evenement/src/Evenement/EventEmitterTrait.php:123
   26.2132    3410528   9. WyriHaximus\React\ChildProcess\Messenger\Messenger->handleData() /Users/Extras/project/vendor/wyrihaximus/react-child-process-messenger/src/Messenger.php:70
   26.2132    3411280  10. WyriHaximus\React\ChildProcess\Messenger\Messenger->iterateMessages() /Users/Extras/project/vendor/wyrihaximus/react-child-process-messenger/src/Messenger.php:216
   26.2132    3412584  11. WyriHaximus\React\ChildProcess\Messenger\Messages\RpcSuccess->handle() /Users/Extras/project/vendor/wyrihaximus/react-child-process-messenger/src/Messenger.php:223
   26.2132    3412904  12. WyriHaximus\React\ChildProcess\Messenger\Messenger->WyriHaximus\React\ChildProcess\Messenger\Messages\{closure:/Users/Extras/project/vendor/wyrihaximus/react-child-process-messenger/src/Messages/RpcSuccess.php:53-55}() /Users/Extras/project/vendor/wyrihaximus/react-child-process-messenger/src/Messages/RpcSuccess.php:57

I get this error pretty frequently when running multiple processes without await. I was not able to reproduce this error. But the tail example in this repo reproduces this error. I tried the same thing with PHP7.3 and PHP7.4. The error is the same.
In this particular case.

https://github.com/reactphp/filesystem/blob/master/examples/tail.php#L30
the error is thrown the file actually changes.

Please, let me know if I could help.

Release for new changes

I am using this in a library I am writing. There are few changes in master I see working that have not been released. What's the ETA on releasing these changes.

Version v0.2 doesn't exist in Packagist

The README refers to installing ^0.2 but I didn't see that in Packagist and got an error when trying to install it.

But it looks like this was just rewritten 4 days ago! what a coincidence as I'm trying to use it for the first time in a project.

That said, I have a question. Is this a valid alternative to using this project which is still experimental? Sample code follows below:

$path = '/foo/bar/file.css';
if (is_readable($path)) {
    $mimeType = $this->getMimeType($path);
    $fileStream = new ReadableResourceStream(fopen($path, 'rb'));
    $bodyStream = new ReadableBodyStream($fileStream, filesize($path));
    $headers = [
        'Content-Type' => $mimeType,
    ];
    return new \React\Http\Message\Response(200, $headers, $bodyStream);
}

I know already this example violates some of the async principles, for example these are all blocking: is_readable, fopen, filesize but this is only for a dev-convenience function not for production use. I have confirmed this works thus far, but wanted to see if this reactphp/filesystem project could be used as a more proper implementation. Thanks!

Not opening/reading all files

Description

Trying to read 10 files from disk usually ends up skipping some of them randomly with error

Unknown error calling: "eio_open"

Takes for ever to load with the ChildProcess adapter.
strlen() also shows different bytes each time (might be different issue)

OS/PHP versions

  • Ubuntu Linux 19.04/Kernel 5.0.0-29-generic
  • PHP 7.3.9-1+ubuntu19.04.1+deb.sury.org+1 (cli) (built: Sep 2 2019 12:54:43)
  • ext-eio 2.0.4

Sample script

https://gist.github.com/petsoukos/2cc5f7cc3181efbaab12d43fbe325644

Create some random files with sizes over 3MB up to 150MB and store em in a "downloads" folder or adjust the script to point to your files.

Sample output

$ php Processor.php 
Bytes loaded for file file10.xml: 27164772
Bytes loaded for file file9.xml: 27159323
Bytes loaded for file file8.xml: 175390820
Bytes loaded for file file7.xml: 27099273
Bytes loaded for file file6.xml: 27145682
Bytes loaded for file file5.xml: 27080067
Bytes loaded for file file4.xml: 306454628
Opening file3.xml produced some error: Unknown error calling "eio_open"
Bytes loaded for file file2.xml: 227803236
Bytes loaded for file file1.xml: 27085574
$

$ php Processor.php 
Bytes loaded for file file10.xml: 30176743
Bytes loaded for file file9.xml: 30171294
Bytes loaded for file file8.xml: 178394599
Bytes loaded for file file7.xml: 30111244
Bytes loaded for file file6.xml: 30157653
Bytes loaded for file file5.xml: 30097545
Bytes loaded for file file4.xml: 309466599
Bytes loaded for file file3.xml: 30083846
Bytes loaded for file file2.xml: 230831591
Bytes loaded for file file1.xml: 30070147
$

$ php Processor.php 
Bytes loaded for file file10.xml: 27164772
Bytes loaded for file file9.xml: 27159323
Bytes loaded for file file8.xml: 175374436
Opening file7.xml produced some error: Unknown error calling "eio_open"
Bytes loaded for file file6.xml: 27145682
Bytes loaded for file file5.xml: 27091081
Bytes loaded for file file4.xml: 306454628
Bytes loaded for file file3.xml: 27077382
Bytes loaded for file file2.xml: 227795044
Bytes loaded for file file1.xml: 27063683
$

Missing append to file

Trying write content to existing file, flags 'a' and 'w' so similar, and any write clear previously saved data:

$file = $filesystem->file($tsv_filename);
$file->open('ca')->then(function (React\Stream\WritableStreamInterface $stream) use ($tsv_data) {
$stream->write(implode("\t", $tsv_data) . "\n");
$stream->end();
echo "Data was written\n";
});

Apologize no file append functionality in reactphp/filesystem, please add it, thx.

Delay when using Filesystem compared to ReadableResourceStream directly

Greetings πŸ‘‹,

I'm fairly new to ReactPHP, please forgive me if this is something obvious and my Google/Stack Overflow search skills have just failed me πŸ™ˆ.

"react/filesystem": "^0.1.2" is the only dependency in my composer.json, and I'm using PHP 7.4.8 installed with Homebrew on MacOS Big Sur (I hope that's not the reason πŸ˜…), with the StreamSelectLoop (no event extensions are installed).

The following code hopefully makes it reproducible:

// test.php
use React\EventLoop\Factory;
use React\Filesystem\Filesystem;
use React\Stream\ReadableResourceStream;

$loop = Factory::create();

$filePath = 'test.txt';

$file = new ReadableResourceStream(fopen($filePath, 'r'), $loop);
$fs = Filesystem::create($loop);

When using the ReadableResourceStream, the text is printed and the script terminates immediately:

$file->on('data', function ($contents) {
    echo $contents;
});

$loop->run();
❯ time php test.php
test
php test.php  0,04s user 0,03s system 94% cpu 0,070 total

When using the Filesystem, the text is printed immediately, but it takes another three to four seconds until the script finally terminates:

$fs->getContents($filePath)
    ->then(function ($contents) {
        echo $contents;
    });

$loop->run();
❯ time php test.php
test
php test.php  0,15s user 0,11s system 6% cpu 4,083 total

I'm not sure if this is an actual problem or if I missed something in the docs - either way I'd be happy if you could give me a hint on what might be going on here. (I also noticed that the system time is quite different between the two methods)

:octocat:

Not whole file is read if use the eio adapter

Steps to reproduce behavior

1. create file

php -r 'foreach(range(0, 1000000) as $i) { print $i . PHP_EOL; }' > static/test.txt

2. create script

<?php

use \React\Promise\Deferred;

$loader = require __DIR__ . '/vendor/autoload.php';

#$loop = React\EventLoop\Factory::create();
$loop = new React\EventLoop\ExtEvLoop();

$filesystem = \React\Filesystem\Filesystem::create($loop);
    $file = $filesystem->file('static/test.txt');
    $file->exists()
        ->then(function () use ($file) {
            return $file->open('r');
        })
        ->then(function ($stream) use ($loop) {
            $d = new Deferred();
            $stream->on('data', function ($data) {
                print $data;
            });
            $stream->on('end', function ($data) use ($stream, $d) {
                $stream->close();
                $d->resolve('finish');
            });

            return $d->promise();
        })
        ->then(function () use ($loop) {
            $loop->stop();
        })
        ->otherwise(function ($e) {
            var_dump($e);
        });
$loop->run();

3. run

php7.3 3.php
0
1
2
3
...
375148
375149
3751root@7cf1e7fada2c:/app/adv# 

if you change the adapter to child process then everything works well

PHP 7.3.27 compatibility

I'm using 2 server providers, AWS and an local provider.
I'm developing and testing on AWS, where installed PHP is 7.4.13.
I put an copy of the application on my local provider, where installed PHP is 7.3.27.
On my local provider I has no terminal access, so I have to transfer the entire folder, with vendor folder.
Before transferring the files, on my AWS installation I have included "config": { "platform": { "php": "7.3" } } in composer.json file and executed composer update, composer install and composer dump.
To make sure it was still working, I executed the application without problems.
After that, I transfered the entire folder from AWS to my local provider.
When execute it, bet get the following error:
PHP Parse error: syntax error, unexpected 'FilesystemInterface' (T_STRING), expecting function (T_FUNCTION) or const (T_CONST) in /home/public_html/zhukBook/src/Core/Uploader.php on line 15.
With the editor the line private FilesystemInterface $filesystem; is checked with an PHP syntax error.
Is there any version incompatibility?

Support for other types of filesystems

It would be really awesome if we can use the library against things like S3, ceph or some other type of file system.

I noticed that flysystem will not be supporting async (thephpleague/flysystem#198), so I think the idea of having built in adapters for filesystems other than EIO would be nice.

Remove call invokers

Initially these call invokers where added to keep ext-eio under control. And they made sense in the design for that adapter. But with uv adapter coming up this feels less and less like it makes sense due to the increased overhead caused by it.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.