Consumer example for Google Pub/Sub in C++ - c++

I am trying to play around Google Pub/Sub and I need to integrate it in C++ code-base.
As there is no native support for Google Pub/Sub in C++, I am using it through gRPC. Thus, I have generated corresponding pubsub.grpc.pb.h, pubsub.grpc.pb.cc, pubsub.pb.h and pubsub.pb.cc files via protoc.
Question part: because of lack of documentation it would be very helpful to have an example in C++. I have found an example for publisher part, but not for the subscriber part. I tried to dive into the generated code and examples in other languages, but quite many question arise. Is there any example for the subscriber part? Or may be someone already had such kind of experience?

Just like you are making Publish requests, you can make StreamingPull requests for messages. Note that this is a simple proof of concept, and, in practice, you’d probably want to make this code more robust; e.g. create multiple streams, have the message processing happen on a thread pool, implement some kind of flow control, etc…
#include <iostream>
#include <memory>
#include <grpc++/grpc++.h>
#include "google/pubsub/v1/pubsub.grpc.pb.h"
auto main() -> int {
using grpc::ClientContext;
using grpc::ClientReaderWriter;
using google::pubsub::v1::Subscriber;
using google::pubsub::v1::StreamingPullRequest;
using google::pubsub::v1::StreamingPullResponse;
auto creds = grpc::GoogleDefaultCredentials();
auto stub = std::make_unique<Subscriber::Stub>(
grpc::CreateChannel("pubsub.googleapis.com", creds));
// Open up the stream.
ClientContext context;
std::unique_ptr<ClientReaderWriter<
StreamingPullRequest, StreamingPullResponse>> stream(
stub->StreamingPull(&context));
// Send initial message.
StreamingPullRequest request;
request.set_subscription(
"projects/pubsub-cpp-api-1504713535863/subscriptions/testing");
request.set_stream_ack_deadline_seconds(10);
stream->Write(request);
// Receive messages.
StreamingPullResponse response;
while (stream->Read(&response)) {
// Ack messages.
StreamingPullRequest ack_request;
for (const auto &message : response.received_messages()) {
ack_request.add_ack_ids(message.ack_id());
}
stream->Write(ack_request);
}
}
This is the newest Cloud Pub/Sub API, and is the currently recommended way of pulling messages from the service; this is especially true for users who expect high throughput and low latency. Currently, there is no existing client library for C++, but there is an open issue on GitHub for it. The existing client libraries for other languages (e.g. Java) already use this API, so you may be able to replicate their functionality in your own C++ code.
For simpler use-cases, you could also use the older Pull API, which makes many independent requests for messages. Note that, for high throughput and low latency, you should most likely be making many simultaneous asynchronous RPCs: see gRPC documentation.
#include <iostream>
#include <memory>
#include <grpc++/grpc++.h>
#include "google/pubsub/v1/pubsub.grpc.pb.h"
auto main() -> int {
using grpc::ClientContext;
using google::pubsub::v1::Subscriber;
using google::pubsub::v1::PullRequest;
using google::pubsub::v1::PullResponse;
auto creds = grpc::GoogleDefaultCredentials();
auto stub = std::make_unique<Subscriber::Stub>(
grpc::CreateChannel("pubsub.googleapis.com", creds));
PullRequest request;
request.set_subscription(
"projects/pubsub-cpp-api-1504713535863/subscriptions/testing");
request.set_max_messages(50);
request.set_return_immediately(false);
PullResponse response;
ClientContext ctx;
auto status = stub->Pull(&ctx, request, &response);
if (!status.ok()) {
// ...
}
// Do something with "response".
}
As a last resort, you could use a Push subscription, which would only require you to implement an HTTP endpoint on your client. However, this is not usually recommended unless you are fanning in from multiple subscriptions, or for cases where your client cannot make outgoing requests.

There is c++ library called pubsuber for accessing google pubsub.
For more information look here.

Related

How do you read/log gRPC HTTP headers (not custom metadata)?

