Git Product home page Git Product logo

file's People

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

Watchers

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

file's Issues

ftruncate analogue

Hi.
Is there any plans to add ftruncate() analogue or any workaround?
Now I'm using something like that

yield \Amp\ParallelFunctions\parallel(function () use ($filename) {
    $fh = fopen($filename, 'c');
    ftruncate($fh, 1024);
    fclose($fh);
})();

but I think it's terrible solution

Possible inconsistency with EioDriver::unlink() and other functions

From reading the code today, I feel like they might be some inconsistencies in error handling between the drivers. For some operations some drivers can only return true or throw an exception while others might possibly return false but I'm not sure because I'm not familiar with eio and uv at all.

Most notably it seems that EioDriver::unlink() either returns true or throws an exception. Other drivers seem to can return false in some cases - possibly when file doesn't exist or there are insufficient permissions? If I'm correct about EioDriver being broken here then this would break FileCache::delete() as well.

Overall I think there should be more test cases for failures like these to ensure consistency between the drivers. For instance DriverTest has no test for calling unlink on a non-existent or insufficient-permissions file to ensure consistent result. Same goes for other functions most likely.

EIO createDirectoryRecursively() errors if it exists

When I'm using the EIO driver, calling yield filesystem()->createDirectoryRecursively("/tmp"); errors out, while the BlockingDriver returns new Success(). It would be nice if they behave identical, so we don't have to wrap our calls in exists-checks.

On a related note, it took me very long to find this error, because the EIO error-messages seem to get mixed up. The actual error I got was 'No such file or directory', but when trying to reproduce the problem, I got the correct 'File exists' error. I will try to find a minimum example to reproduce this.

Revolt event loop hangs with file operations inside defer()

Not sure, if it's related to #75 , but the script below is just hanging indefinitely (writing succeeds):

\Revolt\EventLoop::defer(function () {
    \Amp\File\write('/code/out', 'contents');
});

\Revolt\EventLoop::run();

The same version without defer() works fine:

\Amp\File\write('/code/out', 'contents');

\Revolt\EventLoop::run();

Check stream behavior

Currently closed streams throw on another read(), I think they should return null like TCP streams.

Fatal error v3.0.0-beta.6 Declaration must be compatible Amp\Parallel\Worker\Task

Amp\File\write('test.txt', 'test');
PHP Fatal error:  Declaration of Amp\File\Internal\FileTask::run(Amp\Sync\Channel $channel, Amp\Cache\Cache $cache, Amp\Cancellation $cancellation): mixed must be compatible with Amp\Parallel\Worker\Task::run(Am
p\Sync\Channel $channel, Amp\Cancellation $cancellation): mixed in ...\vendor\amphp\file\src\Internal\FileTask.php on line 53

UvDriver cannot scan empty dir

For this code:

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

use Amp\File;
use Amp\Loop;
use App\App;

Loop::run(function () {
    $flist = yield File\scandir("/tmp/tmp/");
    var_dump($flist);
});

/tmp/tmp is empty dir


Run php72 -dmemory_limit=1024m /path/to/php.php, it throw a excepiton:

PHP Fatal error:  Uncaught Amp\File\FilesystemException: Failed reading contents from /tmp/tmp/ in /opt/pkgist/vendor/amphp/file/lib/UvDriver.php:420
Stack trace:
#0 [internal function]: Amp\File\UvDriver->Amp\File\{closure}(NULL, 0)
#1 /opt/pkgist/vendor/amphp/amp/lib/Loop/UvDriver.php(174): uv_run(Object(UVLoop), 1)
#2 /opt/pkgist/vendor/amphp/amp/lib/Loop/Driver.php(130): Amp\Loop\UvDriver->dispatch(true)
#3 /opt/pkgist/vendor/amphp/amp/lib/Loop/Driver.php(70): Amp\Loop\Driver->tick()
#4 /opt/pkgist/vendor/amphp/amp/lib/Loop.php(76): Amp\Loop\Driver->run()
#5 /opt/pkgist/bin/gc2(11): Amp\Loop::run(Object(Closure))
#6 {main}
  thrown in /opt/pkgist/vendor/amphp/file/lib/UvDriver.php on line 420

But run env AMP_LOOP_DRIVER='\Amp\Loop\EvDriver' php72 -dmemory_limit=1024m /path/to/php.php, it works normally:

array(0) {
}

UvDriver bug in amphp/file 1.0.1

