From 7095770b9517987989e952739961475ffe97b2cc Mon Sep 17 00:00:00 2001 From: Dillenn Terumalai <dillenn.terumalai@sib.swiss> Date: Mon, 19 Jul 2021 08:54:51 +0200 Subject: [PATCH] // WIP --- .gitlab-ci.yml | 2 +- src/Console/WatchCommand.php | 5 +++- src/Watcher.php | 16 ++++++---- src/WatcherOptions.php | 12 ++++++-- tests/Feature/WatcherCommandTest.php | 45 ++++++++++++++++++++++++++-- 5 files changed, 68 insertions(+), 12 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 51e5cc8..b9e2f29 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -5,7 +5,7 @@ test:package: - apt-get install -qq git curl libmcrypt-dev libjpeg-dev libpng-dev libfreetype6-dev libbz2-dev libzip-dev zip - apt-get clean - pecl install mcrypt inotify - - docker-php-ext-enable mcrypt + - docker-php-ext-enable mcrypt inotify - docker-php-ext-install zip - curl --silent --show-error "https://getcomposer.org/installer" | php -- --install-dir=/usr/local/bin --filename=composer script: diff --git a/src/Console/WatchCommand.php b/src/Console/WatchCommand.php index a313cbb..73674a6 100644 --- a/src/Console/WatchCommand.php +++ b/src/Console/WatchCommand.php @@ -18,6 +18,7 @@ class WatchCommand extends Command */ protected $signature = 'watch:run {--force : Force the worker to run even in maintenance mode} + {--once : Specify if the watcher should stop after one file has been detected} {--sleep=3 : Number of seconds to sleep when no job is available} {--rest=0 : Number of seconds to rest between jobs} {--timeout=0 : Only process the event on the queue}'; @@ -99,7 +100,8 @@ class WatchCommand extends Command $this->option('sleep'), $this->option('force'), $this->option('rest'), - $this->option('timeout') + $this->option('timeout'), + $this->option('once') ); } @@ -107,6 +109,7 @@ class WatchCommand extends Command * Listen for the queue events in order to update the console output. * * @return void + * @psalm-suppress UndefinedInterfaceMethod */ protected function listenForEvents(): void { diff --git a/src/Watcher.php b/src/Watcher.php index 0dae160..dc7bc17 100644 --- a/src/Watcher.php +++ b/src/Watcher.php @@ -48,7 +48,7 @@ class Watcher /** * The inotify instance * - * @var resource + * @var resource|closed-resource */ protected $inotify; @@ -94,9 +94,9 @@ class Watcher * Execute the console command. * * @param WatcherOptions $options - * @return int + * @return int|null */ - public function daemon(WatcherOptions $options): int + public function daemon(WatcherOptions $options) { if ($this->supportsAsyncSignals()) { $this->listenForSignals(); @@ -138,6 +138,10 @@ class Watcher $cookie ); + if ($options->once) { + $this->shouldQuit = true; + } + if ($options->rest > 0) { $this->sleep($options->rest); } @@ -270,11 +274,11 @@ class Watcher protected function stopWatchers(): void { foreach (array_keys($this->watchers) as $watcher) { - inotify_rm_watch($this->inotify, $watcher); + if(inotify_rm_watch($this->inotify, $watcher)) { + unset($this->watchers[$watcher]); + } } - $this->watchers = []; - $this->unregisterWatchers(); } diff --git a/src/WatcherOptions.php b/src/WatcherOptions.php index 68e0000..f3a8717 100644 --- a/src/WatcherOptions.php +++ b/src/WatcherOptions.php @@ -26,12 +26,19 @@ class WatcherOptions public $force; /** - * Indicates if the watcher should stop after one event. + * Indicates if the watcher should stop after a specific elapsed time (in seconds). * * @var mixed */ public $timeout; + /** + * Indicates if the watcher should stop after one event. + * + * @var mixed + */ + public $once; + /** * Create a new watcher options instance. * @@ -40,11 +47,12 @@ class WatcherOptions * @param mixed $rest * @return void */ - public function __construct($sleep = 5, $force = false, $rest = 0, $timeout = 0) + public function __construct($sleep = 5, $force = false, $rest = 0, $timeout = 0, $once = false) { $this->sleep = $sleep; $this->rest = $rest; $this->force = $force; $this->timeout = $timeout; + $this->once = $once; } } diff --git a/tests/Feature/WatcherCommandTest.php b/tests/Feature/WatcherCommandTest.php index cdd0187..6ece1ed 100644 --- a/tests/Feature/WatcherCommandTest.php +++ b/tests/Feature/WatcherCommandTest.php @@ -4,7 +4,6 @@ namespace Dterumal\Watcher\Tests\Feature; use Dterumal\Watcher\Events\FileEvent; use Dterumal\Watcher\Events\WatcherCreated; -use Dterumal\Watcher\Events\WatcherRestarted; use Dterumal\Watcher\Events\WatcherStopped; use Dterumal\Watcher\Tests\TestCase; use Illuminate\Support\Facades\Artisan; @@ -73,11 +72,53 @@ class WatcherCommandTest extends TestCase // Check that the watcher was created Event::assertDispatched(FileEvent::class, function ($event) { - ray($event); return $event->directory === 'default' && $event->mask === 256 && $event->cookie === 0 && $event->name === 'test.txt'; }); } + + /** @test */ + function it_detects_a_file_and_exits_with_option_once() + { + Event::fake(); + + // File created + $fooFile = storage_path('app/test.txt'); + + // make sure we're starting from a clean state + if (File::exists($fooFile)) { + unlink($fooFile); + } + + // Start background process + $process = new Process(['/bin/bash', 'sleep-and-create-a-file.sh', $fooFile], $this->getStubDirectory()); + $process->start(); + + // Run the artisan command + $exitCode = Artisan::call('watch:run', [ + '--once' => true + ], new NullOutput); + + // Assert a new file is created + $this->assertTrue(File::exists($fooFile)); + unlink($fooFile); + + // Check that exit code + $this->assertSame(0, $exitCode); + + // Check that the watcher was created + Event::assertDispatched(FileEvent::class, function ($event) { + return $event->directory === 'default' && + $event->mask === 256 && + $event->cookie === 0 && + $event->name === 'test.txt'; + }); + + // Check that the watcher was stopped + Event::assertDispatched(WatcherStopped::class, function ($event) { + return $event->status === 0; + }); + } } \ No newline at end of file -- GitLab