Git Product home page Git Product logo

etcd4j's People

Contributors

althink avatar bramk avatar burakdede avatar ctrimble avatar dgutierrez-stratio avatar ffdybuster avatar hardbyte avatar jaceklach avatar johneke avatar jurmous avatar lburgazzoli avatar oscerd avatar q-fabianmurariu avatar shiroari avatar timgesekus avatar zlooo27 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

etcd4j's Issues

Exception on simple put request

Sorry for posting this here but i have the following problem.
I create single get request.

   try{

      EtcdClient client = new EtcdClient(URI.create("http://x.x.x.x:4012"));
      EtcdKeysResponse response = client.put("foo", "bar").send().get();

      // Prints out: bar
      System.out.println(response.node.value);
    }catch(EtcdException e){
      // Do something with the exception returned by etcd
    }catch(IOException e){
      // Exception happened in the retrieval. Do something with it.
    }catch(TimeoutException e){
      // Timeout happened. Do something
    }

and there is a thrown exception

WARNING: An exception was thrown by ousio.etcd4j.transport.EtcdNettyClient$3.operationComplete()
java.io.IOException:io.netty.handler.codec.http.multipart.HttpPostRequestEncoder$ErrorDataEncoderException: Cannot create a Encoder if not a POST
at mousio.etcd4j.transport.EtcdNettyClient.createHttpRequest(EtcdNettyClient.java:276)
at mousio.etcd4j.transport.EtcdNettyClient$3.operationComplete(EtcdNettyClient.java:198)
at mousio.etcd4j.transport.EtcdNettyClient$3.operationComplete(EtcdNettyClient.java:159)
at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:680)
at io.netty.util.concurrent.DefaultPromise.notifyListeners0(DefaultPromise.java:603)
at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:563)
at io.netty.util.concurrent.DefaultPromise.trySuccess(DefaultPromise.java:406)
at io.netty.channel.DefaultChannelPromise.trySuccess(DefaultChannelPromise.java:82)
at >io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.fulfillConnectPromise(AbstractNioChannel.java:247)
at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:282)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:528)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:468)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:382)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354)
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116)
at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
at java.lang.Thread.run(Thread.java:744)

WARN log message for all redirect

Hi there,

Seems etcd4j logs a WARN message for each redirect. This results in excessive log messages in clustering environment. It is not really a warning situation.

Here is the message:
Jan 05 2015 15:34:41.339 [nioEventLoopGroup-6-6] [EtcdKeyResponseHandler.java:82] WARN m.e.t.EtcdKeyResponseHandler - redirect for /v2/keys/test to http://127.0.0.1:4004/v2/keys/test

Can you please change the log level to DEBUG or no log at all for this?

Thanks,

Ken

EtcdException to have constructor accepting string value

For example I want to throw custom EtcdException and I can't. Other reason is that i handle IOException, TimeoutException and I want to throw new EtcdException with custom error message. Thus where I use the method which uses the client I will have to handle only single EtcdException, not all of them.

What do you think about that guys?

Retry handler is invoked only when a connection failed

I use aggressive timeouts when querying ETCD. It often results to timeout exception.
Etcdj4 uses nice system of retry handlers.

However, according to https://github.com/jurmous/etcd4j/blob/master/src/main/java/mousio/etcd4j/transport/EtcdNettyClient.java#L167 it seems that some retry policy is performed only when promise does not succeed. Log entry in the condition says that this happen only when connection failed.

I'd appreciate to use retry handler even for timeout exception. In general, we can say that there are certain conditions when it makes sense to retry but there are also conditions when it does not make a sense to do retry. Depends on a use-case.

From my point of PUT view, I will do retries in case of timeout exception until some counter exceeds or until ETCD results precondition fails - which means that the code changes the value in ETCD but the request was timeout on client side - in fact, it succeeded but after my timeout.

This sounds exactly like an implementation of already implemented handler(s) but placed on request execution itself, not only on connection.

Support for SRV records

Etcd allows to bootstrap over SRV records and tools such as confd supports reading them. Would be nice if etcd4j could read them. This is the code that I am using the bootstrap etcd4j using SRV records (I can make a PR if you want to).
https://github.com/coreos/etcd/blob/master/Documentation/clustering.md#dns-discovery
Does this sound like a good idea?

private URI[] getUris(String service) throws NamingException {
    List<URI> uris = new ArrayList<>();
    String srvService = "_etcd._tcp." + service;
    Hashtable<String, String> env = new Hashtable<>();
    env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory");
    env.put("java.naming.provider.url", "dns:");
    DirContext ctx = new InitialDirContext(env);
    Attributes attributes = ctx.getAttributes(srvService, new String[]{"SRV"});
    NamingEnumeration<? extends Attribute> records = attributes.getAll();
    while (records.hasMore()) {
        Attribute next = records.next();
        NamingEnumeration<String> values = (NamingEnumeration<String>) next.getAll();
        while (values.hasMore()) {
            String dns = values.next();
            String[] split = dns.split(" ");
            String port = split[2];
            String host = split[3];
            URI uri = URI.create("http://" + host + ":" + port);
            uris.add(uri);
        }
    }
    return uris.toArray(new URI[0]);
}