[TypeError]                                                                  
Argument 2 passed to Amp\File\StatCache::set() must be of the type array, bool given, called in .../vendor/amphp/file/src/UvDriver.php on line 157 

file\put() default mode

If a file does not yet exist, we have to set a default file permissions mode.

Currently it's a mess:

  • NativeDriver sets 0666 [note this is hardcoded, if we decide to not use 0666 by default, we'll need an extra chmod() call then and checking whether the file existed beforehand]
  • EioDriver sets 0644
  • UvDriver sets 0700

So: what should be the default?

Also, I think we should add a third optional parameter to put() to allow overriding that default.

\cc @trowski @DaveRandom @kelunik

UV: Call to a member function onResolve() on array

Error: Call to a member function onResolve() on array in /home/kelunik/GitHub/composer/mirror-fiber/vendor/amphp/file/src/Driver/UvDriver.php:413
Stack trace:
#0 /home/kelunik/GitHub/composer/mirror-fiber/vendor/amphp/file/src/Driver/UvDriver.php(232): Amp\File\Driver\UvDriver->isDir('/')
#1 /home/kelunik/GitHub/composer/mirror-fiber/vendor/amphp/file/src/Driver/UvDriver.php(246): Amp\File\Driver\UvDriver->Amp\File\Driver\{closure}()
#2 /home/kelunik/GitHub/composer/mirror-fiber/vendor/amphp/file/src/Driver/StatusCachingDriver.php(109): Amp\File\Driver\UvDriver->createDirectoryRecursively('/home/kelunik/G...', 511)

Possible race conditions in UvDriver

UvDriver uses a dummy watcher to keep the loop active. These are unreferenced on operation completions. Unfortunately, this seems to create a race condition, because for two concurrent operations, the faster one will just unreference once complete while there's still another operation going on. I think there should be a counter of currently active operations to solve this.

touch in eio driver don't create files

touch() in in Eio driver don't create file if it is absent.

I ve added php \touch() to check, that file can be created.

Im using php8.2.5 with ev and eio-3.0.0RC4

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


\touch('some_file_sync.txt');
\Amp\File\touch('some_file_async.txt');
\Revolt\EventLoop::run();
Fatal error: Uncaught Amp\File\FilesystemException: No such file or directory in /app-host-link/vendor/amphp/file/src/Driver/EioFilesystemDriver.php:426
Stack trace:
#0 [internal function]: Amp\File\Driver\EioFilesystemDriver->onGenericResult(Object(Amp\DeferredFuture), -1, Resource id #71)
#1 /app-host-link/vendor/amphp/file/src/Internal/EioPoll.php(28): eio_poll()
#2 /app-host-link/vendor/revolt/event-loop/src/EventLoop/Internal/AbstractDriver.php(569): Amp\File\Internal\EioPoll::Amp\File\Internal\{closure}('a', Resource id #54)
#3 [internal function]: Revolt\EventLoop\Internal\AbstractDriver->Revolt\EventLoop\Internal\{closure}()
#4 /app-host-link/vendor/revolt/event-loop/src/EventLoop/Internal/AbstractDriver.php(479): Fiber->start()
#5 /app-host-link/vendor/revolt/event-loop/src/EventLoop/Internal/AbstractDriver.php(533): Revolt\EventLoop\Internal\AbstractDriver->invokeCallbacks()
#6 [internal function]: Revolt\EventLoop\Internal\AbstractDriver->Revolt\EventLoop\Internal\{closure}()
#7 /app-host-link/vendor/revolt/event-loop/src/EventLoop/Internal/AbstractDriver.php(86): Fiber->start()
#8 /app-host-link/vendor/revolt/event-loop/src/EventLoop/Internal/DriverSuspension.php(97): Revolt\EventLoop\Internal\AbstractDriver->Revolt\EventLoop\Internal\{closure}()
#9 /app-host-link/vendor/amphp/amp/src/Future.php(251): Revolt\EventLoop\Internal\DriverSuspension->suspend()
#10 /app-host-link/vendor/amphp/file/src/Driver/EioFilesystemDriver.php(323): Amp\Future->await()
#11 /app-host-link/vendor/amphp/file/src/Driver/StatusCachingFilesystemDriver.php(144): Amp\File\Driver\EioFilesystemDriver->touch('/app-host-link/...', 1682506529, 1682506529)
#12 /app-host-link/vendor/amphp/file/src/Filesystem.php(308): Amp\File\Driver\StatusCachingFilesystemDriver->touch('/app-host-link/...', NULL, NULL)
#13 /app-host-link/vendor/amphp/file/src/functions.php(295): Amp\File\Filesystem->touch('/app-host-link/...', NULL, NULL)
#14 /app-host-link/test.php(6): Amp\File\touch('/app-host-link/...')
#15 {main}
  thrown in /app-host-link/vendor/amphp/file/src/Driver/EioFilesystemDriver.php on line 426

Process finished with exit code 255

Worker not found in openFile

Hi, I think I'm having an issue with openFile.

First of all here's a reproduction: https://github.com/tncrazvan/amphp-file-parallel-driver-issue-reproduction

The program is a web server and it's serving a web application to the client.

However when sending many requests in a row and canceling them (you can reproduce this by refreshing the browser very fast) I get this error in the console:

PHP Fatal error:  Uncaught UnexpectedValueException: Object not found in /home/raz/GitHub/tncrazvan/amphp-file-reproduction-SplObjectStorage-issue/vendor/amphp/file/src/Driver/ParallelFilesystemDriver.php:49
Stack trace:
#0 /home/raz/GitHub/tncrazvan/amphp-file-reproduction-SplObjectStorage-issue/vendor/amphp/file/src/Internal/FileWorker.php(26): Amp\File\Driver\ParallelFilesystemDriver::Amp\File\Driver\{closure}()
#1 [internal function]: Amp\File\Internal\FileWorker->__destruct()
#2 {main}

Next Error: Cannot use object of type SplObjectStorage as array in /home/raz/GitHub/tncrazvan/amphp-file-reproduction-SplObjectStorage-issue/vendor/amphp/file/src/Driver/ParallelFilesystemDriver.php:49
Stack trace:
#0 /home/raz/GitHub/tncrazvan/amphp-file-reproduction-SplObjectStorage-issue/vendor/amphp/file/src/Internal/FileWorker.php(26): Amp\File\Driver\ParallelFilesystemDriver::Amp\File\Driver\{closure}()
#1 [internal function]: Amp\File\Internal\FileWorker->__destruct()
#2 {main}
  thrown in /home/raz/GitHub/tncrazvan/amphp-file-reproduction-SplObjectStorage-issue/vendor/amphp/file/src/Driver/ParallelFilesystemDriver.php on line 49

Note

The error is only visible after closing the program (ctrl+c).

The problem seems to be this assert.

I think I'm doing something wrong but I'm not sure exactly what.

It's probably too much to ask for a solution because there's a lot of code behind my use case.

I was wondering if you have any ideas as to what is causing that worker to disappear from the storage.

It's a bit difficult to debug because the problem doesn't seem to happen at all while running with xdebug, it just works fine when running with xdebug for some reason.

My first instinct tells me it's somewhat related to timing and xdebug slows the application enough to the point where the worker doesn't get detached at the wrong time?

Other notes

  • My whole application is wrapped in one single

    async(...)->await();

    You can see that by following Bootstrap::start.

  • Other than openFile and the amp http server, there are no other async operations in the application going on.
    However, I am trying serve the client byte range responses when possible.
    Which is this piece of code here.
    It's nothing fancy, it just reads the range header and throws the exception if it's invalid and falls back to streaming the file as usual.

stat failed

hi, i have an error in amphp when i init madeline
Exception: stat(): stat failed for E:\php\telegram\tbot\session.madeline.safe.php in BlockingDriver.php:47
PHP Fatal error: Uncaught \danog\MadelineProto\Exception: stat(): stat failed for E:\session.madeline.safe.php in phar://madeline-12bb67bc0618338b71ff507bd50a6b948d48e98e-80.phar/vendor/phabel-transpiler80.amphp/file/src/Driver/BlockingDriver.php:47

EioDriver is blocking

I'm developing a file system watcher using Amp and am in the process of replacing blocking file system operations with amphp/file. UvDriver works ok but has a couple of (c[++]?) extension issues:

  1. readlink causes a crash when a path does not exist
  2. scandir on an empty directory causes an error
  3. stat returns an invalid definition (link instead of nlink)

So I'd like to use EioDriver. However, it appears to be blocking. I have a repository andrewmackrodt/filesystem which demonstrates the issue.

Reproduction steps:

uv and eio extensions must be installed before proceeding

# checkout and initialize the project
git clone https://github.com/andrewmackrodt/filesystem.git
cd filesystem
composer install

# run the scandir test using the default driver (uv)
php test.php

# run the scandir test using eio (eio)
EIO_ENABLED=1 php test.php

Notice how the output between UvDriver and EioDriver differs, i.e. the 10 second repeat loop is never called when executing using EioDriver.

composer.json is currently tracking my own fork of amphp/file, but the issue exists in 0.3 from packagist too

Broken ext-uv 0.2 support in dev-master

I wanted to take a look at the problem from one of my PRs and found out that the tests are not passing in dev-master when ext-uv v0.2 is installed. By checking out some older commits I found out that it was broken by the upgrade to ext-uv 0.3: ae97b95.

FileMutex does not release mutex if process is killed

<?php

use Amp\File\FileMutex;

require 'vendor/autoload.php';

$pid = pcntl_fork();

if ($pid) {
    sleep(1);
    posix_kill($pid, 9);
    var_dump("killed");

    var_dump("Trying to re-acquire lock");
    $lock = new FileMutex('/tmp/test');
    $lock->acquire();
    
    var_dump("unreachable");
} else {
    $lock = new FileMutex('/tmp/test');
    $lock->acquire();
    var_dump("Acquired lock!");
}

using flock instead of just file creation like in https://github.com/danog/MadelineProto/blob/v8/src/AsyncTools.php#L83 should fix the issue.

Add optional time parameters to touch function

PHP's built-in touch function has 2 optional parameter:

  • time
    The touch time. If time is not supplied, the current system time is used.
  • atime
    If present, the access time of the given filename is set to the value of atime. Otherwise, it is set to the value passed to the time parameter. If neither are present, the current system time is used.

These parameters are useful for some common use cases and worth to be added to the lib

EioDriver not working

After upgrading to amphp/file v2, EioDriver is not working anymore.

I simplified it to this:

\Amp\Loop::run(
	function () {
		\Amp\File\filesystem(new \Amp\File\Driver\EioDriver(\Amp\Loop::get()));
		echo 1;
		yield \Amp\File\openFile(tempnam(sys_get_temp_dir(), 'test'), 'r');
		echo 2;
	}
);

The result is that echo 2 is never called. No error anywhere, the script just keeps running.

Non-blocking driver using OS programs and child processes

Is there any reason we couldn't create a new driver which uses amphp/process to invoke OS programs (such as cat) in order to provide a non-blocking driver with no dependency on any PHP extensions? This probably wouldn't work as well as libuv but it could act as a nice polyfill.

Support for file locks

We might need it to support file based sessions using UV / EIO. If those do not support it, we have to go with blocking standard library operations.

Bug while create directory recursively with async driver

Hi,
An exception is thrown when try to create directory recursively with async driver.

yield createDirectoryRecursively('/test/1/');

This create directory but throw an exception.

Problem was in ending slash and only in async drivers. Blocking driver works fine using mkdir(). Seems, async drivers must work the same as blocking driver.

Inconsistent and incorrect behavior

require 'vendor/autoload.php';

$file = Amp\File\openFile('test.txt', 'a');
$file->write("test\n");
unset($file);

Revolt\EventLoop::run();
  1. When using default driver the execution hangs.
  2. When using eio driver the a mode behaves like w.
  3. When using uv driver it works but the file is not automatically closed in underlying destructors. I discovered this by encountering an anomalous chart of open file descriptors (similar code in a real module). Is it meant to be closed manually?

Permission Error Writing a file on Windows 10 & PHP 7.4

The same error happens, no matter what the permissions are.
The same exact code works fine under Linux.


Exception: fwrite(): write of 8192 bytes failed with errno=13 Permission denied in BlockingFile.php:66

Previous TL trace:
exceptionErrorHandler()
BlockingFile.php(66): fwrite()
Files.php(1153): write()

Is it possible to use this with virtual file system stream wrapper?

Hi,
probably I'm missing something but I would like to use this library with https://github.com/mikey179/vfsStream and I get an error. I made a super simple test script:

<?php

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

\org\bovigo\vfs\vfsStream::setup();

$path = \org\bovigo\vfs\vfsStream::url('root/file.txt');
$result = @\file_put_contents($path, 'hello world');
var_dump($result);
var_dump(file_get_contents($path));

\Amp\Loop::run(function () use ($path) {
    $result = yield \Amp\File\put($path, 'hello world');
    var_dump($result);
    var_dump(yield \Amp\File\get($path));
});

And the output is:

int(11)
string(11) "hello world"
PHP Fatal error:  Uncaught Amp\Parallel\Worker\TaskException: Uncaught Amp\File\FilesystemException in worker with message "file_put_contents(vfs://root/file.txt): failed to open stream: No such file or directory" and code "0" in /private/tmp/test/vendor/amphp/parallel/lib/Worker/Internal/TaskFailure.php:55
Stack trace:
#0 /private/tmp/test/vendor/amphp/parallel/lib/Worker/AbstractWorker.php(89): Amp\Parallel\Worker\Internal\TaskFailure->promise()
#1 [internal function]: Amp\Parallel\Worker\AbstractWorker->Amp\Parallel\Worker\{closure}()
#2 /private/tmp/test/vendor/amphp/amp/lib/Coroutine.php(74): Generator->send(Object(Amp\Parallel\Worker\Internal\TaskFailure))
#3 /private/tmp/test/vendor/amphp/amp/lib/Internal/Placeholder.php(127): Amp\Coroutine->Amp\{closure}(NULL, Object(Amp\Parallel\Worker\Internal\TaskFailure))
#4 /private/tmp/test/vendor/amphp/amp/lib/Coroutine.php(79): Amp\Coroutine->resolve(Object(Amp\Parallel\Worker\Internal\TaskFailure))
#5 /private/tmp/test/vendor/amphp/amp/lib/Internal/Pla
Fatal error: Uncaught Amp\Parallel\Worker\TaskException: Uncaught Amp\File\FilesystemException in worker with message "file_put_contents(vfs://root/file.txt): failed to open stream: No such file or directory" and code "0" in /private/tmp/test/vendor/amphp/parallel/lib/Worker/Internal/TaskFailure.php:55
Stack trace:
#0 /private/tmp/test/vendor/amphp/parallel/lib/Worker/AbstractWorker.php(89): Amp\Parallel\Worker\Internal\TaskFailure->promise()
#1 [internal function]: Amp\Parallel\Worker\AbstractWorker->Amp\Parallel\Worker\{closure}()
#2 /private/tmp/test/vendor/amphp/amp/lib/Coroutine.php(74): Generator->send(Object(Amp\Parallel\Worker\Internal\TaskFailure))
#3 /private/tmp/test/vendor/amphp/amp/lib/Internal/Placeholder.php(127): Amp\Coroutine->Amp\{closure}(NULL, Object(Amp\Parallel\Worker\Internal\TaskFailure))
#4 /private/tmp/test/vendor/amphp/amp/lib/Coroutine.php(79): Amp\Coroutine->resolve(Object(Amp\Parallel\Worker\Internal\TaskFailure))
#5 /private/tmp/test/vendor/amphp/amp/lib/Internal/Placeholder.php(127): Amp\Co in /private/tmp/test/vendor/amphp/file/lib/ParallelDriver.php on line 48

As you can see the plain PHP file_put_contents function works (it returns a non false result and then the content is red from the same file).

But with Amp\File\put it doesn't work (I get a fatal error). Why this happens?

The write function blocks the completion of Eventloop::Run()

I'm running the following code:

write('file.txt', 'text');
EventLoop::run(); // it never ends

Writing the file works as expected, the script hangs on the EventLoop::run() call. I have a Windows operating system. I didn't install any additional extensions for event loop.

I only see this problem when using the write function. I don't see this problem when I use Amp\Http, including when I run asynchronous operations using the async function. The problem also disappears if I replace write with file_put_contents.

Unexpected behavior in GitLab CI with cache and symlinks

TL;DR
To fix issue create a new 1.0.1 version from master where unresolved symlink was deleted. And do not use any symlinks in composer packages, please.

Hi! I found a small bug related to symlinks in 1.0.0 version:
https://github.com/amphp/file/tree/80cfffa8238f4ccfe2bcf425bcc18fd3a8cb5eeb/travis

This folder contains symlink which can't be resolved where using GitLab CI cache for packing/unpacking dependencies into zip-archive. It breaks the vendor dependencies in the docker image and project can't be run successfully.

Container will be runs with error:

Fatal error: Could not check compatibility between Amp\Http\Server\Router::onStart(Amp\Http\Server\Server $server): Amp\Promise and Amp\Http\Server\ServerObserver::onStart(Amp\Http\Server\HttpServer $server): Amp\Promise, because class Amp\Http\Server\Server is not available in /app/vendor/amphp/http-server-router/src/Router.php on line 262

This error does not have any relations with class_exists in there files or how it function works. It just side effect.

Step by step:

  1. Configure GitLab CI for two stages, first stage for install composer requirements and cache them, second stage for build docker image.
  2. First stage runs composer install --ignore-platform-reqs, then cache vendor/ with GitLab CI standard functionality. Zip archive will be created from vendor/ directory.
  3. On second stage, zip archive will be unzipped to git checkout directory.
  4. CI throws warning:
Checking cache for composer-cache-master-2...
Downloading cache.zip from http://172.17.42.175/gitlab-runner-cache/gitlab_runner/project/1452/composer-cache-master-2 
WARNING: vendor/amphp/file/travis/install-uv.sh: chmod vendor/amphp/file/travis/install-uv.sh: no such file or directory (suppressing repeats) 
Successfully extracted cache
  1. Docker image "successfully" created with broken files.
  2. Container runs with error above.

GitLab CI issue: https://gitlab.com/gitlab-org/gitlab-runner/issues/3385

Please, release new version.

How should isfile and isdir work with symlink?

Current version of amphp is possibly inconsistent:

File\isfile('symlink-to-file') - true or false? (currently false)
File\isdir('symlink-to-directory') - true or false? (currently true - note that it doesn't resolve the link, it returns true as a sideeffect of bad behavior described below)

Note that I'm adding a new File\islink() function to detect symlinks.

For comparison PHP's is_dir returns true for symlink to directory according to docs.

is_file doesn't say but from my testing seems to resolve symlink too.

Another note is that currently isfile and isdir return the exact oposite value for an existing file. This may not be correct since it can be neither. For instance PHP's is_file and is_dir both return false for a FIFO.

Event loop hangs after calling exists

Hey, I'm trying to prepare migrating a large codebase from amp v2 to v3 and so far everything has been really smooth, which is impressive, also the documentation and the short descriptions on the github releases page saying what replaced what from v2 to v3 helped a lot.

However I'm having an issue with \Amp\File\exists, it seems to be causing revolt's event loop to hang.

I prepared a repository that reproduces the error as I'm seeing it
https://github.com/tncrazvan/amp-v3-event-loop-hangs-after-exists

I'm running the script and then my event loop seems to hang forever.
image

However if I run some other async operation other than exists, everything works fine, the event loop stops as expected.

These are my php version and modules

PHP 8.2.7 (cli) (built: Jun  8 2023 15:27:40) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.7, Copyright (c) Zend Technologies
    with Zend OPcache v8.2.7, Copyright (c), by Zend Technologies
    with Xdebug v3.2.1, Copyright (c) 2002-2023, by Derick Rethans
[PHP Modules]
calendar
Core
ctype
curl
date
dom
exif
FFI
fileinfo
filter
ftp
gettext
hash
iconv
json
libxml
mbstring
mysqli
mysqlnd
openssl
pcntl
pcre
PDO
pdo_mysql
Phar
posix
random
readline
Reflection
session
shmop
SimpleXML
sockets
sodium
SPL
standard
sysvmsg
sysvsem
sysvshm
tokenizer
uuid
xdebug
xml
xmlreader
xmlwriter
xsl
yaml
Zend OPcache
zlib

[Zend Modules]
Xdebug
Zend OPcache

And this is my os release

Distributor ID:	Pop
Description:	Pop!_OS 22.04 LTS
Release:	22.04
Codename:	jammy

Filesystem driver cache

I'm trying to write a file watcher using \Amp\File\getModificationTime and a custom listFilesRecursive.

This is what listFilesRecursive does:

use function Amp\call;
use function Amp\File\isDirectory;
use function Amp\File\listFiles;

use Amp\Promise;

function listFilesRecursive(string $path):Promise {
    return call(function() use ($path) {
        $items = yield listFiles($path);
        $files = [];
        foreach ($items as $item) {
            $filename = "$path/$item";
            $isDir    = yield isDirectory($filename);
            if ($isDir) {
                foreach (yield listFilesRecursive($filename) as $subItem) {
                    $files[] = $subItem;
                }
                continue;
            }

            $files[] = $filename;
        }
        return $files;
    });
}

I'm running \Amp\File\getModificationTime for each one of those files and everything repeats every X seconds.

The problem is that getModificationTime seems to return the wrong modification time when it runs more than once.

I noticed the filesystem driver is keeping a cache:

public function __construct(Driver $driver)
{
$this->driver = $driver;
$this->statusCache = new Cache(1000, 1024);
}

which is great for both performance and familiarity since the traditional filemtime also uses a cache.

In this case I don't really care if the \Amp\File\* functions are optimized for performance using that cache, I just care for their async nature, I want to avoid a bottleneck when the number of scanned files increases.

I noticed this method exists but it's private:

private function invalidate(array $paths, Promise $promise): Promise
{
foreach ($paths as $path) {
$this->statusCache->delete($path);
}
if (!$promise instanceof Success) {
$promise->onResolve(function () use ($paths) {
foreach ($paths as $path) {
$this->statusCache->delete($path);
}
});
}
return $promise;
}

Is there a way to manually invalidate this cache similar to how traditional php does it with clearstatcache?

Split chown

chown should be possible with UID and / or GID, not always both.

libev driver bad file descriptor when using exists on directory

exceptionErrorHandler(2,"EvLoop::run(): Libev error(9): Bad file descriptor","\/www\/pony\/fantasiaNew\/vendor\/revolt\/event-loop\/src\/EventLoop\/Driver\/EvDriver.php",157)<br>
EvDriver.php(157):   run(3)<br>
AbstractDriver.php(470): dispatch(false)<br>
AbstractDriver.php(532): tick(false)<br>
Revolt\EventLoop\Internal\{closure}()<br>
AbstractDriver.php(86): start()<br>
DriverSuspension.php(97): Revolt\EventLoop\Internal\{closure}()<br>
Future.php(251):     suspend()<br>
EioFilesystemDriver.php(86): await()<br>
Filesystem.php(33):  getStatus("\/www\/pony\/fantasiaNew\/fantasiaNewv8.madeline")<br>
Filesystem.php(58):  getStatus("\/www\/pony\/fantasiaNew\/fantasiaNewv8.madeline")<br>
functions.php(117):  exists("\/www\/pony\/fantasiaNew\/fantasiaNewv8.madeline")<br>
SessionPaths.php(95): Amp\File\exists("\/www\/pony\/fantasiaNew\/fantasiaNewv8.madeline")<br>

creating new session failed

I cant start new session, I delete everything, update package , create new settings file but I get this error:

stat(): stat failed for E:\session.madeline.safe.php in BlockingDriver.php:47

The file session.madeline and it's not existed in the directory because it contains old data of old app.

BlockingFile operations after destructor run throw TypeErrors

PHP Fatal error:  Uncaught TypeError: fseek(): supplied resource is not a valid stream resource in /.../vendor/amphp/file/src/Driver/BlockingFile.php:184
Stack trace:
#0 /.../vendor/amphp/file/src/Driver/BlockingFile.php(184): fseek(Resource id #383, 0, 0)
#1 ...: Amp\File\Driver\BlockingFile->seek(0)

The cycle collector happened to first destroy the BlockingFile instance, then another class wanting to write to it in its destructor.
The fix would be trivial to just also set the handle to null in __destruct. Having it then emit a normal ClosedException.

I'm wondering though, do we really need an explicit fclose() call in BlockingFile destructor, and can't just have it automatically close whenever PHP frees the underlying resource? So that we can just continue using it...

Documentation

Hello Guys,

This is not a real issue i just did not find another way to communicate which is available to me.

Perhaps i just cant find it but is there a reason why there is no getting started or otherwise documentation for the file api?

I switched one of my projects from react and started to compare my available options and this somehow confused me a bit because the basic amp decumentation is already from an user experience not so great, and my reason for switching was file system problems under windows. (which works perfectly fine in amp)

I just dont quite understand it, because all the work for documentation is in the code so its just missing generation for a simple api reference atleast. Perhaps its not needed for most people and i also dont need it to work with the api but for Newcomers or people with less experience it could help. Because the first thing i usually try in a new environment are the basics like writing files making connections etc.

If all this stuff exists and im just not finding it perhaps linking it in the readme more promiment could help people get faster access to amp which has a clearer code base and is better to understand in source than similar projects, but somehow more confusing in its documentation atleast from my standpoint with just some hours into it.

Thanks this is not a real issue but i just could not figure out why this is and thought that perhaps its overlooked because you guys work with it all the time and spend time to write all the comments and references needed so its a somehow a shame if somebody would not use it because of that.

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.