I am working with gRPC and Protobuf, using a C++ server and a C++ client, as well as a grpc-js client. Is there a way to get a read on all of the HTTP request/response headers from the transport layer in gRPC? I am looking for the sort of typical client/server HTTP headers - particularly, I would like to see what version of the protocol is being used (whether it is HTTP1.1/2). I know that gRPC is supposed to be using HTTP2, but I am trying to confirm it at a low level.
In a typical gRPC client implementation you have something like this:
class PingPongClient {
public:
PingPongClient(std::shared_ptr<Channel> channel)
: stub_(PingPong::NewStub(channel)) {}
// Assembles the client's payload, sends it and presents the response back
// from the server.
PingPongReply PingPong(PingPongRequest request) {
// Container for the data we expect from the server.
PingPongReply reply;
// Context for the client. It could be used to convey extra information to
// the server and/or tweak certain RPC behaviors.
ClientContext context;
// The actual RPC.
Status status = stub_->Ping(&context, request, &reply);
// Act upon its status.
if (status.ok()) {
return reply;
} else {
auto errorMsg = status.error_code() + ": " + status.error_message();
std::cout << errorMsg << std::endl;
throw std::runtime_error(errorMsg);
}
}
private:
std::unique_ptr<PingPong::Stub> stub_;
};
and on the serverside, something like:
class PingPongServiceImpl final : public PingPong::Service {
Status Ping(
ServerContext* context,
const PingPongRequest* request,
PingPongReply* reply
) override {
std::cout << "PingPong" << std::endl;
printContextClientMetadata(context->client_metadata());
if (request->input_msg() == "hello") {
reply->set_output_msg("world");
} else {
reply->set_output_msg("I can't pong unless you ping me 'hello'!");
}
std::cout << "Replying with " << reply->output_msg() << std::endl;
return Status::OK;
}
};
I would think that either ServerContext or the request object might have access to this information, but context seems to only provide an interface into metadata, which is custom.
None of the gRPC C++ examples give any indication that there is such an API, nor do any of the associated source/header files in the gRPC source code. I have exhausted my options here in terms of tutorials, blog posts, videos, and documentation - I asked a similar question on the grpc-io forum, but have gotten no takers. Hoping the SO crew has some insights here!
I should also note that I experimented with passing a variety of environment variables as flags to the running processes to see if I can get details about HTTP headers, but even with these flags enabled (the HTTP-related ones), I do not see basic HTTP headers.
First, the gRPC libraries absolutely do use HTTP/2. The protocol is explicitly defined in terms of HTTP/2.
The gRPC libraries do not directly expose the raw HTTP headers to the application. However, they do have trace logging options that can log a variety of information for debugging purposes, including headers. The tracers can be enabled by setting the environment variable GRPC_TRACE. The environment variable GRPC_VERBOSITY=DEBUG should also be set to make sure that all of the logs are output. More information can be found in this document describing how the library uses envinronment variables.
In the C++ library, the http tracer should log the raw headers. The grpc-js library has different internals and different tracer definitions, so you should use the call_stream tracer for that one. Those will also log other request information, but it should be pretty easy to pick out the headers.

Cancelling an upload task

I've done some reading regarding the Azure SDK and in order to cancel a task you seemingly need to pass in a cancellation_token.
My upload code is very simple:
azure::storage::cloud_block_blob blockBlob = container.get_block_blob_reference(fileLeaf.wstring());
auto task = blockBlob.upload_from_file_async(fullFilePath);
However, some files I upload are potentially very large, and I would like to be able to cancel this operation. I'll probably also likely use continuations and would need all those cancelling too, if that's possible.
The problem I'm having is I can't see any way of attaching a cancellation_token to the task.
Any pointers?
There is a sample code using PPL library, I refered to it and changed the code for canceling task using PPLX library within C++ REST SDK which be used for Azure Storage SDK for C++, please try the code below.
/* Declare a cancellation_token_source and get the cancellation_token,
* please see http://microsoft.github.io/cpprestsdk/classpplx_1_1cancellation__token__source.html
*/
#include <pplxtasks.h>
cancellation_token_source cts;
auto token = cts.get_token();
//Pass the cancellation_toke to task via then method, please see https://msdn.microsoft.com/en-us/library/jj987787.aspx
task.then([]{}, token).wait();
// Cancel the task
cts.cancel();
Hope it helps.

c++ send request to API on webserver then receive json array response?

