danielwertheim

danielwertheim


notes from a passionate developer

Share


Sections


Tags


Disclaimer

This is a personal blog. The opinions expressed here represent my own and not those of my employer, nor current or previous. All content is published "as is", without warranty of any kind and I don't take any responsibility and can't be liable for any claims, damages or other liabilities that might be caused by the content.

Using C# and HttpClient to consume continuously streamed results from CouchDB

In CouchDb there’s a way to subscribe to all changes that occur in a certain database. You can consume it in various ways: polling | long polling | continuous | event source (read more here). This post will show you how-to consume the continuous feed.

No matter which subscription you want, it’s a simple GET that should be performed. Using Curl it would be as easy as this:

curl -GET "http://localhost:5984/dbname/_changes?feed=normal
curl -GET "http://localhost:5984/dbname/_changes?feed=longpolling
curl -GET "http://localhost:5984/dbname/_changes?feed=continuous
curl -GET "http://localhost:5984/dbname/_changes?feed=eventsource

Before looking at it in C#, lets cover yet another parameter that you can pass via the querystring: heartbeat. The value is specified in milliseconds and will cause CouchDb to respond with a newline at every tick. That way, you know it’s alive.

Now lets have a quick look at one way to accomplish this in C#. I’m just going to show you a simple way, and will not include any exception handling etc.

var url = "http://localhost:5984/fiddles/_changes?feed=continuous&heartbeat=1000";

using (var client = new HttpClient())
{
    client.Timeout = TimeSpan.FromMilliseconds(Timeout.Infinite);

    var request = new HttpRequestMessage(HttpMethod.Get, url);
    using (var response = await client.SendAsync(
        request, 
        HttpCompletionOption.ResponseHeadersRead))
    {
        using (var body = await response.Content.ReadAsStreamAsync())
        using (var reader = new StreamReader(body))
            while (!reader.EndOfStream)
                Console.WriteLine(reader.ReadLine());
    }
}

There’s one really important configuration of the call, and that is to use the overload of SendAsync and specify HttpCompletionOption.ResponseHeadersRead. Without it, it would hang on getting the response, and eventually be timing out.

Another important thing, is to configure the timeout. If not, well, your request will timeout, even though you are getting heartbeat data. So this line is really important:

client.Timeout = TimeSpan.FromMilliseconds(Timeout.Infinite);

That’s it. Simple, sweet and effective. More follow ups on use-cases of the Changes API will come and it will soon be part of the client library MyCouch.

Cheers,

//Daniel

View Comments