G-Research / consuldotnet

Consul.NET is a .NET client library for the Consul HTTP API
https://consuldot.net/
Apache License 2.0
322 stars 85 forks source link

Event when a KV value changes #37

Open arpontes opened 3 years ago

arpontes commented 3 years ago

Hello,

I'm using consuldotnet for a long time, but when I need to check if a value changes, I need to do it on my own. I think would be nice if this lib could do a check every X minutes for a change in the value and then fire and event with the new value.

I could implement this funcionality and send an PR, if you approve such feature.

mfkl commented 3 years ago

Hi,

Not sure that's in scope with consuldotnet, but maybe. Could you share a snippet of the solution you are currently using please?

I'm using consuldotnet for a long time, but when I need to check if a value changes, I need to do it on my own.

Do you use consul watch for this or your own code?

If you suggest custom code for this, then users will probably ask next for a HTTP retry/error handling mechanisms, internet connection check, etc. I'm not sure this is in scope with this project, but let's see what others say.

Relevant:

lucascebertin commented 3 years ago

Well, just trying to compare consul utilization across some languages and nodejs lib brings a watch functionality. https://github.com/silas/node-consul#watch

Snippet:

import consulFn from 'consul'

const consul = consulFn()
const watch = consul.watch({
  method: consul.kv.get,
  options: { key: 'test' },
  backoffFactor: 1000,
});

watch.on('change', function(data, res) {
  console.log('data:', data);
});

watch.on('error', function(err) {
  console.log('error:', err);
});

setTimeout(function() { watch.end(); }, 30 * 1000);

@arpontes, any chance to this being related? Could you share how you do that in dotnet today?

Thanks

marcin-krystianc commented 2 years ago

Consul supports blocking HTTP queries, so it is entirely possible to watch for value changes in a very efficient fashion. When the watched value changes, the HTTP call returns instantaneously - see a simplified example implementation.:

var lastIndex = 0ul;
do
{
  var res = await _client.KV.Get("foo", new QueryOptions { WaitIndex = lastIndex });
  // TODO - value of "foo" has changed
} while(true);

As mfkl has already mentioned, the tricky bit is exposing in the API a configurable error handling and retrying policy.

chester89 commented 1 year ago

I'd like watch functionality for service instances. Will the trick similar to KV work? e.g. var result = await consulClient.Health.Service("serviceName", "tagName", true, new QueryOptions { WaitIndex = 0ul }, cancellationToken); //further processing

marcin-krystianc commented 1 year ago

I'd like watch functionality for service instances. Will the trick similar to KV work? e.g. var result = await consulClient.Health.Service("serviceName", "tagName", true, new QueryOptions { WaitIndex = 0ul }, cancellationToken); //further processing

Yes, I think it will work. Mind, that WaitIndex need to be set to the value from the previous query result.