OpenFunction
OpenFunction copied to clipboard
Unable to create a python function with asynchronous bindings
Description
The README in functions-framework-python says that synchronous functions backed by the Knative runtime can now interact with middlewares defined by Dapr output binding or pub/sub
.
I'm trying to run the hello-world example for python with one modification: I add an output binding to it. I'm using the Go example and going by analogy.
Now if I'm not mistaken, in order to actually interact with the output binding, we have to call the send
on a DaprRuntime
object. And in order to access DaprRuntime
, we need to install the python framework, similarly to what the go example does with the go framework. The installation of the framework also requires dapr-ext-grpc
, otherwise the function doesn't even start serving.
The issue is as follows:
If you add functions-framework-python and dapr-ext-grpc
to the requirements, the function gets built and runs. But if you send a POST request to it, you'll receive an error (500
) in the function response, and the grpc._channel._InactiveRpcError
in the logs.
Am I using the library the wrong way? I don't see any different way to access the bindings, and this way renders async and sync with bindings unusable for python.
Environment
- Operating System Information: tried MacOs Ventura 13.0 (M1, arm), and Ubuntu 22.04 LTS (i7, Intel)
- kubernetes version: 1.20
- OpenFunction version: 0.8.1
- Versions of dependent components: Dapr 1.8.3, Keda: 2.8.1, Knative 1.3.2
Expected behavior
- Should be able to use the DaprRuntime objects to send messages to the output binding
- The function should return the hello world message and a success status
Actual behavior
The function returns 500 when POST
ed to.
The functoin logs say:
Traceback (most recent call last):
2023-01-23T18:19:32.693Z File "/layers/google.python.pip/pip/lib/python3.10/site-packages/flask/app.py", line 1844, in finalize_request
2023-01-23T18:19:32.693Z response = self.process_response(response)
2023-01-23T18:19:32.693Z File "/layers/google.python.pip/pip/lib/python3.10/site-packages/flask/app.py", line 2337, in process_response
2023-01-23T18:19:32.693Z response = self.ensure_sync(func)(response)
2023-01-23T18:19:32.693Z File "/layers/google.python.pip/pip/lib/python3.10/site-packages/openfunction/dapr_output_middleware.py", line 12, in dapr_output_middleware
2023-01-23T18:19:32.693Z resp = runtime.send(response.get_data(True))
2023-01-23T18:19:32.693Z File "/layers/google.python.pip/pip/lib/python3.10/site-packages/openfunction/function_runtime.py", line 79, in send
2023-01-23T18:19:32.693Z resp = self.client.invoke_binding(value.component_name, value.operation, data, value.metadata)
2023-01-23T18:19:32.693Z File "/layers/google.python.pip/pip/lib/python3.10/site-packages/dapr/clients/grpc/client.py", line 326, in invoke_binding
2023-01-23T18:19:32.693Z response, call = self._stub.InvokeBinding.with_call(req, metadata=metadata)
2023-01-23T18:19:32.693Z File "/layers/google.python.pip/pip/lib/python3.10/site-packages/grpc/_channel.py", line 957, in with_call
2023-01-23T18:19:32.693Z return _end_unary_response_blocking(state, call, True, None)
2023-01-23T18:19:32.693Z File "/layers/google.python.pip/pip/lib/python3.10/site-packages/grpc/_channel.py", line 849, in _end_unary_response_blocking
2023-01-23T18:19:32.693Z raise _InactiveRpcError(state)
2023-01-23T18:19:32.693Z grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
2023-01-23T18:19:32.693Z status = StatusCode.UNAVAILABLE
2023-01-23T18:19:32.693Z details = "failed to connect to all addresses; last error: UNKNOWN: Failed to connect to remote host: Connection refused"
2023-01-23T18:19:32.693Z debug_error_string = "UNKNOWN:Failed to pick subchannel {created_time:"2023-01-23T18:19:32.688955584+00:00", children:[UNKNOWN:failed to connect to all addresses; last error: UNKNOWN: Failed to connect to remote host: Connection refused {grpc_status:14, created_time:"2023-01-23T18:19:32.688932667+00:00"}]}"
To Reproduce Steps to reproduce the behavior:
- Clone the
hello-world
example into a repository that your cluster can access. - Add
git+https://github.com/OpenFunction/functions-framework-python
anddapr-ext-grpc
torequirements.txt
- Modify the yaml specs provided in the README of the hello world example: add an output binding like in the Go example (by the way, the example seems to confuse bindings and pubsub, which leads to an error. I'm using the
bindings
instead of thepubsub
key). - Deploy the function using the modified specs.
- Send a
POST
request to the function.
@grigorizaika1 The dapr support to both sync and async python functions is not officially released and supported yet. @kehuili Regarding your PR https://github.com/OpenFunction/functions-framework-python/pull/1 :
- Is it compatible with the latest OpenFunction v0.8.1 in which we introduce Dapr-Proxy?
- Is there working samples added for the python sync & async functions dapr integration in https://github.com/OpenFunction/samples/tree/main/functions/async and https://github.com/OpenFunction/samples/tree/main/functions/knative ?
@grigorizaika1 @benjaminhuo Will look into it.