Is there a way to implement async handlers?
tobymurray opened this issue · 2 comments
Is it possible to register async handlers? I want to do some work in a handler that ultimately invokes a function that calls await
. Currently my code that looks like:
let mut c = ConsumerBuilder::default();
c.register("job_type", &async_handler);
...
async fn async_handler(job: Job) -> io::Result<()> {
// here I would do stuff and .await
Ok(())
}
produces:
error[E0271]: expected `&fn(Job) -> impl Future<Output = Result<(), Error>> {async_handler}` to be a reference that returns `Result<(), Error>`, but it returns `impl Future<Output = Result<(), Error>>`
--> src/main.rs:48:22
|
48 | c.register("job_type", &async_handler);
| -------- ^^^^^^^^^^^^ expected `Result<(), Error>`, found future
| |
| required by a bound introduced by this call
I'm using Tokio, so I guess I can do e.g.:
c.register("job_type", |job| -> io::Result<()> {
let runtime = Runtime::new()?;
runtime.block_on(async_handler(job));
Ok(())
});
The answer at the moment is unfortunately no. You can start a runtime as you indicate, though that's going to slow things down a fair amount since each new such runtime will have a startup cost. You could probably launch one in main
and pass a Handler
to the runtime into each job type you register, though that'll still be somewhat painful.
Realistically, I think the right path forward here is to make this whole library async
, including all the job handler callbacks. Unfortunately, I don't use the library myself any more, so won't have the time it'd take to make such a change, but if someone wants to pick up this project and assume long-term ownership of it, I'd be happy to work with them to make that happen!