Azure / azure-functions-python-worker

Python worker for Azure Functions.
http://aka.ms/azurefunctions
MIT License
332 stars 100 forks source link

Using AsgiFunctionApp with another non-http function (QueueTrigger) #1284

Closed garoplin closed 10 months ago

garoplin commented 1 year ago

Is your question related to a specific version? If so, please specify:

Python 3.10, Python v2 model, Az Function 4+

What binding does your question apply to, if any? (e.g. Blob Trigger, Event Hub Binding, etc)

Http + Queue Trigger

Question

I'm developing an application which will consist of 2 functions: Http and QueueTrigger. I want to use Http function with Fast Api. I wrote a simple code based on the documentation and it seems to be working, but i wanted to make sure that this is a proper solution. Namely I've created instance of an application: app = func.AsgiFunctionApp(app=fast_app, http_auth_level=func.AuthLevel.ANONYMOUS). Is it ok to use this app object in QueueTrigger function?

The whole code:



fast_app = FastAPI()

@fast_app.get("/return_http_no_body")
async def return_http_no_body():
    return Response(content='test', media_type="application/json")

app = func.AsgiFunctionApp(app=fast_app,
                           http_auth_level=func.AuthLevel.ANONYMOUS)

@app.function_name(name="QueueFunc")
@app.queue_trigger(arg_name="msg", queue_name="queue",
                   connection="storageAccountConnectionString")  # Queue trigger
def test_function(msg: func.QueueMessage) -> None:
    print(msg.get_body())```
tomvrugt commented 1 year ago

I have the exact same use case: combining FastAPI based http triggers with other trigger types in a single function app. Is it possible/supported?

bhagyshricompany commented 1 year ago

Thanks for informing will check and update you soon on this.

bhagyshricompany commented 1 year ago

@gavin-aguiar pls comment

addeelnayyer commented 11 months ago

any updates on this?

YunchuWang commented 11 months ago

@addeelnayyer Hi, AsgiFunctionApp should support other trigger/binding functions except for http functions (all http functions need to be defined under asgi not separately). Here is an example fastapi + timertrigger:

image
microsoft-github-policy-service[bot] commented 10 months ago

This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment.

DCMattyG commented 5 months ago

Hi @YunchuWang, per my comment in #1352 (which also has a reference to this issue from @alexx087), the above example appears to fail when you actually run it in Azure due to this decorator:

@app.function_name(name="<funcname>")

Your example of running this in Azure as detailed in #1352 excludes this decorator despite being included in your example above and working as expected when using the Azure Function Tools.

This is particularly frustrating because it makes the process of properly naming the function in the Portal impossible, and it will just use a permutation of the actual Python function definition instead (not very pretty).

nikie commented 3 months ago

@DCMattyG

Non-HTTP functions used with an AsgiFunctionApp can be renamed via Blueprint which has the function_name decorator available:

bp = func.Blueprint()

@bp.function_name(name="QueueFunc")
@bp.queue_trigger(arg_name="msg", queue_name="queue", connection="storageAccountConnectionString")
def test_function(msg: func.QueueMessage) -> None:
    print(msg.get_body())

fast_app = FastAPI()
app = func.AsgiFunctionApp(app=fast_app)
app.register_functions(bp)
twferrell commented 2 months ago

@nikie, thank you for posting that example. This worked! I was able to utilize a custom function name for my Non-HTTP function. That said, I want to also provide a custom name for my HTTP function, which is a FastAPI app exactly like the example you have above. Is there a way of renaming the HTTP function as well?

DCMattyG commented 2 months ago

Thank you @nikie!

I concur with @twferrell, my original purpose for asking the question was around renaming the HTTP function (which represents FastAPI).

twferrell commented 2 months ago

@DCMattyG, I got something working. Give this a try and see if this meets your needs. @nikie may have some other better suggestions, but this met my needs:

import azure.functions as func
from fastapi import FastAPI

app = func.FunctionApp()

fastapi_app_v1 = FastAPI(
    root_path="/v1",
    version="v1"
)

# Register our FastAPI as an Azure HTTP Function
@app.function_name("enterprise-apis-v1")
@app.route(route="v1/{*route}", auth_level=func.AuthLevel.ANONYMOUS)
async def register_apis(req: func.HttpRequest) -> func.HttpResponse:
    return await func.AsgiMiddleware(fastapi_app_v1).handle_async(req)