restbed icon indicating copy to clipboard operation
restbed copied to clipboard

Ability to schedule HTTP client work on service run-loop.

Open ben-crowhurst opened this issue 9 years ago • 11 comments

service.schedule( Request request, const function< void ( Request, Response ) >& callback );

ben-crowhurst avatar Feb 11 '16 00:02 ben-crowhurst

Comment from the peanut gallery: This is a great idea, although not quite enough for my use case. My application needs to perform asynchronous I/O on pipes and files to collect data for HTTP replies, and also run timed events in parallel -- so rather than go multithreaded or export the asio APIs one at a time, I ended up just hacking in a way to supply my own asio::io_service for restbed::Service to use. I can definitely see the appeal of a 'lite' mode where there's no exposed dependencies on non-std libraries, but (in my opinion) integrating with the rest of the asio framework really unlocks the full potential of restbed.

willmmiles avatar Apr 11 '16 14:04 willmmiles

Could you supply a code sample showing your core use case?

I'll see if we have anything in the pipeline that might alleviate your "hack" ;)

callum-kirby avatar Apr 11 '16 21:04 callum-kirby

Sure - I'll see if I can put together an illustrative example.

willmmiles avatar Apr 12 '16 16:04 willmmiles

OK, I've put together an example at https://github.com/willmmiles/restbed/tree/external_asio called 'cgi'. It's a partial implementation of a CGI-like interface whereby an external program is called and the results are streamed back to the client. ASIO is used to allow parallel operation processing. As written, the example should take the POST data, feed it in to 'sort', and return the results to the client.

I integrated it into the build tree even though the code isn't of the same quality because it seemed like the simplest way to make sure you could build it easily. Note that this prototype uses posix_spawn, so it needs to be run on a UNIX-like system.

My specific application does something similar, although not exactly the same. I'm putting together a network front-end for a package management system, so I need to be able to collect the output of package's shell install scripts and stream it back to a client in real time. This kind of solution lets me achieve this without resorting to threading or polling.

willmmiles avatar Apr 20 '16 21:04 willmmiles

Thanks for this, please allow us some time to review your example.

ben-crowhurst avatar Apr 21 '16 09:04 ben-crowhurst

@willmmiles Given the fact that ASIO is getting main streamed into an upcoming C++ Standard. I'd like to propose the following.

shared_ptr< asio::io_service > Service::get_runloop( void ) const;
void Service::set_runloop( const shared_ptr< asio::io_service >& );

Do you have any thoughts?

ben-crowhurst avatar Nov 03 '16 03:11 ben-crowhurst

FYI: We've been reluctant to expose our dependencies to 3rd-parties. However, as stated ASIO is getting mainstreamed.

ben-crowhurst avatar Nov 03 '16 03:11 ben-crowhurst

Hm, in terms of implementation details, I'd be somewhat wary of a the set_runloop() call -- you'd have to carefully manage where this is legal, because IIRC a reference to the asio::io_service class is captured in all of the asio::*::socket() classes when constructed (and other places, possibly), and that reference can't be changed after construction. I think it might be better to optionally accept a shared_ptrasio::io_service object during restbed::Service construction instead; then you don't have to worry about managing object scope.

willmmiles avatar Nov 03 '16 17:11 willmmiles

Re dependencies -- from my chair, the deep question is how you want to think of the relationship between restbed and ASIO. Is it a dependency - an implementation detail irrelevant to a potential user? Or is ASIO a foundation - an environment upon which restbed may be plugged in to offer some powerful new abstractions? My $0.02 would be that since restbed's core approach seems to be strongly related to ASIO concepts, I think it might make more sense to treat ASIO as a foundational component supplied by the environment, rather than a dependency best kept hidden.

willmmiles avatar Nov 03 '16 17:11 willmmiles

Restbed currently has no support for run-time modifications. You would be restricted to calling set_runloop prior to Service::start.

Discussions have been conducted on whether ASIO is the correct choice. We are working towards an architecture where you would supply a Runloop epoll, select, LibEvent, LibUV, or another approach.

vision

auto service = make_shared< Service >( );
service->set_runloop( EPollInstance );
service->add_application_layer( HTTP1Instance );
service->add_application_layer( HTTP2Instance );
service->add_application_layer( SPDYInstance );
service->set_network_layer( TCPInstance );
//service->set_network_layer( RS232Instance);
//service->set_network_layer( USBInstance);
service.start( settings );

ben-crowhurst avatar Nov 03 '16 21:11 ben-crowhurst

auto service = make_shared< Service >( settings, runloop );
auto runloop = service->get_runloop( );
...
auto runloop = session->get_runloop( );

ben-crowhurst avatar Nov 16 '16 02:11 ben-crowhurst