put with space in value fails

Hi,

I noticed that put request with a space in the value return a 400 "bad request". PR follows...

Greetings and happy holidays :)

Request parameters are not exposed

I want to use etcd4j along with etcd 2.3, released this week it looks like. There is now the option of using the 'refresh=true' parameter so that updating ttl will not trigger a watch. I need a way to use this parameter via etcd4j, and it seems like exposing the parameters to pass along to etcd would be useful. Something like
EtcdKeyRequest.addParam(String param, String value);
Alternatively, updating the api to be compatible with the 2.3 changes would also work. Being able to do

put(key, value).ttl(5).refresh(true).prevExists(true);

Currently it looks like the value param is added on for all put calls, that would have to be changed as well (refresh does not support updating value as well, it just updates ttl).

Are there any plans for adding this? thanks. Z

double files in 0.4.9 jar

Hi,

we just noticed that the released etcd4j-0.4.9.jar contains the client classes twice, with different file dates. I can not reproduce building such a file with "gradle jar", I think a gradle clean should fix this problem...?

Greetings, Marc

$ unzip -l etcd4j-0.4.9.jar
Archive: etcd4j-0.4.9.jar
Length Date Time Name


    0  10-07-14 13:45   META-INF/
   25  10-07-14 13:45   META-INF/MANIFEST.MF
    0  10-07-14 13:34   mousio/
    0  10-07-14 13:34   mousio/client/
  453  10-07-14 13:34   mousio/client/ConnectionState.class
    0  10-07-14 13:34   mousio/client/exceptions/
  426  10-07-14 13:34   mousio/client/exceptions/PrematureDisconnectException.class
    0  10-07-14 13:34   mousio/client/promises/
 1541  10-07-14 13:34   mousio/client/promises/ResponsePromise$1.class
  912  10-07-14 13:34   mousio/client/promises/ResponsePromise$2.class
  462  10-07-14 13:34   mousio/client/promises/ResponsePromise$IsSimplePromiseResponseHandler.class
 6025  10-07-14 13:34   mousio/client/promises/ResponsePromise.class
    0  10-07-14 13:34   mousio/client/retry/
  195  10-07-14 13:34   mousio/client/retry/ConnectionFailHandler.class
  197  10-07-14 13:34   mousio/client/retry/RetryHandler.class
  680  10-07-14 13:34   mousio/client/retry/RetryNTimes.class
  613  10-07-14 13:34   mousio/client/retry/RetryOnce.class
 1242  10-07-14 13:34   mousio/client/retry/RetryPolicy$1.class
 2336  10-07-14 13:34   mousio/client/retry/RetryPolicy.class
 1151  10-07-14 13:34   mousio/client/retry/RetryWithExponentialBackOff.class
  911  10-07-14 13:34   mousio/client/retry/RetryWithTimeout.class
    0  10-07-14 13:35   mousio/etcd4j/
 3795  10-07-14 13:35   mousio/etcd4j/EtcdClient.class
    0  10-07-14 13:35   mousio/etcd4j/promises/
 1478  10-07-14 13:35   mousio/etcd4j/promises/EtcdResponsePromise.class
    0  10-07-14 13:35   mousio/etcd4j/requests/
 2773  10-07-14 13:35   mousio/etcd4j/requests/EtcdKeyDeleteRequest.class
 3085  10-07-14 13:35   mousio/etcd4j/requests/EtcdKeyGetRequest.class
 2685  10-07-14 13:35   mousio/etcd4j/requests/EtcdKeyPostRequest.class
 3229  10-07-14 13:35   mousio/etcd4j/requests/EtcdKeyPutRequest.class
 2388  10-07-14 13:35   mousio/etcd4j/requests/EtcdKeyRequest.class
 3450  10-07-14 13:35   mousio/etcd4j/requests/EtcdRequest.class
 1716  10-07-14 13:35   mousio/etcd4j/requests/EtcdVersionRequest.class
    0  10-07-14 13:35   mousio/etcd4j/responses/
 1310  10-07-14 13:35   mousio/etcd4j/responses/EtcdException.class
 1386  10-07-14 13:35   mousio/etcd4j/responses/EtcdKeyAction.class
  762  10-07-14 13:35   mousio/etcd4j/responses/EtcdKeysResponse$EtcdNode.class
  890  10-07-14 13:35   mousio/etcd4j/responses/EtcdKeysResponse.class
 6576  10-07-14 13:35   mousio/etcd4j/responses/EtcdKeysResponseParser.class
    0  10-07-14 13:35   mousio/etcd4j/transport/
  465  10-07-14 13:35   mousio/etcd4j/transport/EtcdClientImpl.class
 4868  10-07-14 13:35   mousio/etcd4j/transport/EtcdKeyResponseHandler.class
 2117  10-07-14 13:35   mousio/etcd4j/transport/EtcdNettyClient$1.class
 1142  10-07-14 13:35   mousio/etcd4j/transport/EtcdNettyClient$2.class
 3029  10-07-14 13:35   mousio/etcd4j/transport/EtcdNettyClient$3.class
 2114  10-07-14 13:35   mousio/etcd4j/transport/EtcdNettyClient$4.class
 1440  10-07-14 13:35   mousio/etcd4j/transport/EtcdNettyClient$5.class
