Skip to content

Commit

Permalink
fix: async shutdown handler not getting called (#965)
Browse files Browse the repository at this point in the history
* fix async shutdown handler

* split startup & shtudown handlers

* document the reasoning behind not creating a new function
  • Loading branch information
VishnuSanal authored Oct 15, 2024
1 parent d3e8cb1 commit 06c487d
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 12 deletions.
6 changes: 5 additions & 1 deletion robyn/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,4 +129,8 @@ def run():
print("Starting dev server...")
start_dev_server(config, config.file_path)
else:
start_app_normally(config)
try:
start_app_normally(config)
except KeyboardInterrupt:
# for the crash happening upon pressing Ctrl + C
pass
2 changes: 1 addition & 1 deletion src/executors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ pub async fn execute_http_function(
})
}

pub async fn execute_event_handler(
pub async fn execute_startup_handler(
event_handler: Option<Arc<FunctionInfo>>,
task_locals: &TaskLocals,
) -> Result<()> {
Expand Down
48 changes: 38 additions & 10 deletions src/server.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use crate::executors::{execute_event_handler, execute_http_function, execute_middleware_function};
use crate::executors::{
execute_http_function, execute_middleware_function, execute_startup_handler,
};

use crate::routers::const_router::ConstRouter;
use crate::routers::Router;
Expand Down Expand Up @@ -122,7 +124,7 @@ impl Server {
thread::spawn(move || {
actix_web::rt::System::new().block_on(async move {
debug!("The number of workers is {}", workers);
execute_event_handler(startup_handler, &task_locals_copy)
execute_startup_handler(startup_handler, &task_locals_copy)
.await
.unwrap();

Expand Down Expand Up @@ -222,14 +224,40 @@ impl Server {
let event_loop = (*event_loop).call_method0("run_forever");
if event_loop.is_err() {
debug!("Ctrl c handler");
Python::with_gil(|py| {
pyo3_asyncio::tokio::run(py, async move {
execute_event_handler(shutdown_handler, &task_locals.clone())
.await
.unwrap();
Ok(())
})
})?;

// executing this from the same file (and not creating a function -- like startup handler)
// to fix an issue that arises when a new async function is spooled up.

// if we create a function & move the code, the function won't run s & raises the warning:
// "unused implementer of `futures_util::Future` that must be used futures do nothing
// unless you await or poll them."

// but, adding `.await` raises the error "await is used inside non-async function,
// which is not an async context".

// which can only be solved by creating a new async function -- hence, resorting
// to this solution

if let Some(function) = shutdown_handler {
if function.is_async {
debug!("Shutdown event handler async");

pyo3_asyncio::tokio::run_until_complete(
task_locals.event_loop(py),
pyo3_asyncio::into_future_with_locals(
&task_locals.clone(),
function.handler.as_ref(py).call0()?,
)
.unwrap(),
)
.unwrap();
} else {
debug!("Shutdown event handler");

Python::with_gil(|py| function.handler.call0(py))?;
}
}

exit(0);
}
Ok(())
Expand Down

0 comments on commit 06c487d

Please sign in to comment.