Open josephp27 opened 2 months ago
We have some users combining Mangum with FastAPI: https://pypi.org/project/mangum
If you do that, make sure you set serve_path="/"
in your Inngest serve
function
Hey! thank you for the help here. Ive been wracking my brain with this for awhile and not sure what I'm missing here. I cant get inngest to discover this function locally. I've gotten it to work outside of an aws handler. But when it's in this, I can't get discovery to work at all :
Dockerfile (docker run -p 8000:8080
FROM public.ecr.aws/lambda/python:3.11
RUN yum update -y
RUN yum update -y python3 curl libcom_err ncurses expat libblkid libuuid libmount
RUN yum install ffmpeg libsm6 libxext6 python3-pip git -y
RUN pip3 install fastapi --target "${LAMBDA_TASK_ROOT}"
RUN pip3 install mangum --target "${LAMBDA_TASK_ROOT}"
RUN pip3 install inngest --target "${LAMBDA_TASK_ROOT}"
# Copy function code
COPY app.py ${LAMBDA_TASK_ROOT}
# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
CMD [ "app.handler" ]
App.py
import logging
import os
from fastapi import FastAPI
from inngest.fast_api import serve
import inngest
from mangum import Mangum
os.environ["INNGEST_DEV"] = "1"
inngest_client = inngest.Inngest(
app_id="fast_api_example",
api_base_url="host.docker.internal:8288",
logger=logging.getLogger("uvicorn"),
)
app = FastAPI()
@app.get("/")
def read_root():
return {"Welcome": "Welcome to the FastAPI on Lambda"}
@inngest_client.create_function(
fn_id="my_function",
trigger=inngest.TriggerEvent(event="app/my_function"),
)
async def my_function(ctx: inngest.Context, step: inngest.Step) -> str:
ctx.logger.info(ctx.event)
return "done"
serve(app, inngest_client, [my_function], serve_path="/")
handler = Mangum(app=app)
Querying:
curl -XPOST "http://localhost:8000/2015-03-31/functions/function/invocations" -d '{"resource": "/", "path": "/", "httpMethod": "GET", "requestContext": {}, "multiValueQueryStringParameters": null}'
{
"statusCode": 200,
"headers": {
"content-length": "46",
"content-type": "application/json"
},
"multiValueHeaders": {},
"body": "{\"Welcome\":\"Welcome to the FastAPI on Lambda\"}",
"isBase64Encoded": false
}
If you're running an app in a Docker container then you'll need to tell our SDK how to reach our Dev Server. By default, our SDK will try to reach the Dev Server at http://localhost:8288
but that won't work in a Docker container. So instead, try setting the INNGEST_DEV=http://host.docker.internal:8288
env var.
The INNGEST_DEV
env var can be a URL if you want to use the Dev Server and you want to explicitly set the Dev Server URL 😄
Hmm, I don't think thats the problem. I was actually able to solve that a different way off the AWS server just using Mangum and FastAPI in a docker container with
inngest_client = inngest.Inngest(
app_id="fast_api_example",
api_base_url="host.docker.internal:8288", // <-- this line
logger=logging.getLogger("uvicorn"),
)
The issue now is inngest dev finding the fastapi server to sync with. I'm not sure where or if it is even being exposed.
Ive tried a few urls like:
curl -XPOST "http://localhost:8000/2015-03-31/functions/function/invocations" -d '{"resource": "/api/inngest", "path": "/api/inngest", "httpMethod": "GET", "requestContext": {}, "multiValueQueryStringParameters": null}'
curl http://localhost:8000/2015-03-31/functions/function/invocations/api/inngest
curl http://localhost:8000/2015-03-31/functions/function/invocations
with no luck
Our Dev Server isn't able to find your app? Could you share the command you use to start our Dev Server?
I got it working locally by overriding entrypoint
and command
:
services:
app:
build:
context: .
environment:
INNGEST_DEV: "http://inngest:8288"
ports:
- "9000:8080"
# Override entrypoint and command so that we don't get the weird AWS Lambda
# response. In production, we also avoid the weird AWS Lambda response if we
# use a "function URL".
entrypoint: ""
command:
[
"fastapi",
"dev",
"lambda_function.py",
"--host",
"0.0.0.0",
"--port",
"8080",
]
inngest:
image: "inngest/inngest:latest"
command: "inngest dev -u http://app:8080/"
ports:
- "8288:8288"
If you don't override them, you'll need to send the weird AWS Lambda request shape:
curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"resource": "/", "path": "/", "httpMethod": "GET", "requestContext": {}, "multiValueQueryStringParameters": null}'
And you'll get the weird AWS Lambda response shape:
{"statusCode": 200, "headers": {"content-type": "application/json", "x-inngest-sdk": "inngest-py:v0.4.19", "x-inngest-req-version": "1", "user-agent": "inngest-py:v0.4.19", "x-inngest-framework": "fast_api", "x-inngest-expected-server-kind": "dev", "content-length": "187"}, "multiValueHeaders": {}, "body": "{\"schema_version\": \"2024-05-24\", \"authentication_succeeded\": null, \"function_count\": 1, \"has_event_key\": false, \"has_signing_key\": false, \"has_signing_key_fallback\": false, \"mode\": \"dev\"}", "isBase64Encoded": false}
In production, using a "Function URL" for your AWS Lambda should avoid the weird requests and responses
How do I serve aws lambda in pyhon? I see there is one in TS but need it in python. Thanks!