11217  10-07-14 13:35   mousio/etcd4j/transport/EtcdNettyClient.class
  453  10-02-14 11:27   mousio/client/ConnectionState.class
  426  10-02-14 11:27   mousio/client/exceptions/PrematureDisconnectException.class
 1541  10-02-14 11:27   mousio/client/promises/ResponsePromise$1.class
  912  10-02-14 11:27   mousio/client/promises/ResponsePromise$2.class
  462  10-02-14 11:27   mousio/client/promises/ResponsePromise$IsSimplePromiseResponseHandler.class
 6025  10-02-14 11:27   mousio/client/promises/ResponsePromise.class
  195  10-02-14 11:27   mousio/client/retry/ConnectionFailHandler.class
  197  10-02-14 11:27   mousio/client/retry/RetryHandler.class
  680  10-02-14 11:27   mousio/client/retry/RetryNTimes.class
  613  10-02-14 11:27   mousio/client/retry/RetryOnce.class
 1242  10-02-14 11:27   mousio/client/retry/RetryPolicy$1.class
 2336  10-02-14 11:27   mousio/client/retry/RetryPolicy.class
 1151  10-02-14 11:27   mousio/client/retry/RetryWithExponentialBackOff.class
  911  10-02-14 11:27   mousio/client/retry/RetryWithTimeout.class

96228                   62 files

Java 7 support

Hi,

we would like to use your etcd4j client, but can not switch to Java 8 for our project yet. I had a look at what Java 8 features are used, and it seems it's very little until now. I already changed the code to make it Java 7 compatible, please have a look at https://github.com/slintes/etcd4j/commit/415371143cf4fe026d0110d40add338ca7ecb116

What do you think about keeping your client Java 7 compatible? If you like the idea, I would like to create a pull request.

Kind regards,

Marc

Jackson Object Mapper

Hi @jurmous ,

as the number of decoders is growing and write them is just a very manual task, would you mind if I switch to Jackson Object Mapper ? I know we already had this discussion but now that the messages we support is growing I think the advantages outcome the small issues it adds (dependencies, maybe slower parsing)

Large values are not handled

If a large value is stored etcd4j does not handle it correctly. By large I mean value grater than 8096 which causes io.netty.handler.codec.http.multipart.HttpPostRequestEncoder to create a chunked request. If that happens request without a body is sent to etcd and operation never completes.

What's the proper way to chain waitForChange()s?

Hi,

I'm playing with etcd4j using a sample piece of code below. What I'm seeing, and what I am unable to fix, is the onResponse handler being invoked twice for each change of /mykey. Each invocation of the handler seems to happen on a different thread.

I guess it must be related to invoking waitForChange() from inside the handler itself? What's the proper way to do it?

package testpackage;

import mousio.client.promises.ResponsePromise;
import mousio.etcd4j.EtcdClient;
import mousio.etcd4j.promises.EtcdResponsePromise;
import mousio.etcd4j.responses.EtcdAuthenticationException;
import mousio.etcd4j.responses.EtcdException;
import mousio.etcd4j.responses.EtcdKeysResponse;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.concurrent.TimeoutException;

public class Main {
    public static void main(String[] args) throws URISyntaxException, IOException, EtcdAuthenticationException, TimeoutException, EtcdException, InterruptedException {
        EtcdClient client = new EtcdClient(new URI("https://localhost:2379"));

        EtcdResponsePromise promise = client.get("/mykey").waitForChange().send();
        promise.addListener(new ResponsePromise.IsSimplePromiseResponseHandler() {
            @Override
            public void onResponse(ResponsePromise responsePromise) {
                try {
                    EtcdKeysResponse response = (EtcdKeysResponse) responsePromise.get();
                    System.out.println("Waited for: " + response.node.value);
                    EtcdResponsePromise next = client.get("/mykey").waitForChange(response.etcdIndex + 1).send();
                    next.addListener(this);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        while(true) {
            Thread.sleep(1000);
        }
    }
}

Include Netty dependency in main pom

Because the netty dependency is attached to the client artifact and gradle maven plugin by default does not include dependencies of the extra artifacts in the generated pom, the Netty dependencies are missing from the pom.

Adapt the gradle build file so it includes the Netty Dependencies.

IllegalStateException warning on every get request

NOTE: Please disregard/delete -- we're using etcd 0.3.0

I'm attempting a simple get as folllows:

EtcdResponsePromise promise = client.get("/my/existing/key").send();

This always results in the message below. It's just a WARNING, so I then try to subsequently read out the promise in a blocking? manner

promise.getNow().node.value

and I will get null, even though the key exists, unless I set breakpoint and wait. This leads me to believe that "getNow()" is asynchronous, but when I do same in a listener, it never fires. Perhaps I'm using this incorrectly?

Sep 25, 2014 3:36:01 PM io.netty.channel.DefaultChannelPipeline$TailContext exceptionCaught
WARNING: An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
java.lang.IllegalStateException: complete already: DefaultPromise@3d3c76be(failure(java.util.concurrent.CancellationException)
at io.netty.util.concurrent.DefaultPromise.setFailure(DefaultPromise.java:418)
at mousio.etcd4j.transport.EtcdKeyResponseHandler.channelRead0(EtcdKeyResponseHandler.java:60)
at mousio.etcd4j.transport.EtcdKeyResponseHandler.channelRead0(EtcdKeyResponseHandler.java:15)
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105)
at io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:83)
at io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:153)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:182)
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
at io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:83)
at io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:153)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:182)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:163)
at io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:83)
at io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:153)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:182)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:886)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:126)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:510)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:467)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:381)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:353)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:834)
at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalStateException: complete already: DefaultPromise@3d3c76be(failure(java.util.concurrent.CancellationException)
at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:400)
at mousio.etcd4j.transport.EtcdKeyResponseHandler.channelRead0(EtcdKeyResponseHandler.java:54)
... 22 more

