cachewerk / bref-laravel-bridge

An advanced Laravel integration for Bref, including Octane support.
MIT License
38 stars 8 forks source link

Better queue handler #6

Closed tillkruss closed 2 years ago

tillkruss commented 2 years ago

Currently, each SQS event will trigger a new Lambda instance. Should we instead keep something like Vapor's work command running?

tillkruss commented 2 years ago
tillkruss commented 2 years ago
while (true) {
    $lambdaRuntime->nextInvocation(function ($invocationId, $event) {
        $commandOptions = trim(sprintf(
            '--delay=%s --timeout=%s --tries=%s %s',
            $_ENV['SQS_DELAY'] ?? 3,
            $_ENV['QUEUE_TIMEOUT'] ?? 0,
            $_ENV['SQS_TRIES'] ?? 3,
            ($_ENV['SQS_FORCE'] ?? false) ? '--force' : ''
        ));

        try {
            static::$app->useStoragePath(StorageDirectories::PATH);

            $consoleKernel = static::$app->make(Kernel::class);

            static::$app->bind(LambdaEvent::class, function () use ($event) {
                return new LambdaEvent($event);
            });

            $consoleInput = new StringInput(
                'vapor:work '.$commandOptions.' --no-interaction'
            );

            $status = $consoleKernel->handle(

                if ($this->downForMaintenance()) {
                    return;
                }

                if (! static::$listeningForEvents) {
                    $this->listenForEvents();

                    static::$listeningForEvents = true;
                }

                $this->worker->setCache($this->laravel['cache']->driver());

                pcntl_async_signals(true);

                pcntl_signal(SIGALRM, function () use ($job) {
                    throw new VaporJobTimedOutException($job->resolveName());
                });

                pcntl_alarm(
                    max($this->timeoutForJob($job, $options), 0)
                );

                app(JobAttempts::class)->increment($job);

                $this->runJob($job, $connectionName, $options);

                pcntl_alarm(0);

            );

            $consoleKernel->terminate($consoleInput, $status);

            return new ArrayLambdaResponse([
                'requestId' => $_ENV['AWS_REQUEST_ID'] ?? null,
                'logGroup' => $_ENV['AWS_LAMBDA_LOG_GROUP_NAME'] ?? null,
                'logStream' => $_ENV['AWS_LAMBDA_LOG_STREAM_NAME'] ?? null,
                'statusCode' => $status,
                'output' => base64_encode($output->fetch()),
            ]);
        } finally {
            unset(static::$app[LambdaEvent::class]);

            $this->terminate();
        }
    });

    LambdaContainer::terminateIfInvocationLimitHasBeenReached(
        ++$invocations, (int) ($_ENV['VAPOR_MAX_REQUESTS'] ?? 250)
    );
}
georgeboot commented 2 years ago

I PR'd to the original bref laravel bridge long ago to basically make it work the same as Vapor's bridge does. Unfortunately, it was not merged.

Maybe it can help you for inspiration: https://github.com/brefphp/laravel-bridge/pull/31

tillkruss commented 2 years ago

Yeah, I saw that. I'm a bit tight for time. Do you want to open a PR against this repo. I do like the Vapor approach.