I'm wondering the most simple way to send a request to a API on my server then receive the API's response (json array) wihtout using any libraries. I've tried using libs like cURL & boost without any luck which is the reason i want to stay away from them. I've searched for many days for a answer and have not been able to find anything, which is why i've resorted to coming to the stack overflow community!
Even though the question is about not using a library I 'am taking this opportunity to show how easy it is to use a library than the user thinks.
Its better to use pre-built libraries and stop reinventing the wheel. You can use curlcpp library. Its a wrapper for libcurl. Using this library HTTP requests can be made easily. Learning curve is also less and it provides C++ style access which makes it more comfortable to work with.
The following code is taken from their gitHub page - https://github.com/JosephP91/curlcpp
It makes a simple GET request to Google and retrieves the HTML response. You can use this example to hit apis too.
#include "curl_easy.h"
#include "curl_exception.h"
using curl::curl_easy;
using curl::curl_easy_exception;
using curl::curlcpp_traceback;
int main(int argc, const char **argv) {
curl_easy easy;
// Add some option to the curl_easy object.
easy.add<CURLOPT_URL>("http://www.google.it");
easy.add<CURLOPT_FOLLOWLOCATION>(1L);
try {
// Execute the request.
easy.perform();
} catch (curl_easy_exception error) {
// If you want to get the entire error stack we can do:
curlcpp_traceback errors = error.get_traceback();
// Otherwise we could print the stack like this:
error.print_traceback();
// Note that the printing the stack will erase it
}
return 0;
}

how to add proxy support to boost::asio?

In my desktop application I added access to various internet resources using boost::asio. All i do is sending http requests (i.e to map tile servers) and read the results.
My code is based on the asio sync_client sample.
Now i get reports from customers who are unable to use these functions as they are running a proxy in their company. In a web browser they can enter the address of their proxy and everything is fine. Our application is unable to download data.
How can i add such support to my application?
I found the answer myself. It's quite simple:
http://www.jmarshall.com/easy/http/#proxies
gives quite a brief and clear description how http proxies work.
All i had to do is add the following code to the asio sync_client sample sample :
std::string myProxyServer = ...;
int myProxyPort = ...;
void doDownLoad(const std::string &in_server, const std::string &in_path, std::ostream &outstream)
{
std::string server = in_server;
std::string path = in_path;
char serice_port[255];
strcpy(serice_port, "http");
if(! myProxyServer.empty())
{
path = "http://" + in_server + in_path;
server = myProxyServer;
if(myProxyPort != 0)
sprintf(serice_port, "%d", myProxyPort);
}
tcp::resolver resolver(io_service);
tcp::resolver::query query(server, serice_port);
...
It seems that sample is merely a show-off of what Boost ASIO can be used for but is likely not intended to be used as-is. You should probably use a complete library that handles not only HTTP proxies, but also HTTP redirects, compression, and so on.
HTTP is a complex thing: without doing so, chances are high that you will get news from another client soon with another problem.
I found cppnetlib which looks promising and is based on Boost ASIO not sure it handles proxies though.
There is also libcurl but I don't know if it can easily be integrated with Boost ASIO.

Simple C/C++ network I/O library

I have the following problem to solve. I want to make a number of requests to a number of "remote" servers (actually, a server farm we control). The connection is very simple. Send a line, and then read lines back. Because of the number of requests and the number of servers, I use pthreads, one for each request.
The naive approach, using blocking sockets, does not work; very occasionally, I'll have a thread stuck in 'connect'. I cannot use SIGALRM because I am using pthreads. I tried converting the code to O_NONBLOCK but this vastly complicated the code to read single lines.
What are my options? I'm looking for the simplest solution that allows the following pseudocode:
// Inside a pthread
try {
req = connect(host, port);
req.writeln("request command");
while (line = req.readline()) {
// Process line
}
} catch TimeoutError {
// Bitch and complain
}
My code is in C++ and I'm using Boost. A quick look at Boost ASIO shows me that it probably isn't the correct approach, but I could be wrong. ACE is far, far too heavy-weight to solve this problem.
Have you looked at libevent?
http://www.monkey.org/~provos/libevent/
It's totally different paradigm but the performance is so amazing.
memcached is built on top of libevent.
I saw the comments and i think you can use boost::asio with boost::asio::deadline_timer
Fragment of a code:
void restart_timer()
{
timer_.cancel();
timer_.expires_from_now(boost::posix_time::seconds(5));
timer_.async_wait(boost::bind(&handleTimeout,
MyClass::shared_from_this(), boost::asio::placeholders::error));
}
Where handleTimeout is a callback function, timer_ is boost::asio::deadline_timer
and MyClass is similar to
class Y: public enable_shared_from_this<Y>
{
public:
shared_ptr<Y> f()
{
return shared_from_this();
}
}
You can call restart_timer before connect ou read/write
More information about share_from_this()
You mentioned this happens 'very occasionally'. Your 'connect' side should have the fault tolerance and error handling you are looking for but you should also consider the stability of your servers, DNS, network connections, etc.
The underlying protocols are very sturdy and work very well, so if you are experiencing these kind of problems that often then it might be worth checking.
You may also be able close the socket from the other thread. That should cause the connect to fail.