How can I get etcd stats using etcd4j

Hi @jurmous, Im sorry if this is the wrong place for this but I didnt find a room on gitter.

Is it possible to perform GET requests on non /v2/keys keys? I need to GET /v2/stats/self and I cant seem to figure out how to do that with etcd4j

I'd appreciate any pointers. Thanks a lot!

Asking for an outdated key produces an obscure exception

A response like this:

HTTP/1.1 400 Bad Request
Content-Type: application/json
X-Etcd-Cluster-Id: 7e27652122e8b2ae
X-Etcd-Index: 4429
Date: Tue, 05 Apr 2016 12:29:04 GMT
Content-Length: 154

{"errorCode":401,"message":"The event in requested index is outdated and cleared","cause":"the requested history has been cleared [3430/5]","index":4429}

Causes an obscure exception like the one to be thrown:

com.fasterxml.jackson.databind.JsonMappingException: Instantiation of [simple type, class mousio.etcd4j.responses.EtcdKeysResponse] value failed: Name is null
    at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.wrapException(StdValueInstantiator.java:399) ~[jackson-databind-2.6.5.jar:2.6.5]
    at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromObjectWith(StdValueInstantiator.java:231) ~[jackson-databind-2.6.5.jar:2.6.5]
    at com.fasterxml.jackson.databind.deser.impl.PropertyBasedCreator.build(PropertyBasedCreator.java:135) ~[jackson-databind-2.6.5.jar:2.6.5]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:442) ~[jackson-databind-2.6.5.jar:2.6.5]
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1099) ~[jackson-databind-2.6.5.jar:2.6.5]
    at com.fasterxml.jackson.module.afterburner.deser.SuperSonicBeanDeserializer.deserializeFromObject(SuperSonicBeanDeserializer.java:236) ~[jackson-module-afterburner-2.7.0.jar:2.7.0]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:133) ~[jackson-databind-2.6.5.jar:2.6.5]
    at com.fasterxml.jackson.module.afterburner.deser.SuperSonicBeanDeserializer.deserialize(SuperSonicBeanDeserializer.java:117) ~[jackson-module-afterburner-2.7.0.jar:2.7.0]
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3736) ~[jackson-databind-2.6.5.jar:2.6.5]
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2796) ~[jackson-databind-2.6.5.jar:2.6.5]
    at mousio.etcd4j.responses.EtcdResponseDecoders$JsonDecoder.decode(EtcdResponseDecoders.java:54) ~[etcd4j-2.10.0.jar:2.10.0]
    at mousio.etcd4j.transport.EtcdResponseHandler.channelRead0(EtcdResponseHandler.java:139) [etcd4j-2.10.0.jar:2.10.0]
    at mousio.etcd4j.transport.EtcdResponseHandler.channelRead0(EtcdResponseHandler.java:47) [etcd4j-2.10.0.jar:2.10.0]
    at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:83) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:154) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:439) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:162) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103) [netty-codec-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:83) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:154) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:439) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:162) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:83) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:154) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:439) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:162) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:433) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:276) [netty-codec-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:263) [netty-codec-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:243) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:83) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:154) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:439) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:162) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.handler.timeout.ReadTimeoutHandler.channelRead(ReadTimeoutHandler.java:152) [netty-handler-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:83) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:154) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:439) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:162) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:924) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:125) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:510) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:467) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:381) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:353) [netty-transport-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:742) [netty-common-4.1.0.CR2.jar:4.1.0.CR2]
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137) [netty-common-4.1.0.CR2.jar:4.1.0.CR2]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_71]
Caused by: java.lang.NullPointerException: Name is null
    at java.lang.Enum.valueOf(Enum.java:236) ~[na:1.8.0_71]
    at mousio.etcd4j.responses.EtcdKeyAction.valueOf(EtcdKeyAction.java:6) ~[etcd4j-2.10.0.jar:2.10.0]
    at mousio.etcd4j.responses.EtcdKeysResponse.<init>(EtcdKeysResponse.java:62) ~[etcd4j-2.10.0.jar:2.10.0]
    at sun.reflect.GeneratedConstructorAccessor42.newInstance(Unknown Source) ~[na:na]
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_71]
    at java.lang.reflect.Constructor.newInstance(Constructor.java:422) ~[na:1.8.0_71]
    at com.fasterxml.jackson.databind.introspect.AnnotatedConstructor.call(AnnotatedConstructor.java:125) ~[jackson-databind-2.6.5.jar:2.6.5]
    at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromObjectWith(StdValueInstantiator.java:227) ~[jackson-databind-2.6.5.jar:2.6.5]
    ... 48 common frames omitted

