Skip to content

Commit

Permalink
add facade
Browse files Browse the repository at this point in the history
  • Loading branch information
freekmurze committed Mar 26, 2024
1 parent 5c38d79 commit c2f81e7
Show file tree
Hide file tree
Showing 9 changed files with 115 additions and 31 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ coverage
.php_cs.cache
tests/temp
.php-cs-fixer.cache
.phpunit.cache

54 changes: 40 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,23 @@

If you need to execute something with a higher frequency, for example every second, than you've come to the right package. With laravel-short-schedule installed, you can do this:

```php
// in your routes/console.php file

use Spatie\ShortSchedule\Facades\ShortSchedule;

// this command will run every second
ShortSchedule::command('artisan-command')->everySecond();

// this command will run every 30 seconds
ShortSchedule::command('another-artisan-command')->everySeconds(30);

// this command will run every half a second
ShortSchedule::command('another-artisan-command')->everySeconds(0.5);
```

Alternatively, you could add this to the `shortSchedule` method in your console kernel:

```php
// in app\Console\Kernel.php

Expand Down Expand Up @@ -83,6 +100,16 @@ Next, edit the new `ShortScheduleRunCommand.php` file, and change the namespace

## Usage

Un your routes/console.php file, you can use the `ShortSchedule` facade to schedule commands.

```php
// in your routes/console.php file

use Spatie\ShortSchedule\Facades\ShortSchedule;

