3
3
namespace Illuminate \Console ;
4
4
5
5
use Illuminate \Console \View \Components \Factory ;
6
+ use Illuminate \Contracts \Console \Isolatable ;
6
7
use Illuminate \Support \Traits \Macroable ;
7
8
use Symfony \Component \Console \Command \Command as SymfonyCommand ;
8
9
use Symfony \Component \Console \Input \InputInterface ;
10
+ use Symfony \Component \Console \Input \InputOption ;
9
11
use Symfony \Component \Console \Output \OutputInterface ;
10
12
11
13
class Command extends SymfonyCommand
@@ -86,6 +88,10 @@ public function __construct()
86
88
if (! isset ($ this ->signature )) {
87
89
$ this ->specifyParameters ();
88
90
}
91
+
92
+ if ($ this instanceof Isolatable) {
93
+ $ this ->configureIsolation ();
94
+ }
89
95
}
90
96
91
97
/**
@@ -106,6 +112,22 @@ protected function configureUsingFluentDefinition()
106
112
$ this ->getDefinition ()->addOptions ($ options );
107
113
}
108
114
115
+ /**
116
+ * Configure the console command for isolation.
117
+ *
118
+ * @return void
119
+ */
120
+ protected function configureIsolation ()
121
+ {
122
+ $ this ->getDefinition ()->addOption (new InputOption (
123
+ 'isolated ' ,
124
+ null ,
125
+ InputOption::VALUE_OPTIONAL ,
126
+ 'Do not run the command if another instance of the command is already running ' ,
127
+ false
128
+ ));
129
+ }
130
+
109
131
/**
110
132
* Run the console command.
111
133
*
@@ -139,9 +161,38 @@ public function run(InputInterface $input, OutputInterface $output): int
139
161
*/
140
162
protected function execute (InputInterface $ input , OutputInterface $ output )
141
163
{
164
+ if ($ this instanceof Isolatable && $ this ->option ('isolated ' ) !== false &&
165
+ ! $ this ->commandIsolationMutex ()->create ($ this )) {
166
+ $ this ->comment (sprintf (
167
+ 'The [%s] command is already running. ' , $ this ->getName ()
168
+ ));
169
+
170
+ return (int ) (is_numeric ($ this ->option ('isolated ' ))
171
+ ? $ this ->option ('isolated ' )
172
+ : self ::SUCCESS );
173
+ }
174
+
142
175
$ method = method_exists ($ this , 'handle ' ) ? 'handle ' : '__invoke ' ;
143
176
144
- return (int ) $ this ->laravel ->call ([$ this , $ method ]);
177
+ try {
178
+ return (int ) $ this ->laravel ->call ([$ this , $ method ]);
179
+ } finally {
180
+ if ($ this instanceof Isolatable && $ this ->option ('isolated ' ) !== false ) {
181
+ $ this ->commandIsolationMutex ()->forget ($ this );
182
+ }
183
+ }
184
+ }
185
+
186
+ /**
187
+ * Get a command isolation mutex instance for the command.
188
+ *
189
+ * @return \Illuminate\Console\CommandMutex
190
+ */
191
+ protected function commandIsolationMutex ()
192
+ {
193
+ return $ this ->laravel ->bound (CommandMutex::class)
194
+ ? $ this ->laravel ->make (CommandMutex::class)
195
+ : $ this ->laravel ->make (CacheCommandMutex::class);
145
196
}
146
197
147
198
/**
0 commit comments