Default retry handler causes infinite loop

I use default retry handler RetryWithExponentialBackOff using -1 as maxRetryCount. Unfortunately this specific setting results into infinite loop as method RetryWithExponentialBackOff.shouldRetry returns always true in the case of maxRetryCount=-1 - first condition is always skipped.

Note that I used following statement to create the policy:

new RetryWithExponentialBackOff(20, -1, 1000)

Support prevExist=false

Hi there,

Currently prevExist() in EtcdKeyPutRequest can only set prevExist =true. While in certain situations, we would like to have prevExist=false as the condition to set up etcd key. Can you please extend the api to support?

public EtcdKeyPutRequest prevExist() {
this.requestParams.put("prevExist", "true");
return this;
}

Make Host name configurable

The Host name reported by the etcd client should be the cname of the web app. Since Netty gathers the information from resolving the ip with /etc/hosts it should be possible to configure the value if the user wants it to be different.

Accessing through Nginx

I have an etcd instance running which is exposed via an nginx reverse-proxy. When I used your client it was failing with a 400 error. When I looked into it, the error reported by nginx was:
client sent HTTP/1.1 request without "Host" header while reading client request headers
I had a look through your code, and did a quick fix to set the host header - see below patch. This seems to have fixed it for me, so I thought you might want to consider incorporating the fix into your next release?

Patch:

diff --git a/src/main/java/mousio/etcd4j/transport/EtcdNettyClient.java b/src/main/java/mousio/etcd4j/transport/EtcdNettyClient.java
index 3c0ef14..0408b00 100644
--- a/src/main/java/mousio/etcd4j/transport/EtcdNettyClient.java
+++ b/src/main/java/mousio/etcd4j/transport/EtcdNettyClient.java
@@ -24,6 +24,7 @@
 import org.slf4j.LoggerFactory;

 import java.io.IOException;
+import java.net.InetAddress;
 import java.net.URI;
 import java.nio.charset.Charset;
 import java.util.Date;