ShortSchedule::command('artisan-command')->everySecond();
```

In `app\Console\Kernel` you should add a method named `shortSchedule`.

```php
Expand All @@ -103,27 +130,27 @@ protected function shortSchedule(\Spatie\ShortSchedule\ShortSchedule $shortSched
You can run an artisan command every single second like this:

```php
$shortSchedule->command('artisan-command')->everySecond();
ShortSchedule::command('artisan-command')->everySecond();
```

You can specify a specific amount of seconds using `everySeconds`

```php
$shortSchedule->command('artisan-command')->everySeconds(30);
ShortSchedule::command('artisan-command')->everySeconds(30);
```

You can even schedule tasks at sub-second frequency. This task will run every half a second.

```php
$shortSchedule->command('artisan-command')->everySeconds(0.5);
ShortSchedule::command('artisan-command')->everySeconds(0.5);
```

### Scheduling shell commands

Use `exec` to schedule a bash command.

```php
$shortSchedule->exec('bash-command')->everySecond();
ShortSchedule::exec('bash-command')->everySecond();
```

### Preventing overlaps
Expand All @@ -133,52 +160,51 @@ $shortSchedule->exec('bash-command')->everySecond();
You can prevent that by tacking on `withoutOverlapping`

```php
$shortSchedule->command('artisan-command')->everySecond()->withoutOverlapping();
ShortSchedule::command('artisan-command')->everySecond()->withoutOverlapping();
```

### Between time constraints

Limit the task to run between start and end times.

```php
$shortSchedule->command('artisan-command')->between('09:00', '17:00')->everySecond();
ShortSchedule::command('artisan-command')->between('09:00', '17:00')->everySecond();
```

It is safe use overflow days. In this example the command will run on every second between 21:00 and 01:00

```php
$shortSchedule->command('artisan-command')->between('21:00', '01:00')->everySecond();
ShortSchedule::command('artisan-command')->between('21:00', '01:00')->everySecond();
```

### Truth test constraints

The command will run if the given closure return a truthy value. The closure will be evaluated at the same frequency the command is scheduled. So if you schedule the command to run every second, the given closure will also run every second.

```php
$shortSchedule->command('artisan-command')->when(fn() => rand() %2)->everySecond();
ShortSchedule::command('artisan-command')->when(fn() => rand() %2)->everySecond();
```

### Environment constraints

The command will only run on the given environment.

```php
$shortSchedule->command('artisan-command')->environments('production')->everySecond();
ShortSchedule::command('artisan-command')->environments('production')->everySecond();
```

You can also pass an array:

```php
$shortSchedule->command('artisan-command')->environments(['staging', 'production'])->everySecond();
ShortSchedule::command('artisan-command')->environments(['staging', 'production'])->everySecond();
```

### Composite constraints

You can use all constraints mentioned above at once. The command will only execute if all the used constraints pass.

```php
$shortSchedule
->command('artisan-command')
ShortSchedule::command('artisan-command')
->between('09:00', '17:00')
->when($callable)
->everySecond();
Expand All @@ -189,15 +215,15 @@ You can use all constraints mentioned above at once. The command will only execu
Commands won't run whilst Laravel is in maintenance mode. If you would like to force a command to run in maintenance mode you can use the `runInMaintenanceMode` method.

```php
$shortSchedule->command('artisan-command')->everySecond()->runInMaintenanceMode();
ShortSchedule::command('artisan-command')->everySecond()->runInMaintenanceMode();
```

### Running Tasks On One Server

Limit commands to only run on one server at a time.

```php
$shortSchedule->command('artisan-command')->everySecond()->onOneServer();
ShortSchedule::command('artisan-command')->everySecond()->onOneServer();
```

## Events
Expand Down
10 changes: 7 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@
],
"require": {
"php": "^8.0",
"illuminate/cache": "^8.71|^9.0|^10|^11.0",
"illuminate/cache": "^10|^11.0",
"react/event-loop": "^1.1",
"spatie/laravel-package-tools": "^1.16",
"spatie/temporary-directory": "^2.0"
},
"require-dev": {
"mockery/mockery": "^1.3.3",
"orchestra/testbench": "^6.23|^7.0|^8.0|^9.0",
"phpunit/phpunit": "^9.4|^10.5",
"orchestra/testbench": "^8.0|^9.0",
"phpunit/phpunit": "^10.5",
"spatie/test-time": "^1.2"
},
"autoload": {
Expand All @@ -51,6 +52,9 @@
"providers": [
"Spatie\\ShortSchedule\\ShortScheduleServiceProvider"
]
},
"aliases": {
"ShortSchedule": "Spatie\\ShortSchedule\\Facades\\ShortSchedule"
}
},
"minimum-stability": "dev",
Expand Down
7 changes: 4 additions & 3 deletions src/Commands/ShortScheduleRunCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Illuminate\Console\Command;
use React\EventLoop\Factory;
use React\EventLoop\Loop;
use Spatie\ShortSchedule\ShortSchedule;

class ShortScheduleRunCommand extends Command
Expand All @@ -14,8 +15,8 @@ class ShortScheduleRunCommand extends Command

public function handle()
{
$loop = Factory::create();

(new ShortSchedule($loop))->registerCommands()->run($this->option('lifetime'));
app(ShortSchedule::class)
->registerCommandsFromConsoleKernel()
->run($this->option('lifetime'));
}
}
16 changes: 16 additions & 0 deletions src/Facades/ShortSchedule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Spatie\ShortSchedule\Facades;

use Illuminate\Support\Facades\Facade;

class ShortSchedule extends Facade
{
/**
* @mixin \Spatie\ShortSchedule\ShortSchedule
*/
public static function getFacadeAccessor()
{
return \Spatie\ShortSchedule\ShortSchedule::class;
}
}
10 changes: 9 additions & 1 deletion src/ShortSchedule.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Illuminate\Contracts\Console\Kernel;
use Illuminate\Support\Traits\Macroable;
use React\EventLoop\Loop;
use React\EventLoop\LoopInterface;
use ReflectionClass;

Expand All @@ -18,8 +19,15 @@ class ShortSchedule
protected ?int $lifetime = null;

public function __construct(LoopInterface $loop)
{
$this->useLoop($loop);
}

public function useLoop(LoopInterface $loop): self
{
$this->loop = $loop;

return $this;
}

public function command(string $command): PendingShortScheduleCommand
Expand All @@ -40,7 +48,7 @@ public function exec(string $command): PendingShortScheduleCommand
return $pendingCommand;
}

public function registerCommands(): self
public function registerCommandsFromConsoleKernel(): self
{
$kernel = app(Kernel::class);

Expand Down
28 changes: 20 additions & 8 deletions src/ShortScheduleServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,29 @@

namespace Spatie\ShortSchedule;

use Illuminate\Support\ServiceProvider;
use Illuminate\Foundation\Application;
use React\EventLoop\Loop;
use Spatie\LaravelPackageTools\Package;
use Spatie\LaravelPackageTools\PackageServiceProvider;
use Spatie\ShortSchedule\Commands\ShortScheduleRunCommand;

class ShortScheduleServiceProvider extends ServiceProvider
class ShortScheduleServiceProvider extends PackageServiceProvider
{
public function boot()
public function configurePackage(Package $package): void
{
if ($this->app->runningInConsole()) {
$this->commands([
ShortScheduleRunCommand::class,
]);
}
$package
->name('laravel-short-schedule')
->hasCommand(ShortScheduleRunCommand::class);
}

public function bootingPackage()
{
$this->app->singleton(
ShortSchedule::class,
function () {
$loop = Loop::get();

return new ShortSchedule($loop);
});
}
}
12 changes: 12 additions & 0 deletions tests/Feature/ShortScheduleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,23 @@

use Illuminate\Support\Facades\Cache;
use Spatie\ShortSchedule\ShortSchedule;
use Spatie\ShortSchedule\Facades\ShortSchedule as ShortScheduleFacade;
use Spatie\ShortSchedule\Tests\TestCase;
use Spatie\ShortSchedule\Tests\TestClasses\TestKernel;

class ShortScheduleTest extends TestCase
{
/** @test */
public function it_will_execute_a_command_registered_via_the_facade()
{
ShortScheduleFacade::exec("echo 'called' >> '{$this->getTempFilePath()}'")
->everySeconds(0.05);

$this
->runShortScheduleForSeconds(0.14)
->assertTempFileContains('called', 2);
}

/** @test */
public function it_will_execute_registered_command_in_the_shortSchedule_method_of_the_kernel()
{
Expand Down
8 changes: 6 additions & 2 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Illuminate\Contracts\Console\Kernel;
use Orchestra\Testbench\TestCase as Orchestra;
use React\EventLoop\Factory;
use React\EventLoop\Loop;
use React\EventLoop\LoopInterface;
use Spatie\ShortSchedule\ShortSchedule;
use Spatie\ShortSchedule\ShortScheduleServiceProvider;
Expand Down Expand Up @@ -42,7 +43,7 @@ protected function resolveApplicationConsoleKernel($app)

public function getLoopThatStopsAfterSeconds(float $stopAfterSeconds): LoopInterface
{
$loop = Factory::create();
$loop = Loop::get();

$loop->addTimer($stopAfterSeconds, function () use ($loop) {
$loop->stop();
Expand Down Expand Up @@ -75,7 +76,10 @@ protected function runShortScheduleForSeconds(float $seconds): self
{
$loop = $this->getLoopThatStopsAfterSeconds($seconds);

(new ShortSchedule($loop))->registerCommands()->run();
app(ShortSchedule::class)
->useLoop($loop)
->registerCommandsFromConsoleKernel()
->run();

return $this;
}
Expand Down

0 comments on commit c2f81e7

Please sign in to comment.