0

I am trying to execute a python async function in an actix web socket.

I was able to figure out how to execute a sync function and send the response back to the web socket. However, I am unable to do the same with the async functions.

Here is my approach below:


            Ok(ws::Message::Text(text)) => {
                // need to also passs this text as a param
                let handler_function = &self.router.get("message").unwrap().0;
                let _number_of_params = &self.router.get("message").unwrap().1;
                println!("{:?}", handler_function);
                match handler_function {
                    PyFunction::SyncFunction(handler) => Python::with_gil(|py| {
                        let handler = handler.as_ref(py);
                        // call execute function
                        let op = handler.call0().unwrap();
                        let op: &str = op.extract().unwrap();

                        return ctx.text(op);
                        // return ctx.text(op);
                    }),
                    PyFunction::CoRoutine(handler) => {
                        let fut = Python::with_gil(|py| {
                            let handler = handler.as_ref(py);
                            Ok(pyo3_asyncio::tokio::into_future(handler.call0().unwrap()))
                        })
                        .unwrap();
                        let fut = actix::fut::wrap_future::<_, Self>(fut.unwrap());
                        ctx.spawn(fut);
                        return ctx.text("Async Functions are not supported in WS right now.");
                    }
                }
            }


I am getting the following error:

error[E0271]: type mismatch resolving `<FutureWrap<impl futures_util::Future+std::marker::Send, MyWs> as ActorFuture<MyWs>>::Output == ()`
  --> src/web_socket_connection.rs:88:29
   |
88 |                         ctx.spawn(fut);
   |                             ^^^^^ expected enum `Result`, found `()`
   |
   = note:   expected enum `Result<pyo3::Py<pyo3::PyAny>, pyo3::PyErr>`
           found unit type `()`


error: aborting due to previous error> ] 226/227: robyn

Do let me know if you would require any more details from me.

NEW_APPRROACH

I made some progress and took a new approach where I wrapped the python function inside an async function.


            Ok(ws::Message::Text(text)) => {
                // need to also passs this text as a param
                let handler_function = &self.router.get("message").unwrap().0;
                let _number_of_params = &self.router.get("message").unwrap().1;
                println!("{:?}", handler_function);
                match handler_function {
                    PyFunction::SyncFunction(handler) => Python::with_gil(|py| {
                        let handler = handler.as_ref(py);
                        // call execute function
                        let op = handler.call0().unwrap();
                        let op: &str = op.extract().unwrap();

                        return ctx.text(op);
                        // return ctx.text(op);
                    }),
                    PyFunction::CoRoutine(handler) => {
                        println!("{:?}", handler);
                        println!("Async functions are not supported in WS right now.");
                        let fut = Python::with_gil(|py| {
                            let handler = handler.as_ref(py);
                            pyo3_asyncio::tokio::into_future(handler.call0().unwrap()).unwrap()
                        });
                        let f = async move {
                            let output = fut.await.unwrap();
                            Python::with_gil(|py| {
                                let contents: &str = output.extract(py).unwrap();
                                println!("{:?}", contents);
                            });
                        };
                        let fut = actix::fut::wrap_future::<_, Self>(f);
                        // fut.spawn(self);
                        ctx.spawn(fut);
                        return ctx.text("Async Functions are not supported in WS right now.");
                    }
                }
            }

But now, I am getting an error that the coroutine was never awaited

Async functions are not supported in WS right now.
thread 'actix-rt|system:0|arbiter:0' panicked at 'called `Result::unwrap()` on an `Err` value: PyErr { type: <class 'RuntimeError'>, value: RuntimeError('no running event loop'), traceback: None }', src/web_socket_connection.rs:85:88
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
sys:1: RuntimeWarning: coroutine 'connect' was never awaited
Sebastián Palma
  • 32,692
  • 6
  • 40
  • 59
Sanskar Jethi
  • 544
  • 5
  • 17
  • It looks like part of the error message is missing, can you post the full compiler output? – Coder-256 Dec 12 '21 at 16:48
  • @Coder-256 , I have posted the compiler output. – Sanskar Jethi Dec 12 '21 at 17:18
  • @Coder-256, I also made some progress but I am stuck on a new issue. – Sanskar Jethi Dec 12 '21 at 17:46
  • Unfortunately I think the main issue is the first line of the error: “Async functions are not supported in WS right now.” Maybe try using regular synchronous functions if possible? – Coder-256 Dec 14 '21 at 14:36
  • @Coder-256, that is a debug statement that I am printing. It is not something that the library says. – Sanskar Jethi Dec 14 '21 at 17:02
  • I think you have a problem on one of the `unwrap()` as in one case you have an error istead. You can change the unwrap()s with the expect() to catch where it happens or just handle the error case. – Mario Santini Dec 17 '21 at 10:45
  • @SanskarJethi It's because you're mixing pyo3_asyncio runtime and actix runtime, I have the same problem right now on a project I work on. – Gepsens Dec 30 '21 at 16:43

0 Answers0