@@ -258,6 +259,7 @@
   public static <R> HttpRequest createHttpRequest(String uri, EtcdRequest<R> etcdRequest) throws IOException {
     HttpRequest httpRequest = new DefaultHttpRequest(HttpVersion.HTTP_1_1, etcdRequest.getMethod(), uri);
     httpRequest.headers().add("Connection", "keep-alive");
+    httpRequest.headers().add("Host", InetAddress.getLocalHost().getHostName());    
     try {
       httpRequest = setRequestParameters(uri, etcdRequest, httpRequest);
     } catch (Exception e) {

ConnectionState.uriIndex can contain illegal values

While trying to upgrade from 2.7.0 to 2.9.0, I am seeing lots of ArrayIndexOutOfBoundsExceptions being thrown, relating to the uriIndex field of ConnectionState. The code in RetryPolicy is incrementing this field and then testing if the new value is valid. This seems to be causing other threads to use an illegal value when doing lookups in the uris array. Synchronizing access to the ConnectionState instance seems to resolve the issue.

EtcdNettyClient.close Issue

Hi guys:

When I use the custom method to construct a EtcdClient, I set my NettyEventLoopGroup to EtcdNettyConfig,But when I close EtcdClient, EtcdClient close my NettyEventLoopGroup also.

Maybe if EventLoopGroup is custom set (not the default one), EtcdClient should not close it?
Or have an option to control the behavior?

Thanks!

using Long instead of Integer for index

Hi,

I'm wondering if it would be better to use Long instead of Integer for createdIndex, modifiedIndex and etcdIndex in EtcdKeysResponse / EtcdNode. I think long running and heavily used etcd instances can reach very high values. Maybe Long makes also sense for ttl.

Greetings, Marc

etcd4j project layout

As today the project is structured as a single project even if it has two main component (source sets):

  • etcd4j-client
  • etcd4j

Then on maven central, there are two jars matching the source sets but:

  • etcd4j contains also the classes included in etcd4j-client
  • etcd4j-client is not resolvable via maven

So I'm thinking if it would be better to convert the project to a multi project or get rid of separate etcd4j-client source set and etcd4j-client jar on maven.

Anything that make sense for you ?

SocketException - can't assign requested address

I'm getting some SocketExceptions sporadically when developing on my Mac. I can pretty reliably reproduce the issue with the following test (was testing other properties, but ended up finding this fun one)

    @Test public void testSharedClient() throws Exception{
        EtcdClient client = new EtcdClient(
            URI.create("http://127.0.0.1:12379"),
            URI.create("http://127.0.0.1:22379"),
            URI.create("http://127.0.0.1:32379")
        );
        for (int i = 0; i < 10_000; i++) {
            Thread t = new Thread(() -> {
                try {
                    client.put("test", "test").ttl(3600).send().get();
                    client.get("test").send().get();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
            t.start();
            client.put("test-2", "test-2").ttl(3600).send().get();
            t.join();
        }
    }

It seems it may be related to IPv6 based on the literature I can find online for this error and it does seem to be resolved by adding the following system-property.

-Djava.net.preferIPv4Stack=true

Just thought this might be worth adding to the readme as a note / caveat / warning.

Host header default and proxies

Defaulting the Host header to the local interfaces host name may not be the best default. When connecting to Etcd behind a proxy, the host header needs to match the host being contacted, otherwise the proxy will fail.

A better default would be to extract the host from the url being connected to. This would allow proxies to work as expected.

getStoreStats is not working

When I execute etcdClient.getStoreStats() - thread hangs and nothing is returned. Other requests work fine. My setup: etcd4j-2.10.0, Java 1.8_45

Inconsistent behavior when handling various error states

This topic https://github.com/coreos/etcd/blob/master/Documentation/errorcode.md defines a set of possible error codes which can etcd server return to your request. The server returns both http status code and json body as well. The server does it even in error states.

On the other hand EtcdKeyResponseHandler parses only some http status codes into EtcdException body.

This means that when I send a request to get not existing key, the etcd client returns EtcdException with error code 101. Contrary to this behavior, when I send a request using prevExist=false and the request fails, a new Exception is thrown containing message "412 Precondition Failed". I need to parse the text using HttpResponseStatus.parseLine in this case to discover what happen.

I would suggest to throw an EtcdException with proper error code in all cases when possible.

Threads not closed when client is closed

I noticed that some threads are not closed with the ARM block. I didn't spend a lot of time figuring out where the threads are kept open, but I was able to write a very simple test and reproduce the issue on my Mac. You may need to adjust the loop counter to whatever your ulimit value is on your machine.

@Test public void testEtcdClientClosing() throws IOException {
    for (int i = 0; i < 10_000; i++) {
        try(EtcdClient client = new EtcdClient()) {
            client.put("test-" + i, "value-" + i).send();
            client.get("test-" + i).send();
        } // should close automatically
    }
}

Without fail this blows up with an OutOfMemoryError: unable to create new native thread.

redirect broken in head

While testing #15 I noticed that redirects are broken after rebasing on master (508040f). Reproducable without an etcd cluster if you remove the fix for leading slashes (#14) and use a key with leading slash. I get a CancellationException before the request ends successfully.

Log:
[nioEventLoopGroup-2-2] INFO mousio.etcd4j.transport.EtcdNettyClient - Connected to /172.17.8.20:4001
[nioEventLoopGroup-2-2] INFO mousio.etcd4j.transport.EtcdKeyResponseHandler - Received 301 for PUT /v2/keys//etcd4jTest
[nioEventLoopGroup-2-2] INFO mousio.etcd4j.transport.EtcdNettyClient - Connection closed for request PUT /v2/keys//etcd4jTest
[nioEventLoopGroup-2-2] WARN mousio.etcd4j.transport.EtcdKeyResponseHandler - redirect for /v2/keys//etcd4jTest?value=HelloFromEtcd4J to /v2/keys/etcd4jTest?value=HelloFromEtcd4J
[nioEventLoopGroup-2-3] INFO mousio.etcd4j.transport.EtcdNettyClient - Connected to /172.17.8.20:4001
java.io.IOException: java.util.concurrent.CancellationException
at mousio.etcd4j.promises.EtcdResponsePromise.get(EtcdResponsePromise.java:55)
at etcdTest.Etcd4JTest.main(Etcd4JTest.java:29)
Caused by: java.util.concurrent.CancellationException
[nioEventLoopGroup-2-3] INFO mousio.etcd4j.transport.EtcdKeyResponseHandler - Received 201 for PUT /v2/keys//etcd4jTest
[nioEventLoopGroup-2-3] INFO mousio.etcd4j.transport.EtcdNettyClient - Connection closed for request PUT /v2/keys//etcd4jTest

can not handler, errorcode 401

watch key wait for changing.When server return error code 401,etcd4j can not handler,
EtcdResponseHandler class should add

failureDecoders.put(HttpResponseStatus.BAD_REQUEST, EtcdException.DECODER);

constant timeout exception

Hi there,

I set the put timeout value to be 10 seconds, however, it always throws out an exception in 10 seconds no matter the write succeeded or not.

Below is the log, at 11.926 the write returns successfully, but still at 21.912 an exception happens. Can this exception be avoided? If it is a real exception, can it be thrown to application instead of printing trace underneath? Printing tracing can be very expensive.

Dec 31 2014 12:18:11.926 [main] [Etcd.java:272] DEBUG c.s.c.e.Etcd - Etcd putValue - key GroupId, value 123456, return 123456
Dec 31 2014 12:18:21.912 [nioEventLoopGroup-2-2] [Slf4JLogger.java:151] WARN i.n.c.DefaultChannelPipeline - An exception was thrown by a user handler's exceptionCaught() method:
java.lang.IllegalStateException: complete already: DefaultPromise@282e593e(incomplete)
at io.netty.util.concurrent.DefaultPromise.setFailure(DefaultPromise.java:418) ~[netty-common-4.1.0.Beta3.jar:4.1.0.Beta3]
at mousio.etcd4j.transport.EtcdNettyClient$5.exceptionCaught(EtcdNettyClient.java:233) ~[etcd4j-2.0.0.jar:na]
at io.netty.channel.ChannelHandlerInvokerUtil.invokeExceptionCaughtNow(ChannelHandlerInvokerUtil.java:64) [netty-transport-4.1.0.Beta3.jar:4.1.0.Beta3]
at io.netty.channel.DefaultChannelHandlerInvoker.invokeExceptionCaught(DefaultChannelHandlerInvoker.java:110) [netty-transport-4.1.0.Beta3.jar:4.1.0.Beta3]
at io.netty.channel.AbstractChannelHandlerContext.fireExceptionCaught(AbstractChannelHandlerContext.java:167) [netty-transport-4.1.0.Beta3.jar:4.1.0.Beta3]
at io.netty.channel.ChannelInboundHandlerAdapter.exceptionCaught(ChannelInboundHandlerAdapter.java:131) [netty-transport-4.1.0.Beta3.jar:4.1.0.Beta3]
at io.netty.channel.ChannelHandlerInvokerUtil.invokeExceptionCaughtNow(ChannelHandlerInvokerUtil.java:64) [netty-transport-4.1.0.Beta3.jar:4.1.0.Beta3]
at io.netty.channel.DefaultChannelHandlerInvoker.invokeExceptionCaught(DefaultChannelHandlerInvoker.java:110) [netty-transport-4.1.0.Beta3.jar:4.1.0.Beta3]
at io.netty.channel.AbstractChannelHandlerContext.fireExceptionCaught(AbstractChannelHandlerContext.java:167) [netty-transport-4.1.0.Beta3.jar:4.1.0.Beta3]
at io.netty.channel.ChannelInboundHandlerAdapter.exceptionCaught(ChannelInboundHandlerAdapter.java:131) [netty-transport-4.1.0.Beta3.jar:4.1.0.Beta3]
at io.netty.channel.ChannelHandlerInvokerUtil.invokeExceptionCaughtNow(ChannelHandlerInvokerUtil.java:64) [netty-transport-4.1.0.Beta3.jar:4.1.0.Beta3]
at io.netty.channel.DefaultChannelHandlerInvoker.invokeExceptionCaught(DefaultChannelHandlerInvoker.java:110) [netty-transport-4.1.0.Beta3.jar:4.1.0.Beta3]
at io.netty.channel.AbstractChannelHandlerContext.fireExceptionCaught(AbstractChannelHandlerContext.java:167) [netty-transport-4.1.0.Beta3.jar:4.1.0.Beta3]
at io.netty.channel.ChannelHandlerAdapter.exceptionCaught(ChannelHandlerAdapter.java:79) [netty-transport-4.1.0.Beta3.jar:4.1.0.Beta3]
at io.netty.channel.ChannelHandlerInvokerUtil.invokeExceptionCaughtNow(ChannelHandlerInvokerUtil.java:64) [netty-transport-4.1.0.Beta3.jar:4.1.0.Beta3]
at io.netty.channel.DefaultChannelHandlerInvoker.invokeExceptionCaught(DefaultChannelHandlerInvoker.java:110) [netty-transport-4.1.0.Beta3.jar:4.1.0.Beta3]
at io.netty.channel.AbstractChannelHandlerContext.fireExceptionCaught(AbstractChannelHandlerContext.java:167) [netty-transport-4.1.0.Beta3.jar:4.1.0.Beta3]
at io.netty.channel.ChannelInboundHandlerAdapter.exceptionCaught(ChannelInboundHandlerAdapter.java:131) [netty-transport-4.1.0.Beta3.jar:4.1.0.Beta3]
at io.netty.channel.ChannelHandlerInvokerUtil.invokeExceptionCaughtNow(ChannelHandlerInvokerUtil.java:64) [netty-transport-4.1.0.Beta3.jar:4.1.0.Beta3]
at io.netty.channel.DefaultChannelHandlerInvoker.invokeExceptionCaught(DefaultChannelHandlerInvoker.java:110) [netty-transport-4.1.0.Beta3.jar:4.1.0.Beta3]
at io.netty.channel.AbstractChannelHandlerContext.fireExceptionCaught(AbstractChannelHandlerContext.java:167) [netty-transport-4.1.0.Beta3.jar:4.1.0.Beta3]
at io.netty.handler.timeout.ReadTimeoutHandler.readTimedOut(ReadTimeoutHandler.java:186) [netty-handler-4.1.0.Beta3.jar:4.1.0.Beta3]
at io.netty.handler.timeout.ReadTimeoutHandler$ReadTimeoutTask.run(ReadTimeoutHandler.java:212) [netty-handler-4.1.0.Beta3.jar:4.1.0.Beta3]
at io.netty.util.concurrent.PromiseTask$RunnableAdapter.call(PromiseTask.java:38) [netty-common-4.1.0.Beta3.jar:4.1.0.Beta3]
at io.netty.util.concurrent.ScheduledFutureTask.run(ScheduledFutureTask.java:123) [netty-common-4.1.0.Beta3.jar:4.1.0.Beta3]
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:343) [netty-common-4.1.0.Beta3.jar:4.1.0.Beta3]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:356) [netty-transport-4.1.0.Beta3.jar:4.1.0.Beta3]
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:834) [netty-common-4.1.0.Beta3.jar:4.1.0.Beta3]
at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137) [netty-common-4.1.0.Beta3.jar:4.1.0.Beta3]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_20]
Caused by: io.netty.handler.timeout.ReadTimeoutException: null
Dec 31 2014 12:18:21.913 [nioEventLoopGroup-2-2] [Slf4JLogger.java:151] WARN i.n.c.DefaultChannelPipeline - .. and the cause of the exceptionCaught() was:
io.netty.handler.timeout.ReadTimeoutException: null

