· 3 min de leitura

Usando o LambdaRuntime do Bref para executar corrotinas Swoole de forma assíncrona como funções na AWS

O Swoole vai lançar algo muito, muito legal, que é sua própria CLI. Você já pode começar a brincar com...

O Swoole vai lançar algo muito, muito legal: sua própria CLI. Você já pode começar a brincar com ela usando o binário pré-compilado distribuído nas releases do Swoole em https://github.com/swoole/swoole-src/releases/tag/v4.8.7.

O truque aqui, para este projeto, é: vamos distribuir o binário da Swoole CLI junto com o LambdaRuntime do Bref para fornecer um runtime AWS Lambda customizado movido por Swoole.

Vamos começar.

Crie um diretório para guardar nossos arquivos:

mkdir swoole-lambda
cd swoole-lambda

Traga o IDE helper do Swoole para termos autocomplete de código no nosso editor:

composer require --dev swoole/ide-helper

Então já podemos trazer o Bref para o playground:

composer require bref/bref

O Bref nos dará a abstração para nos comunicarmos com o runtime da AWS Lambda. Podemos simplesmente chamá-lo no nosso arquivo de bootstrap. O arquivo de bootstrap é onde o runtime da lambda iniciará a invocação:

#!/opt/bin/swoole-cli
<?php

use Bref\Context\Context;
use Bref\Runtime\LambdaRuntime;
use Swoole\Coroutine;

require_once __DIR__ . '/vendor/autoload.php';

$runtime = LambdaRuntime::fromEnvironmentVariable('swoole-cli');
$handler = require $_ENV['LAMBDA_TASK_ROOT'] . '/handler.php';

Coroutine\run(static function () use ($runtime, $handler): void {
    while (true) {
        $runtime->processNextEvent($handler);
    }
});

A AWS Lambda moverá o que estiver no nosso diretório bin/ para /opt/bin, então nossa Swoole CLI estará lá. É por isso que podemos criar nossa aplicação PHP de Bootstrap como um script autoexecutável que usará um interpretador localizado nesse caminho.

Vamos baixá-lo:

wget https://github.com/swoole/swoole-src/releases/download/v4.8.7/swoole-cli-v4.8.7-linux-x64.tar.xz
tar -xf swoole-cli-v4.8.7-linux-x64.tar.xz
mkdir bin
mv swoole-cli bin/
rm swoole-cli-v4.8.7-linux-x64.tar.xz

UPX ao resgate! 148 MB pode ser grande demais para uma função. Vamos usar UPX para deixá-lo menor:

upx -9 bin/swoole-cli

O -9 diz ao UPX para deixá-lo o menor possível. Isso pode demorar um pouco, mas o resultado final é um binário de 44 MB, cerca de 30% do tamanho do arquivo original!

Agora podemos criar com segurança nosso arquivo ZIP do runtime:

zip -r runtime.zip bootstrap bin

E enviá-lo para a AWS Lambda como uma layer:

aws lambda publish-layer-version \
--layer-name swoole-runtime \
--zip-file fileb://runtime.zip \
--region us-east-1

Agora vamos compactar nossos arquivos vendor:

zip -r vendor.zip vendor

E enviá-lo também como uma layer:

aws lambda publish-layer-version \
--layer-name swoole-lambda-vendor \
--zip-file fileb://vendor.zip \
--region us-east-1

Com as layers enviadas, estamos prontos para criar nossa função.

O arquivo handler.php, exigido pelo bootstrap, contém o código da nossa função:

<?php

declare(strict_types=1);

use Bref\Context\Context;

return static fn ($event, Context $context): string =>
    'Hello ' . ($event['name'] ?? 'world');

Compacte:

zip -r function.zip handler.php

E crie:

aws lambda create-function \
--function-name swoole-lambda \
--handler handler.handler \
--zip-file fileb://function.zip \
--runtime provided \
--role arn:aws:iam::884320951759:role/swoole-lambda \
--region us-east-1 \
--layers arn:aws:lambda:us-east-1:884320951759:layer:swoole-runtime:1 \
arn:aws:lambda:us-east-1:884320951759:layer:swoole-lambda-vendor:1

Ok, rufem os tambores.

Vamos testá-la:

aws lambda invoke \
--function-name swoole-lambda \
--region us-east-1 \
--log-type Tail \
--query 'LogResult' \
--output text \
--payload $(echo '{"name": "Swoole"}' | base64) output.txt | base64 --decode

A saída deve ser algo como:

START RequestId: eaa39e02-b833-4f06-b18d-7e9a5b603a97 Version: $LATEST
END RequestId: eaa39e02-b833-4f06-b18d-7e9a5b603a97
REPORT RequestId: eaa39e02-b833-4f06-b18d-7e9a5b603a97  Duration: 3.67 ms       Billed Duration: 4 ms   Memory Size: 128 MB     Max Memory Used: 115 MB

Vamos ver os resultados:

cat output.txt
"Hello Swoole"

É isso, pessoal!

O Bref abstrai todo o trabalho de interface com o runtime da AWS Lambda. Internamente, ele usa curl_*, que o Swoole consegue interceptar e tornar assíncrono!

E, claro, nem preciso dizer que o projeto Swoole CLI também é excelente por nos trazer um interpretador PHP com Swoole embutido (compilado estaticamente).