package netflix.ocelli.client; import java.util.HashSet; import java.util.Set; import java.util.concurrent.Semaphore; import java.util.concurrent.atomic.AtomicLong; import netflix.ocelli.util.RxUtil; import rx.Observable; import rx.Observer; import rx.functions.Func1; import rx.functions.Func2; public class TestClient { private final String id; private final Func1<TestClient, Observable<TestClient>> behavior; private final Observable<Void> connect; private final int concurrency = 10; private final Semaphore sem = new Semaphore(concurrency); private final Set<String> vips = new HashSet<String>(); private String rack; public static Func1<TestClient, Observable<String>> byVip() { return new Func1<TestClient, Observable<String>>() { @Override public Observable<String> call(TestClient t1) { return Observable.from(t1.vips).concatWith(Observable.just("*")); } }; } public static Func1<TestClient, Observable<String>> byRack() { return new Func1<TestClient, Observable<String>>() { @Override public Observable<String> call(TestClient t1) { return Observable.just(t1.rack); } }; } public static Func1<TestClient, Integer> byPendingRequestCount() { return new Func1<TestClient, Integer>() { @Override public Integer call(TestClient t1) { return t1.sem.availablePermits(); } }; } public static TestClient create(String id, Observable<Void> connect, Func1<TestClient, Observable<TestClient>> behavior) { return new TestClient(id, connect, behavior); } public static TestClient create(String id, Func1<TestClient, Observable<TestClient>> behavior) { return new TestClient(id, Connects.immediate(), behavior); } public static Func2<TestClient, String, Observable<String>> func() { return new Func2<TestClient, String,Observable<String>>() { @Override public Observable<String> call(TestClient client, String request) { return client.execute(new Func1<TestClient, Observable<String>>() { @Override public Observable<String> call(TestClient t1) { return Observable.just(t1.id()); } }); } }; } public TestClient(String id, Observable<Void> connect, Func1<TestClient, Observable<TestClient>> behavior) { this.id = id; this.behavior = behavior; this.connect = connect; } public Observable<Void> connect() { return connect; } public TestClient withVip(String vip) { this.vips.add(vip); return this; } public TestClient withRack(String rack) { this.rack = rack; return this; } public Set<String> vips() { return this.vips; } public String rack() { return this.rack; } public String id() { return this.id; } private AtomicLong executeCount = new AtomicLong(0); private AtomicLong onNextCount = new AtomicLong(0); private AtomicLong onCompletedCount = new AtomicLong(0); private AtomicLong onSubscribeCount = new AtomicLong(0); private AtomicLong onUnSubscribeCount = new AtomicLong(0); private AtomicLong onErrorCount = new AtomicLong(0); public long getExecuteCount() { return executeCount.get(); } public long getOnNextCount() { return onNextCount.get(); } public long getOnCompletedCount() { return onCompletedCount.get(); } public long getOnErrorCount() { return onErrorCount.get(); } public long getOnSubscribeCount() { return onSubscribeCount.get(); } public long getOnUnSubscribeCount() { return onUnSubscribeCount.get(); } public boolean hasError() { return onErrorCount.get() > 0; } public Observable<String> execute(Func1<TestClient, Observable<String>> operation) { this.executeCount.incrementAndGet(); return behavior.call(this) .doOnSubscribe(RxUtil.increment(onSubscribeCount)) .doOnSubscribe(RxUtil.acquire(sem)) .doOnUnsubscribe(RxUtil.increment(onUnSubscribeCount)) .concatMap(operation) .doOnEach(new Observer<String>() { @Override public void onCompleted() { onCompletedCount.incrementAndGet(); sem.release(); } @Override public void onError(Throwable e) { onErrorCount.incrementAndGet(); } @Override public void onNext(String t) { onNextCount.incrementAndGet(); } }); } public String toString() { return "Host[id=" + id + "]"; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((id == null) ? 0 : id.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; TestClient other = (TestClient) obj; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; return true; } }