Thanks,

Ken

reponse handler can miss response or exception

since a IsSimplePromiseResponseHandler is added after a request was send, it can happen (and for us did happen very often) that the response (or exception) was already received before the handler is added. The handler is not called in this case and waits forever. PR follows.

etcd4j can not handler auth/enable

I implemented PUT/DELETE /v2/auth/enable ,but EtcdResponseHandler.channelRead0 can not handler "status.equals(HttpResponseStatus.OK) && !content.isReadable()" . because auth/enable not response any content.

Netty is not shutting down cleanly after EtcdClient.close is called

I have a simple etcd4j based application which uses the wait facility to wait on Etcd key changes. When shutting down the application (EtcdClient.close() is called from within proto.close()) the Netty won't shutdown cleanly, even if I take care to explicitly cancel all promises beforehand.

It appears that EtcdClient is not trying hard enough to shutdown the underlying Netty factories or whatever.

proto.close()
[main] INFO mousio.etcd4j.transport.EtcdNettyClient - Shutting down Etcd4j Netty client
after proto.close()
[pool-1-thread-1] WARN io.netty.util.HashedWheelTimer - An exception was thrown by TimerTask.
java.lang.IllegalStateException: executor not accepting a task
at io.netty.resolver.NameResolverGroup.getResolver(NameResolverGroup.java:58)
at io.netty.bootstrap.Bootstrap.doResolveAndConnect(Bootstrap.java:164)
at io.netty.bootstrap.Bootstrap.connect(Bootstrap.java:139)
at io.netty.bootstrap.Bootstrap.connect(Bootstrap.java:120)
.... 10 pages of the usual Netty dung omitted

