Skip to content

Commit b7ac9ed

Browse files
authored
Merge pull request #81 from craftcms/cloud/commands-worker
Commands via SQS
2 parents 7d4cc7b + 9ca0be3 commit b7ac9ed

File tree

4 files changed

+113
-1
lines changed

4 files changed

+113
-1
lines changed

composer.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
{
22
"minimum-stability": "dev",
3-
"prefer-stable": true,
43
"name": "craftcms/cloud",
54
"type": "yii2-extension",
65
"require": {

src/bref/craft/CraftCliEntrypoint.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace craft\cloud\bref\craft;
4+
5+
use Symfony\Component\Process\Process;
6+
7+
final class CraftCliEntrypoint
8+
{
9+
/**
10+
* We leave a 10-second buffer for Lambda to start up and shutdown gracefully.
11+
*/
12+
private const LAMBDA_EXECUTION_LIMIT = 890;
13+
14+
private function command(string $command, array $environment, int $timeout): array
15+
{
16+
$php = PHP_BINARY;
17+
18+
$shellCommand = escapeshellcmd("$php /var/task/craft $command");
19+
20+
$process = Process::fromShellCommandline($shellCommand, null, $environment, null, $timeout);
21+
22+
$process->run(function($type, $buffer): void {
23+
echo $buffer;
24+
});
25+
26+
return [
27+
'exit_code' => $process->getExitCode(),
28+
'output' => $process->getErrorOutput() . $process->getOutput(),
29+
'duration' => microtime(true) - $process->getStartTime(),
30+
];
31+
}
32+
33+
public function lambdaCommand(string $command, array $environment)
34+
{
35+
return $this->command($command, $environment, self::LAMBDA_EXECUTION_LIMIT);
36+
}
37+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
namespace craft\cloud\bref\handlers;
4+
5+
use Bref\Context\Context;
6+
use Bref\Event\Handler;
7+
use craft\cloud\bref\craft\CraftCliEntrypoint;
8+
use InvalidArgumentException;
9+
10+
/**
11+
* @internal
12+
*/
13+
final class CraftCommandHandler implements Handler
14+
{
15+
/**
16+
* @inheritDoc
17+
*/
18+
public function handle(mixed $event, Context $context): array
19+
{
20+
if (!isset($event['command'])) {
21+
throw new InvalidArgumentException('No command found.');
22+
}
23+
24+
$command = $event['command'];
25+
26+
$environment = ['LAMBDA_INVOCATION_CONTEXT' => json_encode($context, JSON_THROW_ON_ERROR)];
27+
28+
$entrypoint = new CraftCliEntrypoint();
29+
30+
return $entrypoint->lambdaCommand($command, $environment);
31+
}
32+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
namespace craft\cloud\bref\handlers;
4+
5+
use Bref\Context\Context;
6+
use Bref\Event\Sqs\SqsEvent;
7+
use Bref\Event\Sqs\SqsHandler;
8+
use Craft;
9+
use craft\cloud\bref\craft\CraftCliEntrypoint;
10+
use RuntimeException;
11+
12+
/**
13+
* @internal
14+
*/
15+
final class CraftCommandSqsHandler extends SqsHandler
16+
{
17+
public function handleSqs(SqsEvent $event, Context $context): void
18+
{
19+
$entrypoint = new CraftCliEntrypoint();
20+
21+
foreach ($event->getRecords() as $record) {
22+
$record->getBody();
23+
24+
$body = json_decode($record->getBody(), flags: JSON_THROW_ON_ERROR);
25+
26+
$command = $body['command'] ?? throw new RuntimeException('Command not found');
27+
28+
$callback = $body['callback'] ?? throw new RuntimeException('Callback URL not found');
29+
30+
$environment = ['LAMBDA_INVOCATION_CONTEXT' => json_encode($context, JSON_THROW_ON_ERROR)];
31+
32+
$result = $entrypoint->lambdaCommand($command, $environment);
33+
34+
$this->sendResultBack($callback, $result);
35+
}
36+
}
37+
38+
private function sendResultBack(string $url, array $body): void
39+
{
40+
$client = Craft::createGuzzleClient();
41+
42+
$client->post($url, ['body' => json_encode($body)]);
43+
}
44+
}

0 commit comments

Comments
 (0)