brefphp / bref

Serverless PHP on AWS Lambda
https://bref.sh
MIT License
3.1k stars 367 forks source link

SQS Queues Failing in Lambda #1651

Closed Mugluck closed 12 months ago

Mugluck commented 12 months ago

First up, huge thank you to the amazing work on this project. It felt automagical to see it go live and work. Everything worked flawless up till the job processing part. As a new user I've been trying to dig through any documentation I could find and really have completely come up blank as to why the jobs are failing, so would love a more experienced eye to point to what I'm missing.

I'm using laravel-bridge with bref: bref v: 2.1 laravel-bridge v: 2.1

Also using extra php extensions for mongodb, which is working well in the api context.

API context works perfectly. Items are being put onto the queue. Queue worker is picking up the job. Then after the job is run, this is the output:

image

How to reproduce:

I'm using the latest version of API Gateway, and Lambda, or whatever the current default is.

The serverless file is below:

service: app

provider:
    name: aws
    region: ap-southeast-2
    runtime: provided.al2
    stackName: my-api
    environment:
        # environment variable for Laravel
        FILESYSTEM_DISK: s3
        AWS_BUCKET: !Ref Storage
        -- env trimmed --
        VIEW_COMPILED_PATHL: /tmp/storage/framework/views
        QUEUE_CONNECTION: sqs
        SQS_QUEUE: ${construct:jobs.queueUrl}
        SQS_PREFIX: "https://sqs.${aws:region}.amazonaws.com/${aws:accountId}"
        APP_ENV: production
    iam:
        role:
            statements:
                # Allow Lambda to read and write files in the S3 buckets
                -   Effect: Allow
                    Action: s3:*
                    Resource:
                        - !Sub '${Storage.Arn}' # the storage bucket
                        - !Sub '${Storage.Arn}/*' # and everything inside
resources:
    Resources:
        # Create our S3 storage bucket using CloudFormation
        Storage:
            Type: AWS::S3::Bucket

plugins:
    - ./vendor/bref/bref
    - serverless-lift
    - ./vendor/bref/extra-php-extensions

constructs:
    website:
        type: server-side-website
        assets:
            '/vendor/*': public/vendor
            '/favicon.ico': public/favicon.ico
            '/robots.txt': public/robots.txt
            '/index.php': public/index.php
            '/.htaccess': public/.htaccess
    jobs:
        type: queue
        worker:
            handler: Bref\LaravelBridge\Queue\QueueHandler
            # runtime: php-81
            timeout: 59 # in seconds
            layers:
                - ${bref:layer.php-81-fpm}
                - ${bref-extra:mongodb-php-81}
            # events:
            # -   sqs:
            #         arn: !GetAtt Queue.Arn
            #         batchSize: 1
            #         maximumBatchingWindow: 60
            # add here any file or directory that needs to be served from S3
functions:
    api:
        handler: public/index.php
        environment:
            LOG_CHANNEL: stderr
            SESSION_DRIVER: array
            CACHE_DRIVER: array
            FILESYSTEM_DISK: s3
            AWS_BUCKET: !Ref Storage
        description: ''
        layers:
            - ${bref:layer.php-81-fpm}
            - ${bref-extra:mongodb-php-81} # <----- For Mongodb layer
        # runtime: php-82-fpm
        timeout: 28 # in seconds (API Gateway has a timeout of 29 seconds)
        events:
            -   httpApi: '*'

# Exclude files from deployment
package:
    patterns:
        - '!node_modules/**'
        - '!tests/**'

Some older posts showed people using a worker file for job workers, is this something I should make and point to instead of the QueueHandler namespace like how the index.php is used? All the documentation just says to use the namespace

mnapoli commented 12 months ago

Everything looks great in your config, this should work, something is going wrong somewhere.

Can you confirm you are on the latest Bref version? I recently merged https://github.com/brefphp/bref/pull/1616 that should add a full stack trace (but I think you are on this version)

So my other suspicion would be that the Bref service provider for Laravel is not automatically registered? Does your Laravel app not automatically register packages maybe? (https://github.com/laravel/framework/pull/19420)

Mugluck commented 12 months ago

Thanks! Can confirm that the project's bootstrapped packages have the bridge service provider cached:

image

Regarding the stack trace, I can investigate this, the current version in the composer.json is the latest I think? image

Stack traces in the api work fine. It spits out full errors. For some reason this is only happening with the jobworker runtime. If there's meant to be a full stack trace that does imply the rest of the runtime is potentially missing or partially incomplete. I'll do some testing with the laravel demo in the git and see if I can replicate or not.

mnapoli commented 12 months ago

Thanks for confirming!

Ok 🤔 Maybe the https://github.com/brefphp/laravel-bridge/blob/master/src/bref-init.php file is not running in your case? Composer should automatically require it for every invocation (https://github.com/brefphp/laravel-bridge/blob/master/composer.json#L37-L39), could you check in vendor/composer/autoload_files.php if you can see this file is correctly included by Composer?

mnapoli commented 12 months ago

Oh wait!

    jobs:
        type: queue
        worker:
            handler: Bref\LaravelBridge\Queue\QueueHandler
            # runtime: php-81

Why is the runtime commented? Bref is not running at all here 🤔

Mugluck commented 12 months ago

I was testing different options to see if the runtime effected it :). It still has the same error regardless. The laravel demo project works! So there must be some weird discrepancy between them. I'm currently testing plugin installs and different serverless.yml settings to see if they cause the demo to eventually fail the job. I've also set up my project to have a similar job structure to keep them in parity.

I did manage to get the jobs to run by directly referencing the actual file in the handler import, but this causes an error where it squawks about the message needing to come from APIGateway or something, so I assume I need to instantiate it properly as maybe the request context is missing or something.

Also looks like the autoload files exist: image

Mugluck commented 12 months ago

Ok after a lot of debugging and isolation I finally narrowed it down to the following: image

As you noticed earlier, it was runtime related. But in this case the bref php layer was conflicting with the runtime php. The bref layer was included to allow compatibility to the mongodb layer I'm using.

So there we have it! Missing Bref\LaravelBridge\Queue\QueueHandler means it's a runtime problem!

Anyways, hopefully this helps the next person unfamiliar with the stack to debug it!

Thanks a lot for the help @mnapoli. Really appreciate it!