wait/reconnect does not seem to be working

I'm running a local etcd v 4.6.
I have a test program that uses waitForChange, and all works well as long as the etcd connection is alive. However if I bounce etcd there is no reconnect. Should there be? Below is my test code.

public class Test {

public static void main(String[] args) throws IOException {

    new Thread(new Runnable() {
        @Override
        public void run() {
            final Object lock = this;
            while (true) {
                System.out.println("waiting");
                try (EtcdClient etcd = new EtcdClient(
                        URI.create("http://127.0.0.1:4001"))) {
                    EtcdResponsePromise<EtcdKeysResponse> promise = etcd
                            .get("foo").waitForChange().send();
                    promise.addListener(r -> {
                        System.out.println("change!");
                        try {
                            System.out.println(r.get().node.value);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        synchronized (lock) {
                            lock.notify();
                        }
                    });
                    synchronized (this) {
                        wait();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }).start();

    try {
        Thread.sleep(10000000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

}

Thead can not be finished after close etcdclient

etcd version: 2.3.1
etcd4j version: 2.10.0


description: There are 3 nodes in etcd cluster, I created a EtcdClient, then try to set value, then shut down the EtcdClient. The Thread can be finished.
But if one of the the 3 nodes in the cluster is down, the thread can not be finished, it will be always running.


Code:
EtcdClient etcd = new EtcdClient(
URI.create("http://node1:2379")
,URI.create("http://node2:2379")
,URI.create("http://node3:2379")
);

try {
EtcdKeysResponse response = etcd.put("java", "hi2").timeout(1, TimeUnit.SECONDS).send().get();
System.out.println(response.node.value);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (EtcdException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (EtcdAuthenticationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TimeoutException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

try {
etcd.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

NullPointerException thrown for getAll request

Following call client.getAll().timeout(30, TimeUnit.SECONDS).send().get() throws NPE because of null key parameter.

java.lang.NullPointerException
at mousio.etcd4j.requests.EtcdKeyRequest.(EtcdKeyRequest.java:60)
at mousio.etcd4j.requests.EtcdKeyRequest.(EtcdKeyRequest.java:46)
at mousio.etcd4j.requests.EtcdKeyGetRequest.(EtcdKeyGetRequest.java:37)
at mousio.etcd4j.EtcdClient.getAll(EtcdClient.java:256)
at

I used version 2.10.0 from maven central.

Async / Wait operations support.

Usually a user should be able to watch over a key / dir for a change and when there is a change the user must be notified. This is useful for dynamic application configuration changes. If i have an app which is configured via ETCD and someone decides to change a single parameter, the application must be able to recognize such event and act upon it.

i.e. change the db host.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.