oliora / ppconsul

C++ client for Consul (http://consul.io)
Boost Software License 1.0
152 stars 56 forks source link

Add support for asynchronous callbacks #26

Open jgornowich opened 6 years ago

jgornowich commented 6 years ago

Is there currently any plan to add support for watches on the various types in consul?

Currently have the need to watch key and or keyprefix for update/creation/delete. I'm willing to help looking at how to add this. I have previously used the java support for this behavior from the orbitz consul-client.

oliora commented 6 years ago

AFAIK from HTTP API perspective, watches are done via blocking queries. Ppconsul already supports blocking queries although in a quite limited way.

jgornowich commented 6 years ago

Apologies, my initial comment on this issue was not clear and I am still learning all the capabilities of this library. I see from the README and status markdown file that this blocking query is actually there. I was more referring to an enhancements such as you refer to with capabilities for async callbacks, background polling, etc.

For example, an application wanting to watch for all updates on a key, prefix, etc and then be notified with the value that has changed. Maybe a mechanism to map watch items to registered observers and then background a query that polls and reschedules watch items?

oliora commented 6 years ago

Yes, supporting async callbacks or something similar would be great. It's quite pity there is no standard C++ approach for this. From implementation perspective I can only think about something based on boost.asio so user can kinda integrate Ppconsul into its boost.asio based application. Any other solution seems less generic and less standard for me although I'm open for other ideas.

bkannadassan commented 5 years ago

When is this enhancement planned ?. Can you please update on the same. I see above solution to use boost async is that the only option ?.

oliora commented 5 years ago

@bkannadassan it’s not planned yet. The problem is that there is no standard mechanism in C++ to implement it and regardless of the way I chose there will be projects that can’t integrate with it smoothly.

I don’t want to write event based engine by myself thus I need to either use some framework like Boost.Asio or allow user to integrate Ppconsul with an event engine they use.

I’m talking about Boost.Asio for particular reasons: it’s widely used and I’ve already build a lot of successful projects with it. It’s flexible enough to allow Ppconsul to be integrated into any project that’s not based on Boost.Asio for a cost of one extra thread that will handle Ppconsul IO.

I’d like to hear how ppconsul users would like to use asynchronous callbacks and what their application uses as event engine so I can think about providing the best integration experience.

bmahler commented 4 years ago

The Apache Mesos project has it's own custom library for dealing with asynchronicity: https://github.com/apache/mesos/tree/master/3rdparty/libprocess

The ideal integration for us would allow us to implement one or more interfaces using our async library, and pass those implementation to ppconsul for it to use. Off the top of my head, the operations we would provide implementations for:

These would be straightforward for us to implement and pass into ppconsul, and it would then not need any of its own threads nor would it need to block a caller's thread. We use Futures but we can wire those up ourselves on top of callbacks that ppconsul invokes.

I would also suspect that many users don't care about having multiple threadpools and will want some default implementation that they can pass in, like a threadpool + Boost.Asio implementation.

@oliora asynchronous library composition is an interesting area, would love to hear your thoughts!

oliora commented 4 years ago

Ppconsul uses libcurl easy API which is blocking so it’s not possible to make Ppconsul truly asynchronous (i.e. not blocking the execution thread for the request time) without complete rewrite of the network part.

Otherwise, Ppconsul can only be changed to use a thread pool under the hood (either internal or passed from outside). This will still give some benefit for the user perhaps.

It’s an interesting idea to have async library abstracted via an interface but in reality I don’t think this gonna work. Many users want ppconsul as a ready to use solution not a building block thus ppconsul has to provide its own networking implementation anyway. Also it may not be feasible to come up with interface for async calls that still allows to use different libraries effectively. I’m leaning more toward using boost.asio + boost.beast and leave it up to users to integrate it into their event loop. Worst case they will run one extra thread for ppconsul and dispatch completion events from there to their own event loop.

@bmahler which async io library do you use in your projects?

SamuelMarks commented 4 years ago

I've seen a bunch of Rust projects which are runtime independent, i.e, you bring in your own runtime (e.g., event loop).

libprocess is certainly one approach here, as is #include <future> with std::async. If you're willing to up the C++ standard requirements, checkout http://stlab.cc/libraries/concurrency/index.html which looks a lot closer to the Rust API (FWIW).

I'd still hesitate to include boost as a dependency, unless it's clear that the libraries are header only or will be included in the next C++ standard. Boost is heavy!

bmahler commented 4 years ago

One of the few good references I've found on the I/O free library idea is here:

https://sans-io.readthedocs.io/

Ppconsul uses libcurl easy API which is blocking so it’s not possible to make Ppconsul truly asynchronous (i.e. not blocking the execution thread for the request time) without complete rewrite of the network part.

@oliora yeah, what I had suggested implies ppconsul would use a Sans-I/O style HTTP library (for example, the Sans-IO page links to a python implementation) composed with the user provided I/O library. I'm not sure if there are some good sans-I/O style HTTP libraries in C/C++. libcurl does have an async API and from the looks of the examples, it seems like it does let you drive the I/O. In this example, you need to do the polling your own way, and it will perform the non blocking reads/writes when you tell it to:

https://curl.haxx.se/libcurl/c/curl_multi_perform.html

@bmahler which async io library do you use in your projects?

I mainly work on Apache Mesos and it uses libprocess. It's really only used by Mesos.

Many users want ppconsul as a ready to use solution not a building block thus ppconsul has to provide its own networking implementation anyway.

Right, I think you would want one or more default implementations available to users if you were to go this route (e.g. thread pool + libev + libcurl async API, or some other implementation combo). I noted this in my earlier message.

I've seen a bunch of Rust projects which are runtime independent, i.e, you bring in your own runtime (e.g., event loop).

@SamuelMarks Do you have any links?

SamuelMarks commented 4 years ago

Sure, here's a good example: https://github.com/sozu-proxy/lapin