Skip to content

Commit 7deeef3

Browse files
WIP: Add isolated option
1 parent 01e31c1 commit 7deeef3

File tree

5 files changed

+107
-2
lines changed

5 files changed

+107
-2
lines changed

src/Concerns/Isolatable.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DragonCode\LaravelActions\Concerns;
6+
7+
use DragonCode\LaravelActions\Constants\Options;
8+
use DragonCode\LaravelActions\Services\Mutex;
9+
10+
trait Isolatable
11+
{
12+
protected function isolationCreate(): bool
13+
{
14+
return $this->isolationMutex()->create($this);
15+
}
16+
17+
protected function isolationForget(): void
18+
{
19+
$this->isolationMutex()->forget($this);
20+
}
21+
22+
protected function isolationMutex(): Mutex
23+
{
24+
return $this->getLaravel()->make(Mutex::class);
25+
}
26+
27+
protected function isolatedStatusCode(): int
28+
{
29+
return (int) (is_numeric($this->option(Options::ISOLATED)) ? $this->option(Options::ISOLATED) : self::SUCCESS);
30+
}
31+
}

src/Concerns/Optionable.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ trait Optionable
1818
Options::CONNECTION,
1919
Options::FORCE,
2020
Options::MUTE,
21+
Options::ISOLATED,
2122
];
2223

2324
protected function configure(): void
@@ -49,6 +50,7 @@ protected function availableOptions(): array
4950
[Options::REALPATH, null, InputOption::VALUE_NONE, 'Indicate any provided action file paths are pre-resolved absolute path'],
5051
[Options::STEP, null, InputOption::VALUE_OPTIONAL, 'Force the actions to be run so they can be rolled back individually'],
5152
[Options::MUTE, null, InputOption::VALUE_NONE, 'Turns off the output of informational messages'],
53+
[Options::ISOLATED, null, InputOption::VALUE_OPTIONAL, 'Do not run the actions command if another instance of the actions command is already running'],
5254
];
5355
}
5456

src/Console/Command.php

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,20 @@
55
namespace DragonCode\LaravelActions\Console;
66

77
use DragonCode\LaravelActions\Concerns\ConfirmableTrait;
8+
use DragonCode\LaravelActions\Concerns\Isolatable;
89
use DragonCode\LaravelActions\Concerns\Optionable;
10+
use DragonCode\LaravelActions\Constants\Options;
911
use DragonCode\LaravelActions\Processors\Processor;
1012
use DragonCode\LaravelActions\Values\Options as OptionsDto;
1113
use Illuminate\Console\Command as BaseCommand;
1214
use Illuminate\Container\Container;
15+
use Symfony\Component\Console\Input\InputInterface;
16+
use Symfony\Component\Console\Output\OutputInterface;
1317

1418
abstract class Command extends BaseCommand
1519
{
1620
use ConfirmableTrait;
21+
use Isolatable;
1722
use Optionable;
1823

1924
protected Processor|string $processor;
@@ -24,10 +29,28 @@ public function handle(): int
2429
$this->resolveProcessor()->handle();
2530
$this->forgetProcessor();
2631

27-
return 0;
32+
return self::SUCCESS;
2833
}
2934

30-
return 1;
35+
return self::FAILURE;
36+
}
37+
38+
protected function execute(InputInterface $input, OutputInterface $output): int
39+
{
40+
if ($this->option(Options::ISOLATED) !== false && ! $this->isolationCreate()) {
41+
$this->comment(sprintf('The [%s] command is already running.', $this->getName()));
42+
43+
return $this->isolatedStatusCode();
44+
}
45+
46+
try {
47+
return parent::execute($input, $output);
48+
}
49+
finally {
50+
if ($this->option(Options::ISOLATED) !== false) {
51+
$this->isolationForget();
52+
}
53+
}
3154
}
3255

3356
protected function resolveProcessor(): Processor

src/Constants/Options.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ class Options
1212

1313
public const FORCE = 'force';
1414

15+
public const ISOLATED = 'isolated';
16+
1517
public const MUTE = 'mute';
1618

1719
public const NAME = 'name';

src/Services/Mutex.php

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DragonCode\LaravelActions\Services;
6+
7+
use Carbon\CarbonInterval;
8+
use DragonCode\LaravelActions\Console\Command;
9+
use Illuminate\Contracts\Cache\Factory as Cache;
10+
use Illuminate\Contracts\Cache\Repository;
11+
12+
class Mutex
13+
{
14+
protected ?string $store = null;
15+
16+
public function __construct(
17+
protected Cache $cache
18+
) {
19+
}
20+
21+
public function create(Command $command): bool
22+
{
23+
return $this->store()->add($this->name($command), true, $this->ttl());
24+
}
25+
26+
public function forget(Command $command): void
27+
{
28+
$this->store()->forget(
29+
$this->name($command)
30+
);
31+
}
32+
33+
protected function store(): Repository
34+
{
35+
return $this->cache->store($this->store);
36+
}
37+
38+
protected function ttl(): CarbonInterval
39+
{
40+
return CarbonInterval::hour();
41+
}
42+
43+
protected function name(Command $command): string
44+
{
45+
return 'framework' . DIRECTORY_SEPARATOR . 'action-' . $command->getName();
46+
}
47+
}

0 commit comments

Comments
 (0)