jam2in / arcus-java-client

Arcus Java client
Apache License 2.0
0 stars 0 forks source link

ClientBaseCase 의 CFB class 설계 오류 #4

Closed whchoi83 closed 8 years ago

whchoi83 commented 8 years ago

ClientBaseCase 의 CFB class 에 설계상 오류가 존재합니다.

ClientBaseCase 의 CFB 의 본래 목적은 각 junit test 에서 test 성격에 맞는 설정을 갖는 ConnectionFactory 를 생성하고. 이것을 CFB에 넘겨주면 이것 이외에는 DefaultConnectionFactory 의 값을 사용하도록 하기 위함입니다. 아래 코드를 보시면 이해가 쉽습니다.

ClientBaseCase.java

    protected void initClient() throws Exception {
        initClient(new DefaultConnectionFactory() {
            @Override
            public long getOperationTimeout() {
                return 15000;
            }

            @Override
            public FailureMode getFailureMode() {
                return FailureMode.Retry;
            }
        });
    }

    protected void initClient(ConnectionFactory cf) throws Exception {
        if (USE_ZK) {
            openFromZK(new CFB(cf));
        } else {
            openDirect(new CFB(cf));
        }
    }

ClientBaseCase.CFB

    private static class CFB extends ConnectionFactoryBuilder {

        private final ConnectionFactory inner;

        public CFB(ConnectionFactory cf) {
            this.inner = cf;
        }

        @Override
        public ConnectionFactory build() {
            return new ConnectionFactory() {
                @Override
                public MemcachedConnection createConnection(
                        List<InetSocketAddress> addrs) throws IOException {
                    return inner.createConnection(addrs);
                }
...
                @Override
                public Collection<ConnectionObserver> getInitialObservers() {
                    return inner.getInitialObservers();
                }
...
            };
        }

        @Override
        public ConnectionFactoryBuilder setInitialObservers(
                Collection<ConnectionObserver> obs) {
            return this;
        }
    }

하지만 설계(?)의 문제로 인하여 본래의 의도대로 코드가 동작하지 않습니다. 정확히는 대부분의 코드는 문제가 되지 않지만, 특정 부분에서 문제가 발생합니다.

그 중에 하나가 CFB 의 inner.createConnection(addrs) 입니다. 여기서의 inner 는 ClientBaseCase.initClient() 에서 생성된 DefaultConnectionFactory 인데, createConnection 코드를 보면 아래와 같습니다. DefaultConnectionFactory.java

    public MemcachedConnection createConnection(List<InetSocketAddress> addrs)
        throws IOException {
        return new MemcachedConnection(getReadBufSize(), this, addrs,
            getInitialObservers(), getFailureMode(), getOperationFactory());
    }

여기서 getInitialObservers() 는 코드상 무조건 아래 코드입니다. DefaultConnectionFactory.getinitialObservers

    public Collection<ConnectionObserver> getInitialObservers() {
        return Collections.emptyList();
    }

이렇게 되면 USE_ZK=true 로 테스트 코드를 실행할 경우, CacheManager.createArcusClient() 에서 latch 때문에 10초를 대기하게 됩니다. 이러한 문제는 DefaultConnectionFactory 에는 멤버 변수이 기본 값을 return 하면서, ConnectionFactoryBuilder 의 멤버 변수에 set 을 한 뒤 get 을 하는 설정 들은 모두 문제가 됩니다. 그 예가 initial observers 입니다.

설명이 좀 어렵지만 코드를 찬찬히 읽어보시면 이해가 될 것 같습니다. 현재 발견한 문제는 observers 만 발생하지만 다른 connection config 에도 문제가 될 수 있습니다. ClientBaseCase 의 CFB 만 수정하거나 ClientBaseCase.initClient(ConnectionFactory cf) 만 수정해서는 해결할 문제가 아니고, ClientBaseCase 를 상속받아 initClient(ConnectionFactory cf) 를 사용하는 모든 테스트를 수정해야 합니다.

aiceru commented 8 years ago

Close 합니다.