Skip to content

Commit 46b3fcd

Browse files
committed
Support cancelling the activity on Ctrl+C (non-Windows)
1 parent 2a893f5 commit 46b3fcd

File tree

1 file changed

+62
-4
lines changed

1 file changed

+62
-4
lines changed

src/Service/ActivityMonitor.php

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Platformsh\Cli\Service;
44

5+
use GuzzleHttp\Exception\BadResponseException;
56
use Platformsh\Client\Model\Activity;
67
use Platformsh\Client\Model\ActivityLog\LogItem;
78
use Platformsh\Client\Model\Project;
@@ -99,6 +100,28 @@ public function waitAndLog(Activity $activity, $pollInterval = 3, $timestamps =
99100
return Helper::formatTime(time() - $startTime);
100101
});
101102
$bar->setFormat('[%bar%] %elapsed:6s% (%state%)');
103+
104+
// Set up cancellation for the activity on Ctrl+C.
105+
if (\function_exists('\\pcntl_signal') && $activity->operationAvailable('cancel')) {
106+
declare(ticks = 1);
107+
$sigintReceived = false;
108+
/** @noinspection PhpComposerExtensionStubsInspection */
109+
\pcntl_signal(SIGINT, function () use ($activity, $stdErr, $bar, &$sigintReceived) {
110+
if ($sigintReceived) {
111+
exit(1);
112+
}
113+
$bar->clear();
114+
$result = $this->cancel($activity, $stdErr);
115+
if ($result) {
116+
exit(1);
117+
}
118+
$sigintReceived = true;
119+
$stdErr->writeln('');
120+
$bar->advance();
121+
});
122+
$stdErr->writeln('Enter Ctrl+C once to cancel the activity (or twice to quit this command).');
123+
}
124+
102125
$bar->start();
103126

104127
$logStream = $this->getLogStream($activity, $bar);
@@ -166,6 +189,40 @@ public function waitAndLog(Activity $activity, $pollInterval = 3, $timestamps =
166189
return false;
167190
}
168191

192+
/**
193+
* Attempts to cancel the activity, catching and printing errors.
194+
*
195+
* @param Activity $activity
196+
* @param OutputInterface $stdErr
197+
*
198+
* @return bool
199+
*/
200+
private function cancel(Activity $activity, OutputInterface $stdErr)
201+
{
202+
if (!$activity->operationAvailable('cancel')) {
203+
$stdErr->writeln('The activity cannot be cancelled.');
204+
return false;
205+
}
206+
$stdErr->writeln('Cancelling the activity...');
207+
try {
208+
try {
209+
$activity->cancel();
210+
} catch (BadResponseException $e) {
211+
if ($e->getResponse() && $e->getResponse()->getStatusCode() === 400 && \strpos($e->getMessage(), 'cannot be cancelled in its current state')) {
212+
$activity->refresh();
213+
$stdErr->writeln(\sprintf('The activity cannot be cancelled in its current state (<error>%s</error>).', $activity->state));
214+
return false;
215+
}
216+
throw $e;
217+
}
218+
} catch (\Exception $e) {
219+
$stdErr->writeln(\sprintf('Failed to cancel the activity: <error>%s</error>', $e->getMessage()));
220+
return false;
221+
}
222+
$stdErr->writeln('The activity was successfully cancelled.');
223+
return true;
224+
}
225+
169226
/**
170227
* Reads the log stream and returns LogItem objects.
171228
*
@@ -435,11 +492,11 @@ private function getStart(Activity $activity) {
435492
private function getLogStream(Activity $activity, ProgressBar $bar) {
436493
$url = $activity->getLink('log');
437494

438-
// Try fetching the stream with a 10 second timeout per call, and a .5
439-
// second interval between calls, for up to 2 minutes.
440-
$readTimeout = 10;
441-
$interval = .5;
495+
// Try fetching the stream with an up to 10 second timeout per call,
496+
// and a .5 second interval between calls, for up to 2 minutes.
497+
$readTimeout = .5;
442498
$stream = \fopen($url, 'r', false, $this->api->getStreamContext($readTimeout));
499+
$interval = .5;
443500
$start = \microtime(true);
444501
while ($stream === false) {
445502
if (\microtime(true) - $start > 120) {
@@ -448,6 +505,7 @@ private function getLogStream(Activity $activity, ProgressBar $bar) {
448505
$bar->advance();
449506
\usleep($interval * 1000000);
450507
$bar->advance();
508+
$readTimeout = $readTimeout >= 10 ? $readTimeout : $readTimeout + .5;
451509
$stream = \fopen($url, 'r', false, $this->api->getStreamContext($readTimeout));
452510
}
453511
\stream_set_blocking($stream, 0);

0 commit comments

Comments
 (0)