├── .gitignore ├── precipice-reporting ├── build.gradle └── src │ ├── main │ └── java │ │ └── net │ │ └── uncontended │ │ └── precipice │ │ └── reporting │ │ ├── registry │ │ ├── MetricRegistryCallback.java │ │ ├── SummaryProperties.java │ │ ├── Slice.java │ │ └── MetricRegistry.java │ │ ├── Entry.java │ │ └── Dashboard.java │ └── test │ └── java │ └── net │ └── uncontended │ └── precipice │ └── reporting │ └── registry │ └── SummaryTest.java ├── precipice-threadpool ├── src │ ├── main │ │ └── java │ │ │ └── net │ │ │ └── uncontended │ │ │ └── precipice │ │ │ └── threadpool │ │ │ ├── PatternRejected.java │ │ │ ├── PatternCallable.java │ │ │ ├── CallableWithContext.java │ │ │ ├── utils │ │ │ ├── ServiceThreadFactory.java │ │ │ ├── PrecipiceExecutors.java │ │ │ └── TaskFactory.java │ │ │ ├── ThreadPoolTimeout.java │ │ │ └── experimental │ │ │ └── ExchangingQueue.java │ └── test │ │ └── java │ │ └── net │ │ └── uncontended │ │ └── precipice │ │ └── threadpool │ │ ├── ThreadPoolTimeoutTest.java │ │ └── test_utils │ │ └── TestCallable.java └── build.gradle ├── precipice-core ├── src │ ├── main │ │ └── java │ │ │ └── net │ │ │ └── uncontended │ │ │ └── precipice │ │ │ ├── metrics │ │ │ ├── counts │ │ │ │ ├── WritableCounts.java │ │ │ │ ├── PartitionedCount.java │ │ │ │ ├── NoOpCounter.java │ │ │ │ ├── SingleIncrementCounts.java │ │ │ │ ├── RollingCountsBuilder.java │ │ │ │ ├── LongCounter.java │ │ │ │ ├── CountRecorderBuilder.java │ │ │ │ ├── TotalCounts.java │ │ │ │ ├── AtomicLongCounter.java │ │ │ │ ├── LongAdderCounter.java │ │ │ │ ├── Counters.java │ │ │ │ ├── CountRecorder.java │ │ │ │ ├── RollingCounts.java │ │ │ │ └── Accumulator.java │ │ │ ├── latency │ │ │ │ ├── WritableLatency.java │ │ │ │ ├── PartitionedLatency.java │ │ │ │ ├── SingleIncrementLatency.java │ │ │ │ ├── AtomicHistogram.java │ │ │ │ ├── ConcurrentHistogram.java │ │ │ │ ├── NoOpLatency.java │ │ │ │ ├── LatencyRecorderBuilder.java │ │ │ │ ├── TotalLatency.java │ │ │ │ ├── BaseHDRHistogram.java │ │ │ │ ├── LatencyRecorder.java │ │ │ │ └── RollingLatency.java │ │ │ ├── IntervalIterator.java │ │ │ ├── Resettable.java │ │ │ ├── Metrics.java │ │ │ ├── tools │ │ │ │ ├── Allocator.java │ │ │ │ ├── Recorder.java │ │ │ │ ├── FlipControl.java │ │ │ │ ├── RelaxedFlipControl.java │ │ │ │ ├── StrictFlipControl.java │ │ │ │ ├── RecorderBuilder.java │ │ │ │ ├── RollingMetrics.java │ │ │ │ ├── RollingBuilder.java │ │ │ │ └── MetricRecorder.java │ │ │ ├── Rolling.java │ │ │ └── AbstractMetrics.java │ │ │ ├── rejected │ │ │ ├── Unrejectable.java │ │ │ ├── Rejected.java │ │ │ └── RejectedException.java │ │ │ ├── util │ │ │ └── SimulationRejected.java │ │ │ ├── circuit │ │ │ ├── BackgroundTask.java │ │ │ ├── experimental │ │ │ │ ├── HealthChecker.java │ │ │ │ ├── AbstractBreaker.java │ │ │ │ └── RefactoredBreaker.java │ │ │ ├── CircuitBreaker.java │ │ │ ├── HealthSnapshot.java │ │ │ ├── CircuitBreakerConfig.java │ │ │ ├── NoOpCircuitBreaker.java │ │ │ ├── CircuitBreakerConfigBuilder.java │ │ │ └── HealthGauge.java │ │ │ ├── timeout │ │ │ ├── Timeout.java │ │ │ ├── TimeoutService.java │ │ │ ├── TimerWheelService.java │ │ │ └── PrecipiceTimeoutException.java │ │ │ ├── ResultView.java │ │ │ ├── pattern │ │ │ ├── Sequence.java │ │ │ ├── PatternStrategy.java │ │ │ ├── SequenceFactory.java │ │ │ ├── AllocatingSequenceFactory.java │ │ │ ├── ThreadLocalSequenceFactory.java │ │ │ ├── WritableSequence.java │ │ │ ├── SingleReaderArrayIterable.java │ │ │ ├── Shotgun.java │ │ │ └── RoundRobinLoadBalancer.java │ │ │ ├── Failable.java │ │ │ ├── time │ │ │ ├── Clock.java │ │ │ ├── SystemTime.java │ │ │ └── TickingClock.java │ │ │ ├── PrecipiceFunction.java │ │ │ ├── semaphore │ │ │ ├── PrecipiceSemaphore.java │ │ │ ├── UnlimitedSemaphore.java │ │ │ └── LongSemaphore.java │ │ │ ├── Cancellable.java │ │ │ ├── result │ │ │ ├── SimpleResult.java │ │ │ └── TimeoutableResult.java │ │ │ ├── ExecutionContext.java │ │ │ ├── concurrent │ │ │ ├── PrecipicePromise.java │ │ │ └── PrecipiceFuture.java │ │ │ ├── Precipice.java │ │ │ ├── GuardRailProperties.java │ │ │ ├── Completable.java │ │ │ ├── CallService.java │ │ │ ├── BackPressure.java │ │ │ ├── rate │ │ │ └── RateLimiter.java │ │ │ ├── GuardRailBuilder.java │ │ │ └── factories │ │ │ └── Asynchronous.java │ └── test │ │ └── java │ │ └── net │ │ └── uncontended │ │ └── precipice │ │ ├── CompletionContextTest.java │ │ ├── test_utils │ │ ├── TestResult.java │ │ └── TestCallables.java │ │ ├── pattern │ │ └── ShotgunTest.java │ │ ├── metrics │ │ ├── latency │ │ │ └── RollingLatencyTest.java │ │ ├── tools │ │ │ └── StrictFlipControlTest.java │ │ └── counts │ │ │ └── RollingCountTest.java │ │ └── semaphore │ │ └── UnlimitedSemaphoreTest.java └── build.gradle ├── precipice-samples ├── build.gradle └── src │ └── main │ └── java │ └── net │ └── uncontended │ └── precipice │ └── samples │ ├── http │ └── HTTPStatus.java │ ├── kafka │ └── ProduceStatus.java │ ├── bigger │ ├── BiggerExample.java │ └── Servers.java │ └── GuardRailWithFactory.java ├── settings.gradle ├── gradle └── wrapper │ └── gradle-wrapper.properties ├── doc └── release-notes.md └── gradlew.bat /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | build/ 3 | -------------------------------------------------------------------------------- /precipice-reporting/build.gradle: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /precipice-threadpool/src/main/java/net/uncontended/precipice/threadpool/PatternRejected.java: -------------------------------------------------------------------------------- 1 | package net.uncontended.precipice.threadpool; 2 | 3 | public enum PatternRejected { 4 | ALL_REJECTED 5 | } 6 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/counts/WritableCounts.java: -------------------------------------------------------------------------------- 1 | package net.uncontended.precipice.metrics.counts; 2 | 3 | import net.uncontended.precipice.metrics.Metrics; 4 | 5 | public interface WritableCounts> extends Metrics { 6 | 7 | public void write(T metric, long number, long nanoTime); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/latency/WritableLatency.java: -------------------------------------------------------------------------------- 1 | package net.uncontended.precipice.metrics.latency; 2 | 3 | import net.uncontended.precipice.metrics.Metrics; 4 | 5 | public interface WritableLatency> extends Metrics { 6 | 7 | public void write(T metric, long number, long nanoLatency, long nanoTime); 8 | } 9 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/IntervalIterator.java: -------------------------------------------------------------------------------- 1 | package net.uncontended.precipice.metrics; 2 | 3 | import java.util.Iterator; 4 | import java.util.concurrent.TimeUnit; 5 | 6 | public interface IntervalIterator extends Iterator { 7 | 8 | @Override 9 | boolean hasNext(); 10 | 11 | @Override 12 | T next(); 13 | 14 | @Override 15 | void remove(); 16 | 17 | long intervalStart(); 18 | 19 | long intervalEnd(); 20 | 21 | IntervalIterator limit(long duration, TimeUnit unit); 22 | 23 | IntervalIterator reset(long nanoTime); 24 | 25 | } 26 | -------------------------------------------------------------------------------- /precipice-core/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ -------------------------------------------------------------------------------- /precipice-samples/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ -------------------------------------------------------------------------------- /precipice-threadpool/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | include 'precipice-core', 'precipice-samples', 'precipice-reporting', 'precipice-threadpool' 18 | 19 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/rejected/Unrejectable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.rejected; 19 | 20 | public enum Unrejectable { 21 | } 22 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/Resettable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics; 19 | 20 | public interface Resettable { 21 | 22 | void reset(); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/util/SimulationRejected.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.util; 19 | 20 | public enum SimulationRejected { 21 | SIMULATION_REJECTION 22 | } 23 | -------------------------------------------------------------------------------- /precipice-core/src/test/java/net/uncontended/precipice/CompletionContextTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice; 19 | 20 | public class CompletionContextTest { 21 | 22 | // TODO: Add tests 23 | } 24 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/circuit/BackgroundTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.circuit; 19 | 20 | public interface BackgroundTask { 21 | void tick(long nanoTime); 22 | } 23 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/timeout/Timeout.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.timeout; 19 | 20 | @FunctionalInterface 21 | public interface Timeout { 22 | void timeout(); 23 | } 24 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/ResultView.java: -------------------------------------------------------------------------------- 1 | package net.uncontended.precipice; 2 | 3 | /** 4 | * A read only view of the result of a computation. 5 | * 6 | * @param the type of the result for the computation 7 | * @param the type of the value resulting from the computation 8 | */ 9 | public interface ResultView { 10 | /** 11 | * Return the value of a successful execution. 12 | * 13 | * @return the value 14 | */ 15 | V getValue(); 16 | 17 | /** 18 | * Return the exception that might have occurred during a failed execution. 19 | * 20 | * @return the exception 21 | */ 22 | Throwable getError(); 23 | 24 | /** 25 | * Return the result of the execution. 26 | * 27 | * @return the result 28 | */ 29 | Result getResult(); 30 | } 31 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/pattern/Sequence.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.pattern; 19 | 20 | public interface Sequence extends Iterable { 21 | 22 | boolean isEmpty(); 23 | } 24 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/Failable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice; 19 | 20 | public interface Failable { 21 | 22 | boolean isFailure(); 23 | 24 | boolean isSuccess(); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/time/Clock.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.time; 19 | 20 | public interface Clock { 21 | 22 | long currentTimeMillis(); 23 | 24 | long nanoTime(); 25 | } 26 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/Metrics.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics; 19 | 20 | public interface Metrics> { 21 | 22 | Class getMetricClazz(); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/tools/Allocator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.tools; 19 | 20 | @FunctionalInterface 21 | public interface Allocator { 22 | 23 | T allocateNew(); 24 | } 25 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/PrecipiceFunction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice; 19 | 20 | @FunctionalInterface 21 | public interface PrecipiceFunction { 22 | 23 | void apply(S result, T argument); 24 | } 25 | -------------------------------------------------------------------------------- /precipice-threadpool/src/main/java/net/uncontended/precipice/threadpool/PatternCallable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.threadpool; 19 | 20 | public interface PatternCallable { 21 | 22 | T call(C context) throws Exception; 23 | } 24 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/circuit/experimental/HealthChecker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.circuit.experimental; 19 | 20 | public interface HealthChecker { 21 | 22 | boolean isHealthy(long nanoTime); 23 | } 24 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/rejected/Rejected.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.rejected; 19 | 20 | public enum Rejected { 21 | CIRCUIT_OPEN, 22 | MAX_CONCURRENCY_LEVEL_EXCEEDED, 23 | RATE_LIMIT_EXCEEDED 24 | } 25 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/pattern/PatternStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.pattern; 19 | 20 | public interface PatternStrategy { 21 | 22 | Iterable nextIndices(); 23 | 24 | int acquireCount(); 25 | } 26 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/pattern/SequenceFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.pattern; 19 | 20 | @FunctionalInterface 21 | public interface SequenceFactory { 22 | WritableSequence getSequence(int size); 23 | } 24 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2014 Timothy Brooks 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # 17 | #Fri Jun 19 19:54:59 PDT 2015 18 | distributionBase=GRADLE_USER_HOME 19 | distributionPath=wrapper/dists 20 | zipStoreBase=GRADLE_USER_HOME 21 | zipStorePath=wrapper/dists 22 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip 23 | -------------------------------------------------------------------------------- /precipice-reporting/src/main/java/net/uncontended/precipice/reporting/registry/MetricRegistryCallback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.uncontended.precipice.reporting.registry; 18 | 19 | @FunctionalInterface 20 | public interface MetricRegistryCallback { 21 | 22 | void apply(T argument); 23 | } 24 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/semaphore/PrecipiceSemaphore.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.semaphore; 19 | 20 | public interface PrecipiceSemaphore { 21 | 22 | long maxConcurrencyLevel(); 23 | 24 | long remainingCapacity(); 25 | 26 | long currentConcurrencyLevel(); 27 | } 28 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/timeout/TimeoutService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.timeout; 19 | 20 | public interface TimeoutService { 21 | void scheduleTimeout(Timeout timeout, long timeoutMillis); 22 | 23 | void scheduleTimeout(Timeout timeout, long timeoutMillis, long nanoTime); 24 | } 25 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/Rolling.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics; 19 | 20 | public interface Rolling { 21 | 22 | T current(); 23 | 24 | T current(long nanoTime); 25 | 26 | IntervalIterator intervals(); 27 | 28 | IntervalIterator intervals(long nanoTime); 29 | } 30 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/rejected/RejectedException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.rejected; 19 | 20 | public class RejectedException extends RuntimeException { 21 | 22 | public final Enum reason; 23 | 24 | public RejectedException(Enum reason) { 25 | this.reason = reason; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/Cancellable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice; 19 | 20 | /** 21 | * A context representing the execution of a task that can be cancelled. 22 | */ 23 | public interface Cancellable { 24 | 25 | /** 26 | * Cancels the execution of this task. 27 | */ 28 | void cancel(); 29 | } 30 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/pattern/AllocatingSequenceFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.pattern; 19 | 20 | public class AllocatingSequenceFactory implements SequenceFactory { 21 | @Override 22 | public WritableSequence getSequence(int size) { 23 | return new WritableSequence<>(size); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /precipice-reporting/src/main/java/net/uncontended/precipice/reporting/registry/SummaryProperties.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.uncontended.precipice.reporting.registry; 18 | 19 | public class SummaryProperties { 20 | 21 | public boolean accumulateTotalResults = true; 22 | 23 | public boolean accumulateTotalRejections = true; 24 | 25 | public int bufferSize = 60; 26 | } 27 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/tools/Recorder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.tools; 19 | 20 | public interface Recorder { 21 | 22 | T activeInterval(); 23 | 24 | long activeIntervalStart(); 25 | 26 | T captureInterval(); 27 | 28 | T captureInterval(long nanotime); 29 | 30 | T captureInterval(T newInterval); 31 | 32 | T captureInterval(T newInterval, long nanoTime); 33 | } 34 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/tools/FlipControl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.tools; 19 | 20 | public abstract class FlipControl { 21 | protected volatile V active; 22 | 23 | public V active() { 24 | return active; 25 | } 26 | 27 | public abstract long startRecord(); 28 | 29 | public abstract void endRecord(long permit); 30 | 31 | public abstract V flip(V newValue); 32 | } 33 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/counts/PartitionedCount.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.counts; 19 | 20 | import net.uncontended.precipice.metrics.Metrics; 21 | import net.uncontended.precipice.metrics.Resettable; 22 | 23 | public interface PartitionedCount> extends Metrics, Resettable { 24 | 25 | long getCount(T metric); 26 | 27 | long total(); 28 | 29 | void add(T metric, long delta); 30 | } 31 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/AbstractMetrics.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics; 19 | 20 | public abstract class AbstractMetrics> implements Metrics { 21 | 22 | protected final Class clazz; 23 | 24 | protected AbstractMetrics(Class clazz) { 25 | this.clazz = clazz; 26 | } 27 | 28 | @Override 29 | public Class getMetricClazz() { 30 | return clazz; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/result/SimpleResult.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.result; 19 | 20 | import net.uncontended.precipice.Failable; 21 | 22 | public enum SimpleResult implements Failable { 23 | SUCCESS, 24 | ERROR; 25 | 26 | @Override 27 | public boolean isFailure() { 28 | return this == ERROR; 29 | } 30 | 31 | @Override 32 | public boolean isSuccess() { 33 | return this == SUCCESS; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/result/TimeoutableResult.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.result; 19 | 20 | import net.uncontended.precipice.Failable; 21 | 22 | public enum TimeoutableResult implements Failable { 23 | SUCCESS, 24 | ERROR, 25 | TIMEOUT; 26 | 27 | @Override 28 | public boolean isFailure() { 29 | return this != SUCCESS; 30 | } 31 | 32 | @Override 33 | public boolean isSuccess() { 34 | return this == SUCCESS; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/circuit/CircuitBreaker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.circuit; 19 | 20 | import net.uncontended.precipice.BackPressure; 21 | 22 | public interface CircuitBreaker> extends BackPressure { 23 | boolean isOpen(); 24 | 25 | CircuitBreakerConfig getBreakerConfig(); 26 | 27 | void setBreakerConfig(CircuitBreakerConfig breakerConfig); 28 | 29 | void forceOpen(); 30 | 31 | void forceClosed(); 32 | } 33 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/tools/RelaxedFlipControl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.tools; 19 | 20 | public class RelaxedFlipControl extends FlipControl { 21 | 22 | @Override 23 | public long startRecord() { 24 | return 0L; 25 | } 26 | 27 | @Override 28 | public void endRecord(long permit) { 29 | } 30 | 31 | public synchronized V flip(V newValue) { 32 | V old = this.active; 33 | this.active = newValue; 34 | return old; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/time/SystemTime.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.time; 19 | 20 | public class SystemTime implements Clock { 21 | 22 | private static final SystemTime DEFAULT = new SystemTime(); 23 | 24 | private SystemTime() {} 25 | 26 | @Override 27 | public long currentTimeMillis() { 28 | return System.currentTimeMillis(); 29 | } 30 | 31 | @Override 32 | public long nanoTime() { 33 | return System.nanoTime(); 34 | } 35 | 36 | public static SystemTime getInstance() { 37 | return DEFAULT; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /precipice-core/src/test/java/net/uncontended/precipice/test_utils/TestResult.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.uncontended.precipice.test_utils; 18 | 19 | import net.uncontended.precipice.Failable; 20 | 21 | public enum TestResult implements Failable { 22 | 23 | SUCCESS(false), 24 | ERROR(true); 25 | 26 | private final boolean isFailed; 27 | 28 | TestResult(boolean isFailed) { 29 | this.isFailed = isFailed; 30 | } 31 | 32 | @Override 33 | public boolean isFailure() { 34 | return isFailed; 35 | } 36 | 37 | @Override 38 | public boolean isSuccess() { 39 | return this == SUCCESS; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /precipice-threadpool/src/main/java/net/uncontended/precipice/threadpool/CallableWithContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.threadpool; 19 | 20 | import java.util.concurrent.Callable; 21 | 22 | class CallableWithContext implements Callable { 23 | 24 | private final PatternCallable callable; 25 | private final C context; 26 | 27 | CallableWithContext(PatternCallable callable, C context) { 28 | this.callable = callable; 29 | this.context = context; 30 | } 31 | 32 | @Override 33 | public T call() throws Exception { 34 | return callable.call(context); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/ExecutionContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice; 19 | 20 | /** 21 | * A context representing the execution of a task that was allowed by a guard rail. 22 | */ 23 | public interface ExecutionContext { 24 | 25 | /** 26 | * Returns the time that the guard rail approved the execution of this task. 27 | * 28 | * @return the start nano time 29 | */ 30 | long startNanos(); 31 | 32 | /** 33 | * Returns the number of guard rail permits that this task required. 34 | * 35 | * @return number of permits 36 | */ 37 | long permitCount(); 38 | } 39 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/latency/PartitionedLatency.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.latency; 19 | 20 | import net.uncontended.precipice.metrics.Metrics; 21 | import net.uncontended.precipice.metrics.Resettable; 22 | import org.HdrHistogram.Histogram; 23 | 24 | public interface PartitionedLatency> extends Metrics, Resettable { 25 | 26 | void record(T metric, long number, long nanoLatency); 27 | 28 | Histogram getHistogram(T metric); 29 | 30 | long getValueAtPercentile(T metric, double percentile); 31 | 32 | boolean isHDR(); 33 | 34 | @Override 35 | void reset(); 36 | } 37 | -------------------------------------------------------------------------------- /precipice-samples/src/main/java/net/uncontended/precipice/samples/http/HTTPStatus.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.samples.http; 19 | 20 | import net.uncontended.precipice.Failable; 21 | 22 | public enum HTTPStatus implements Failable { 23 | STATUS_200(false), 24 | NON_200(false), 25 | ERROR(true), 26 | TIMEOUT(true); 27 | 28 | private final boolean isFailed; 29 | 30 | HTTPStatus(boolean isFailed) { 31 | this.isFailed = isFailed; 32 | } 33 | 34 | @Override 35 | public boolean isFailure() { 36 | return isFailed; 37 | } 38 | 39 | @Override 40 | public boolean isSuccess() { 41 | return !isFailed; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/pattern/ThreadLocalSequenceFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | package net.uncontended.precipice.pattern; 18 | 19 | public class ThreadLocalSequenceFactory implements SequenceFactory { 20 | 21 | private ThreadLocal> local = new ThreadLocal<>(); 22 | 23 | 24 | @Override 25 | public WritableSequence getSequence(int size) { 26 | WritableSequence precipices = local.get(); 27 | 28 | if (precipices == null) { 29 | precipices = new WritableSequence<>(size); 30 | local.set(precipices); 31 | } 32 | precipices.reset(); 33 | return precipices; 34 | } 35 | 36 | 37 | } 38 | -------------------------------------------------------------------------------- /precipice-threadpool/src/main/java/net/uncontended/precipice/threadpool/utils/ServiceThreadFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.threadpool.utils; 19 | 20 | import java.util.concurrent.ThreadFactory; 21 | import java.util.concurrent.atomic.AtomicInteger; 22 | 23 | public class ServiceThreadFactory implements ThreadFactory { 24 | 25 | private final AtomicInteger count = new AtomicInteger(0); 26 | private final String name; 27 | 28 | 29 | public ServiceThreadFactory(String name) { 30 | this.name = name; 31 | } 32 | 33 | @Override 34 | public Thread newThread(Runnable r) { 35 | return new Thread(r, name + '-' + count.getAndIncrement()); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/circuit/HealthSnapshot.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.circuit; 19 | 20 | public class HealthSnapshot { 21 | 22 | public final long total; 23 | public final long failures; 24 | public final int failurePercentage; 25 | 26 | public HealthSnapshot(long total, long failures) { 27 | this.total = total; 28 | this.failures = failures; 29 | if (total != 0) { 30 | this.failurePercentage = (int) (100 * failures / total); 31 | } else { 32 | this.failurePercentage = 0; 33 | } 34 | } 35 | 36 | public int failurePercentage() { 37 | return failurePercentage; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /precipice-samples/src/main/java/net/uncontended/precipice/samples/kafka/ProduceStatus.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.samples.kafka; 19 | 20 | import net.uncontended.precipice.Failable; 21 | 22 | public enum ProduceStatus implements Failable { 23 | SUCCESS(false), 24 | NETWORK_EXCEPTION(true), 25 | OTHER_ERROR(true), 26 | TIMEOUT(true); 27 | 28 | private final boolean isFailed; 29 | 30 | ProduceStatus(boolean isFailed) { 31 | this.isFailed = isFailed; 32 | } 33 | 34 | @Override 35 | public boolean isFailure() { 36 | return isFailed; 37 | } 38 | 39 | @Override 40 | public boolean isSuccess() { 41 | return !isFailed; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/circuit/experimental/AbstractBreaker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.circuit.experimental; 19 | 20 | import java.util.concurrent.atomic.AtomicInteger; 21 | 22 | public class AbstractBreaker { 23 | protected static final int CLOSED = 0; 24 | protected static final int OPEN = 1; 25 | protected static final int FORCED_OPEN = 2; 26 | 27 | protected final AtomicInteger state = new AtomicInteger(0); 28 | 29 | public boolean isOpen() { 30 | return state.get() != CLOSED; 31 | } 32 | 33 | public void forceOpen() { 34 | state.set(FORCED_OPEN); 35 | } 36 | 37 | public void forceClosed() { 38 | state.set(CLOSED); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/counts/NoOpCounter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.counts; 19 | 20 | import net.uncontended.precipice.metrics.AbstractMetrics; 21 | 22 | public class NoOpCounter> extends AbstractMetrics implements PartitionedCount { 23 | 24 | public NoOpCounter(Class clazz) { 25 | super(clazz); 26 | } 27 | 28 | @Override 29 | public void add(T metric, long delta) { 30 | } 31 | 32 | @Override 33 | public long getCount(T metric) { 34 | return 0; 35 | } 36 | 37 | @Override 38 | public long total() { 39 | return 0; 40 | } 41 | 42 | @Override 43 | public void reset() { 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/concurrent/PrecipicePromise.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.concurrent; 19 | 20 | import net.uncontended.precipice.Completable; 21 | import net.uncontended.precipice.Failable; 22 | 23 | /** 24 | * A context that can be completed with the result of an asynchronous computation. 25 | * 26 | * @param the type of the result for this promise 27 | * @param the type of the value for this promise 28 | */ 29 | public interface PrecipicePromise extends Completable { 30 | 31 | /** 32 | * Returns a future containing the result of this promise 33 | * 34 | * @return a future 35 | */ 36 | PrecipiceFuture future(); 37 | } 38 | -------------------------------------------------------------------------------- /precipice-threadpool/src/main/java/net/uncontended/precipice/threadpool/utils/PrecipiceExecutors.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.threadpool.utils; 19 | 20 | import java.util.concurrent.ArrayBlockingQueue; 21 | import java.util.concurrent.ExecutorService; 22 | import java.util.concurrent.ThreadPoolExecutor; 23 | import java.util.concurrent.TimeUnit; 24 | 25 | public final class PrecipiceExecutors { 26 | 27 | private PrecipiceExecutors() { 28 | } 29 | 30 | public static ExecutorService threadPoolExecutor(String name, int poolSize, long queueSize) { 31 | return new ThreadPoolExecutor(poolSize, poolSize, Long.MAX_VALUE, TimeUnit.DAYS, 32 | new ArrayBlockingQueue((int) queueSize), new ServiceThreadFactory(name)); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/Precipice.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice; 19 | 20 | /** 21 | * A Precipice is a class that has an associated GuardRail. This interface 22 | * should be implemented by classes that combined the usage of a GuardRail with specialized 23 | * execution logic. The only method {@link #guardRail()} should return the GuardRail associated 24 | * with the implemented class. The {@link CallService} is an example of an implementation. 25 | */ 26 | public interface Precipice & Failable, Rejected extends Enum> { 27 | 28 | /** 29 | * Return the GuardRail associated with this class. 30 | * 31 | * @return the GuardRail 32 | */ 33 | GuardRail guardRail(); 34 | } 35 | -------------------------------------------------------------------------------- /precipice-threadpool/src/main/java/net/uncontended/precipice/threadpool/ThreadPoolTimeout.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.threadpool; 19 | 20 | import net.uncontended.precipice.result.TimeoutableResult; 21 | import net.uncontended.precipice.timeout.PrecipiceTimeoutException; 22 | import net.uncontended.precipice.timeout.Timeout; 23 | 24 | public class ThreadPoolTimeout implements Timeout { 25 | 26 | private CancellableTask cancellableTask; 27 | 28 | public ThreadPoolTimeout(CancellableTask cancellableTask) { 29 | this.cancellableTask = cancellableTask; 30 | } 31 | 32 | @Override 33 | public void timeout() { 34 | cancellableTask.cancel(TimeoutableResult.TIMEOUT, new PrecipiceTimeoutException()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /doc/release-notes.md: -------------------------------------------------------------------------------- 1 | # Release Notes 2 | 3 | ## 0.4.0 4 | 5 | ### Canceling for default PrecipiceFuture implementation. 6 | - Right now does not cancel computation. But sets the result. And avoids first level metrics update. 7 | 8 | ### ActionMetrics updates 9 | - Added tracking of latency for actions. The tracking is currently for the lifetime of the service. There is no 10 | rolling latency measure. 11 | - Added total metric counts to default callable metrics. 12 | - The snapshot function returns both these new features. 13 | 14 | ## 0.5.0 15 | 16 | ### ActionMetrics updates 17 | - Add methods on DefaultActionMetrics to access metric counters. 18 | 19 | ### Latency Metrics Improvements 20 | - Latency metrics are now captured in a specialized class. 21 | - Latency is now partitioned by result - success, error, or timeout. 22 | 23 | ## 0.5.1 24 | 25 | ### Latency Metrics 26 | - Add latency metrics to ServiceProperties 27 | - Remove the implicit initialization of LatencyMetrics in AbstractService. The metrics now must be passed in the 28 | constructor. 29 | 30 | ## 0.5.2 31 | 32 | ### Latency Metrics 33 | - Make latency metrics capture intervals. 34 | 35 | ## 0.6.2 36 | 37 | ### Latency and Count Metrics 38 | - The GuardRail will now pass the permit count to the both latency and count metrics. 39 | - A number of naming conventions have been changes with regard to metrics. 40 | - There are now some metric classes that increment and others that add the total permit count. -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/counts/SingleIncrementCounts.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.counts; 19 | 20 | import net.uncontended.precipice.metrics.AbstractMetrics; 21 | 22 | public class SingleIncrementCounts> extends AbstractMetrics implements WritableCounts { 23 | 24 | private final WritableCounts wrappedCounts; 25 | 26 | public SingleIncrementCounts(WritableCounts wrappedCounts) { 27 | super(wrappedCounts.getMetricClazz()); 28 | this.wrappedCounts = wrappedCounts; 29 | } 30 | 31 | @Override 32 | public void write(T metric, long number, long nanoTime) { 33 | wrappedCounts.write(metric, 1, nanoTime); 34 | } 35 | 36 | public WritableCounts getWrappedCounts() { 37 | return wrappedCounts; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/GuardRailProperties.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice; 19 | 20 | import net.uncontended.precipice.metrics.counts.WritableCounts; 21 | import net.uncontended.precipice.metrics.latency.WritableLatency; 22 | import net.uncontended.precipice.time.Clock; 23 | import net.uncontended.precipice.time.SystemTime; 24 | 25 | import java.util.LinkedHashMap; 26 | import java.util.Map; 27 | 28 | public class GuardRailProperties & Failable, Rejected extends Enum> { 29 | 30 | public String name; 31 | public WritableCounts resultCounts; 32 | public WritableCounts rejectedCounts; 33 | public WritableLatency resultLatency; 34 | public Map> backPressureMap = new LinkedHashMap<>(); 35 | public Clock clock = SystemTime.getInstance(); 36 | } 37 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/counts/RollingCountsBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.counts; 19 | 20 | import net.uncontended.precipice.metrics.tools.RollingBuilder; 21 | import net.uncontended.precipice.metrics.tools.RollingMetrics; 22 | 23 | public class RollingCountsBuilder> extends RollingBuilder, RollingCounts> { 24 | 25 | private final Class clazz; 26 | 27 | public RollingCountsBuilder(Class clazz) { 28 | this.clazz = clazz; 29 | } 30 | 31 | @Override 32 | public RollingCounts build() { 33 | if (allocator == null) { 34 | allocator = Counters.longAdder(clazz); 35 | } 36 | 37 | RollingMetrics> rollingMetrics = buildRollingMetrics(); 38 | return new RollingCounts(rollingMetrics); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/latency/SingleIncrementLatency.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.latency; 19 | 20 | import net.uncontended.precipice.metrics.AbstractMetrics; 21 | 22 | public class SingleIncrementLatency> extends AbstractMetrics implements WritableLatency { 23 | 24 | private final WritableLatency wrappedLatency; 25 | 26 | public SingleIncrementLatency(WritableLatency wrappedLatency) { 27 | super(wrappedLatency.getMetricClazz()); 28 | this.wrappedLatency = wrappedLatency; 29 | } 30 | 31 | @Override 32 | public void write(T metric, long number, long nanoLatency, long nanoTime) { 33 | wrappedLatency.write(metric, 1, nanoLatency, nanoTime); 34 | } 35 | 36 | public WritableLatency getWrappedCounts() { 37 | return wrappedLatency; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /precipice-samples/src/main/java/net/uncontended/precipice/samples/bigger/BiggerExample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.samples.bigger; 19 | 20 | public class BiggerExample { 21 | 22 | // public static void main(String[] args) { 23 | // Servers servers = new Servers(); 24 | // servers.start(); 25 | // 26 | // Client client = new Client(); 27 | // 28 | // BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 29 | // System.out.print("Push enter to start requests"); 30 | // try { 31 | // br.readLine(); 32 | // } catch (IOException e) { 33 | // e.printStackTrace(); 34 | // } 35 | // 36 | // try { 37 | // client.run(); 38 | // } catch (InterruptedException e) { 39 | // e.printStackTrace(); 40 | // } 41 | // 42 | // servers.stop(); 43 | // } 44 | } 45 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/latency/AtomicHistogram.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.latency; 19 | 20 | import org.HdrHistogram.Histogram; 21 | 22 | import java.util.concurrent.TimeUnit; 23 | 24 | public class AtomicHistogram> extends BaseHDRHistogram { 25 | 26 | public AtomicHistogram(Class clazz) { 27 | this(clazz, TimeUnit.HOURS.toNanos(1), 2); 28 | } 29 | 30 | public AtomicHistogram(Class clazz, long highestTrackableValue, int numberOfSignificantValueDigits) { 31 | super(clazz, new Histogram[clazz.getEnumConstants().length]); 32 | T[] enumConstants = clazz.getEnumConstants(); 33 | for (int i = 0; i < enumConstants.length; ++i) { 34 | histograms[i] = new org.HdrHistogram.AtomicHistogram(highestTrackableValue, numberOfSignificantValueDigits); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/timeout/TimerWheelService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.uncontended.precipice.timeout; 18 | 19 | import java.util.concurrent.TimeUnit; 20 | 21 | /** 22 | * Unstable and still in development. At this time, {@link DelayQueueTimeoutService} should be used. 23 | */ 24 | public class TimerWheelService implements TimeoutService { 25 | 26 | private final long resolution; 27 | private final long startTime; 28 | 29 | public TimerWheelService(long resolution, TimeUnit unit) { 30 | this.resolution = unit.toMillis(resolution); 31 | startTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime()); 32 | } 33 | 34 | @Override 35 | public void scheduleTimeout(Timeout timeout, long timeoutMillis) { 36 | 37 | } 38 | 39 | @Override 40 | public void scheduleTimeout(Timeout timeout, long timeoutMillis, long nanoTime) { 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/timeout/PrecipiceTimeoutException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.timeout; 19 | 20 | import java.util.concurrent.TimeoutException; 21 | 22 | public class PrecipiceTimeoutException extends TimeoutException { 23 | 24 | private static final long serialVersionUID = 8491894650644110527L; 25 | private Throwable cause; 26 | 27 | public PrecipiceTimeoutException() { 28 | } 29 | 30 | public PrecipiceTimeoutException(Throwable cause) { 31 | this.cause = cause; 32 | } 33 | 34 | public PrecipiceTimeoutException(String message) { 35 | super(message); 36 | } 37 | 38 | public PrecipiceTimeoutException(String message, Throwable cause) { 39 | super(message); 40 | this.cause = cause; 41 | } 42 | 43 | @Override 44 | public Throwable getCause() { 45 | return cause; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/latency/ConcurrentHistogram.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.latency; 19 | 20 | import org.HdrHistogram.Histogram; 21 | 22 | import java.util.concurrent.TimeUnit; 23 | 24 | public class ConcurrentHistogram> extends BaseHDRHistogram { 25 | 26 | public ConcurrentHistogram(Class clazz) { 27 | this(clazz, TimeUnit.HOURS.toNanos(1), 2); 28 | } 29 | 30 | public ConcurrentHistogram(Class clazz, long highestTrackableValue, int numberOfSignificantValueDigits) { 31 | super(clazz, new Histogram[clazz.getEnumConstants().length]); 32 | T[] enumConstants = clazz.getEnumConstants(); 33 | for (int i = 0; i < enumConstants.length; ++i) { 34 | histograms[i] = new org.HdrHistogram.ConcurrentHistogram(highestTrackableValue, numberOfSignificantValueDigits); 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /precipice-threadpool/src/test/java/net/uncontended/precipice/threadpool/ThreadPoolTimeoutTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.threadpool; 19 | 20 | import net.uncontended.precipice.result.TimeoutableResult; 21 | import net.uncontended.precipice.timeout.PrecipiceTimeoutException; 22 | import org.junit.Test; 23 | 24 | import static org.mockito.Matchers.any; 25 | import static org.mockito.Matchers.eq; 26 | import static org.mockito.Mockito.mock; 27 | import static org.mockito.Mockito.verify; 28 | 29 | public class ThreadPoolTimeoutTest { 30 | 31 | @Test 32 | public void taskCancelledIfTimeout() { 33 | CancellableTask task = mock(CancellableTask.class); 34 | ThreadPoolTimeout timeout = new ThreadPoolTimeout<>(task); 35 | 36 | timeout.timeout(); 37 | 38 | verify(task).cancel(eq(TimeoutableResult.TIMEOUT), any(PrecipiceTimeoutException.class)); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/tools/StrictFlipControl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.tools; 19 | 20 | import org.HdrHistogram.WriterReaderPhaser; 21 | 22 | public class StrictFlipControl extends FlipControl { 23 | 24 | private final WriterReaderPhaser phaser = new WriterReaderPhaser(); 25 | 26 | @Override 27 | public long startRecord() { 28 | return phaser.writerCriticalSectionEnter(); 29 | } 30 | 31 | @Override 32 | public void endRecord(long permit) { 33 | phaser.writerCriticalSectionExit(permit); 34 | } 35 | 36 | @Override 37 | public synchronized V flip(V newValue) { 38 | phaser.readerLock(); 39 | 40 | try { 41 | V old = this.active; 42 | this.active = newValue; 43 | phaser.flipPhase(500000L); 44 | return old; 45 | } finally { 46 | phaser.readerUnlock(); 47 | } 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /precipice-samples/src/main/java/net/uncontended/precipice/samples/bigger/Servers.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.samples.bigger; 19 | 20 | import io.undertow.Undertow; 21 | import io.undertow.server.HttpHandler; 22 | 23 | import java.util.ArrayList; 24 | import java.util.List; 25 | 26 | public class Servers { 27 | 28 | private List servers = new ArrayList<>(); 29 | 30 | 31 | public Servers() { 32 | servers.add(create(6001, new ServerHandler("Weather-1"))); 33 | servers.add(create(7001, new ServerHandler("Weather-2"))); 34 | } 35 | 36 | public void start() { 37 | for (Undertow server : servers) { 38 | server.start(); 39 | } 40 | } 41 | 42 | public void stop() { 43 | for (Undertow server : servers) { 44 | server.stop(); 45 | } 46 | } 47 | 48 | private Undertow create(int port, HttpHandler handler) { 49 | return Undertow.builder().addHttpListener(port, "127.0.0.1").setHandler(handler).build(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/pattern/WritableSequence.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.pattern; 19 | 20 | import java.util.Iterator; 21 | 22 | public class WritableSequence implements Sequence, Iterator { 23 | 24 | private final Object[] children; 25 | private int index = 0; 26 | private int count = 0; 27 | 28 | public WritableSequence(int size) { 29 | this.children = new Object[size]; 30 | } 31 | 32 | @Override 33 | public boolean hasNext() { 34 | return index != count; 35 | } 36 | 37 | @Override 38 | public E next() { 39 | return (E) children[index++]; 40 | } 41 | 42 | @Override 43 | public Iterator iterator() { 44 | return this; 45 | } 46 | 47 | @Override 48 | public boolean isEmpty() { 49 | return count == 0; 50 | } 51 | 52 | public void add(E child) { 53 | children[count++] = child; 54 | } 55 | 56 | public void reset() { 57 | index = 0; 58 | count = 0; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/pattern/SingleReaderArrayIterable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.pattern; 19 | 20 | import java.util.Iterator; 21 | 22 | public class SingleReaderArrayIterable implements Iterator, Iterable { 23 | 24 | private int size; 25 | private Integer[] indices; 26 | private int index = 0; 27 | 28 | public SingleReaderArrayIterable(int size) { 29 | this.indices = new Integer[size]; 30 | this.size = size; 31 | } 32 | 33 | public int size() { 34 | return indices.length; 35 | } 36 | 37 | @Override 38 | public boolean hasNext() { 39 | return index != size; 40 | } 41 | 42 | @Override 43 | public Iterator iterator() { 44 | return this; 45 | } 46 | 47 | @Override 48 | public Integer next() { 49 | return indices[index++]; 50 | } 51 | 52 | public Integer[] getIndices() { 53 | return this.indices; 54 | } 55 | 56 | public void reset() { 57 | index = 0; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /precipice-reporting/src/main/java/net/uncontended/precipice/reporting/Entry.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.reporting; 19 | 20 | import io.undertow.Undertow; 21 | import io.undertow.server.handlers.PathHandler; 22 | import io.undertow.server.handlers.resource.ClassPathResourceManager; 23 | 24 | import static io.undertow.Handlers.resource; 25 | 26 | public class Entry { 27 | 28 | public static void main(String[] args) { 29 | PathHandler path = new PathHandler() 30 | .addPrefixPath("/", resource(new ClassPathResourceManager(Dashboard.class.getClassLoader(), 31 | Dashboard.class.getPackage())).addWelcomeFiles("chart.html")) 32 | .addExactPath("/api", new Dashboard()); 33 | 34 | Undertow server = Undertow.builder() 35 | .addHttpListener(6001, "127.0.0.1") 36 | .setHandler(path) 37 | .build(); 38 | server.start(); 39 | 40 | try { 41 | Thread.sleep(1000000000); 42 | } catch (InterruptedException e) { 43 | e.printStackTrace(); 44 | } 45 | server.stop(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/latency/NoOpLatency.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.latency; 19 | 20 | import net.uncontended.precipice.metrics.AbstractMetrics; 21 | import org.HdrHistogram.Histogram; 22 | 23 | public class NoOpLatency> extends AbstractMetrics implements PartitionedLatency, 24 | WritableLatency { 25 | 26 | private final Histogram generic = new Histogram(1); 27 | 28 | public NoOpLatency(Class clazz) { 29 | super(clazz); 30 | } 31 | 32 | @Override 33 | public void record(T metric, long number, long nanoLatency) { 34 | } 35 | 36 | @Override 37 | public Histogram getHistogram(T metric) { 38 | return generic; 39 | } 40 | 41 | @Override 42 | public long getValueAtPercentile(T metric, double percentile) { 43 | return 0; 44 | } 45 | 46 | @Override 47 | public boolean isHDR() { 48 | return true; 49 | } 50 | 51 | @Override 52 | public void reset() { 53 | generic.reset(); 54 | } 55 | 56 | @Override 57 | public void write(T metric, long number, long nanoLatency, long nanoTime) { 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/counts/LongCounter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.counts; 19 | 20 | import net.uncontended.precipice.metrics.AbstractMetrics; 21 | 22 | public class LongCounter> extends AbstractMetrics implements PartitionedCount { 23 | 24 | private final long[] metrics; 25 | 26 | public LongCounter(Class clazz) { 27 | super(clazz); 28 | T[] metricValues = clazz.getEnumConstants(); 29 | 30 | metrics = new long[metricValues.length]; 31 | } 32 | 33 | @Override 34 | public void add(T metric, long delta) { 35 | metrics[metric.ordinal()] += delta; 36 | } 37 | 38 | @Override 39 | public long getCount(T metric) { 40 | return metrics[metric.ordinal()]; 41 | } 42 | 43 | @Override 44 | public long total() { 45 | long total = 0; 46 | for (long metric : metrics) { 47 | total += metric; 48 | } 49 | return total; 50 | } 51 | 52 | @Override 53 | public void reset() { 54 | int length = metrics.length; 55 | for (int i = 0; i < length; ++i) { 56 | metrics[i] = 0; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/counts/CountRecorderBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.counts; 19 | 20 | import net.uncontended.precipice.metrics.tools.MetricRecorder; 21 | import net.uncontended.precipice.metrics.tools.RecorderBuilder; 22 | import net.uncontended.precipice.metrics.tools.RelaxedFlipControl; 23 | 24 | public class CountRecorderBuilder> extends RecorderBuilder, CountRecorder> { 25 | 26 | private final Class clazz; 27 | 28 | public CountRecorderBuilder(Class clazz) { 29 | this.clazz = clazz; 30 | } 31 | 32 | @Override 33 | public CountRecorder build() { 34 | if (allocator == null) { 35 | allocator = Counters.longAdder(clazz); 36 | } 37 | 38 | if (active == null) { 39 | active = allocator.allocateNew(); 40 | } 41 | if (inactive == null) { 42 | inactive = allocator.allocateNew(); 43 | } 44 | 45 | if (flipControl == null) { 46 | flipControl = new RelaxedFlipControl<>(); 47 | } 48 | 49 | return new CountRecorder(new MetricRecorder<>(active, inactive, flipControl, clock)); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /precipice-reporting/src/main/java/net/uncontended/precipice/reporting/registry/Slice.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.uncontended.precipice.reporting.registry; 18 | 19 | import net.uncontended.precipice.Failable; 20 | 21 | public class Slice & Failable, Rejected extends Enum> { 22 | public final Class resultClazz; 23 | public final Class rejectedClazz; 24 | 25 | public final long[] totalResultCounts; 26 | public final long[] resultCounts; 27 | 28 | public final long[] totalRejectedCounts; 29 | public final long[] rejectedCounts; 30 | 31 | public long startEpoch = -1; 32 | public long endEpoch = -1; 33 | 34 | public Slice(Class resultClazz, Class rejectedClazz) { 35 | this.resultClazz = resultClazz; 36 | this.rejectedClazz = rejectedClazz; 37 | int resultLength = resultClazz.getEnumConstants().length; 38 | int rejectedLength = rejectedClazz.getEnumConstants().length; 39 | 40 | this.totalResultCounts = new long[resultLength]; 41 | this.resultCounts = new long[resultLength]; 42 | this.totalRejectedCounts = new long[rejectedLength]; 43 | this.rejectedCounts = new long[rejectedLength]; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/latency/LatencyRecorderBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.latency; 19 | 20 | import net.uncontended.precipice.metrics.tools.MetricRecorder; 21 | import net.uncontended.precipice.metrics.tools.RecorderBuilder; 22 | import net.uncontended.precipice.metrics.tools.RelaxedFlipControl; 23 | 24 | public class LatencyRecorderBuilder> extends RecorderBuilder, LatencyRecorder> { 25 | 26 | private final Class clazz; 27 | 28 | public LatencyRecorderBuilder(Class clazz) { 29 | this.clazz = clazz; 30 | } 31 | 32 | @Override 33 | public LatencyRecorder build() { 34 | if (allocator == null) { 35 | allocator = Latency.concurrentHDRHistogram(clazz); 36 | } 37 | 38 | if (active == null) { 39 | active = allocator.allocateNew(); 40 | } 41 | if (inactive == null) { 42 | inactive = allocator.allocateNew(); 43 | } 44 | 45 | if (flipControl == null) { 46 | flipControl = new RelaxedFlipControl<>(); 47 | } 48 | 49 | return new LatencyRecorder(new MetricRecorder<>(active, inactive, flipControl, clock)); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/counts/TotalCounts.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.counts; 19 | 20 | import net.uncontended.precipice.metrics.AbstractMetrics; 21 | 22 | public class TotalCounts> extends AbstractMetrics implements WritableCounts, PartitionedCount { 23 | 24 | private final PartitionedCount counter; 25 | 26 | public TotalCounts(Class clazz) { 27 | super(clazz); 28 | counter = new LongAdderCounter<>(clazz); 29 | } 30 | 31 | public TotalCounts(PartitionedCount counter) { 32 | super(counter.getMetricClazz()); 33 | this.counter = counter; 34 | } 35 | 36 | @Override 37 | public void write(T result, long number, long nanoTime) { 38 | counter.add(result, number); 39 | } 40 | 41 | @Override 42 | public long getCount(T metric) { 43 | return counter.getCount(metric); 44 | } 45 | 46 | @Override 47 | public long total() { 48 | return counter.total(); 49 | } 50 | 51 | @Override 52 | public void add(T metric, long delta) { 53 | counter.add(metric, delta); 54 | 55 | } 56 | 57 | @Override 58 | public void reset() { 59 | counter.reset(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /precipice-threadpool/src/test/java/net/uncontended/precipice/threadpool/test_utils/TestCallable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.threadpool.test_utils; 19 | 20 | import java.util.concurrent.Callable; 21 | import java.util.concurrent.CountDownLatch; 22 | 23 | public class TestCallable { 24 | 25 | public static Callable success() { 26 | return success("Success"); 27 | } 28 | 29 | public static Callable success(final T result) { 30 | return new Callable() { 31 | @Override 32 | public T call() throws Exception { 33 | return result; 34 | } 35 | }; 36 | } 37 | 38 | public static Callable blocked(final CountDownLatch latch) { 39 | return new Callable() { 40 | 41 | @Override 42 | public String call() throws Exception { 43 | latch.await(); 44 | return "Success"; 45 | } 46 | }; 47 | } 48 | 49 | public static Callable erred(final Exception exception) { 50 | return new Callable() { 51 | @Override 52 | public String call() throws Exception { 53 | throw exception; 54 | } 55 | }; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/tools/RecorderBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.tools; 19 | 20 | import net.uncontended.precipice.time.Clock; 21 | import net.uncontended.precipice.time.SystemTime; 22 | 23 | public abstract class RecorderBuilder { 24 | 25 | protected FlipControl flipControl; 26 | 27 | protected T active; 28 | protected T inactive; 29 | protected Allocator allocator; 30 | protected Clock clock = SystemTime.getInstance(); 31 | 32 | public RecorderBuilder initialActive(T active) { 33 | this.active = active; 34 | return this; 35 | } 36 | 37 | public RecorderBuilder initialInactive(T inactive) { 38 | this.inactive = inactive; 39 | return this; 40 | } 41 | 42 | public RecorderBuilder withAllocator(Allocator allocator) { 43 | this.allocator = allocator; 44 | return this; 45 | } 46 | 47 | public RecorderBuilder withRecorder(FlipControl flipControl) { 48 | this.flipControl = flipControl; 49 | return this; 50 | } 51 | 52 | public RecorderBuilder withClock(Clock clock) { 53 | this.clock = clock; 54 | return this; 55 | } 56 | 57 | public abstract S build(); 58 | 59 | } 60 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/counts/AtomicLongCounter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.counts; 19 | 20 | import net.uncontended.precipice.metrics.AbstractMetrics; 21 | 22 | import java.util.concurrent.atomic.AtomicLongArray; 23 | 24 | public class AtomicLongCounter> extends AbstractMetrics implements PartitionedCount { 25 | 26 | private final AtomicLongArray metrics; 27 | 28 | public AtomicLongCounter(Class clazz) { 29 | super(clazz); 30 | T[] metricValues = clazz.getEnumConstants(); 31 | 32 | metrics = new AtomicLongArray(metricValues.length); 33 | } 34 | 35 | @Override 36 | public void add(T metric, long delta) { 37 | metrics.getAndAdd(metric.ordinal(), delta); 38 | } 39 | 40 | @Override 41 | public long getCount(T metric) { 42 | return metrics.get(metric.ordinal()); 43 | } 44 | 45 | @Override 46 | public long total() { 47 | long total = 0; 48 | int length = metrics.length(); 49 | for (int i = 0; i < length; ++i) { 50 | total += metrics.get(i); 51 | } 52 | return total; 53 | } 54 | 55 | @Override 56 | public void reset() { 57 | int length = metrics.length(); 58 | for (int i = 0; i < length; ++i) { 59 | metrics.set(i, 0); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/counts/LongAdderCounter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.counts; 19 | 20 | import net.uncontended.precipice.metrics.AbstractMetrics; 21 | 22 | import java.util.concurrent.atomic.LongAdder; 23 | 24 | public class LongAdderCounter> extends AbstractMetrics implements PartitionedCount { 25 | 26 | private final LongAdder[] metrics; 27 | 28 | public LongAdderCounter(Class clazz) { 29 | super(clazz); 30 | T[] metricValues = clazz.getEnumConstants(); 31 | 32 | metrics = new LongAdder[metricValues.length]; 33 | for (T metric : metricValues) { 34 | metrics[metric.ordinal()] = new LongAdder(); 35 | } 36 | } 37 | 38 | @Override 39 | public void add(T metric, long delta) { 40 | metrics[metric.ordinal()].add(delta); 41 | } 42 | 43 | @Override 44 | public long getCount(T metric) { 45 | return metrics[metric.ordinal()].longValue(); 46 | } 47 | 48 | @Override 49 | public long total() { 50 | long total = 0; 51 | for (LongAdder adder : metrics) { 52 | total += adder.longValue(); 53 | } 54 | return total; 55 | } 56 | 57 | @Override 58 | public void reset() { 59 | for (LongAdder adder : metrics) { 60 | adder.reset(); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/circuit/CircuitBreakerConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | package net.uncontended.precipice.circuit; 18 | 19 | import java.util.concurrent.TimeUnit; 20 | 21 | public class CircuitBreakerConfig> { 22 | 23 | public final Rejected reason; 24 | public final Rejected forcedReason; 25 | public final int failurePercentageThreshold; 26 | public final long failureThreshold; 27 | public final long sampleSizeThreshold; 28 | public final long trailingPeriodNanos; 29 | public final long healthRefreshNanos; 30 | public final long backOffTimeNanos; 31 | 32 | public CircuitBreakerConfig(Rejected reason, Rejected forcedReason, long failureThreshold, int failurePercentageThreshold, 33 | long sampleSizeThreshold, long trailingPeriodMillis, long healthRefreshMillis, long backOffTimeMillis) { 34 | this.reason = reason; 35 | this.forcedReason = forcedReason; 36 | this.failureThreshold = failureThreshold; 37 | this.failurePercentageThreshold = failurePercentageThreshold; 38 | this.sampleSizeThreshold = sampleSizeThreshold; 39 | trailingPeriodNanos = TimeUnit.MILLISECONDS.toNanos(trailingPeriodMillis); 40 | healthRefreshNanos = TimeUnit.MILLISECONDS.toNanos(healthRefreshMillis); 41 | backOffTimeNanos = TimeUnit.MILLISECONDS.toNanos(backOffTimeMillis); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /precipice-core/src/test/java/net/uncontended/precipice/test_utils/TestCallables.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.test_utils; 19 | 20 | import java.util.concurrent.Callable; 21 | import java.util.concurrent.CountDownLatch; 22 | 23 | public class TestCallables { 24 | 25 | public static Callable success(final long waitTime) { 26 | return success(waitTime, "Success"); 27 | } 28 | 29 | public static Callable success(final long waitTime, final String result) { 30 | return new Callable() { 31 | @Override 32 | public String call() throws Exception { 33 | if (waitTime != 0) { 34 | Thread.sleep(waitTime); 35 | } 36 | return result; 37 | } 38 | }; 39 | } 40 | 41 | public static Callable blocked(final CountDownLatch latch) { 42 | return new Callable() { 43 | 44 | @Override 45 | public String call() throws Exception { 46 | latch.await(); 47 | return "Success"; 48 | } 49 | }; 50 | } 51 | 52 | public static Callable erred(final Exception exception) { 53 | return new Callable() { 54 | @Override 55 | public String call() throws Exception { 56 | throw exception; 57 | } 58 | }; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /precipice-reporting/src/main/java/net/uncontended/precipice/reporting/Dashboard.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.reporting; 19 | 20 | import io.undertow.server.HttpHandler; 21 | import io.undertow.server.HttpServerExchange; 22 | import io.undertow.util.Headers; 23 | 24 | import java.io.OutputStream; 25 | 26 | public class Dashboard implements HttpHandler { 27 | 28 | @Override 29 | public void handleRequest(HttpServerExchange exchange) throws Exception { 30 | 31 | exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "application/json"); 32 | if (exchange.isInIoThread()) { 33 | exchange.dispatch(this); 34 | return; 35 | } else { 36 | exchange.startBlocking(); 37 | } 38 | OutputStream outputStream = exchange.getOutputStream(); 39 | outputStream.write("[".getBytes()); 40 | for (int i = 0; i < 5; ++i) { 41 | if (i != 4) { 42 | outputStream.write(String.format("{\"time\": %s, \"y\": %s},", System.currentTimeMillis(), i) 43 | .getBytes()); 44 | } else { 45 | outputStream.write(String.format("{\"time\": %s, \"y\": %s}", System.currentTimeMillis(), i) 46 | .getBytes()); 47 | 48 | } 49 | Thread.sleep(500); 50 | } 51 | outputStream.write("]".getBytes()); 52 | outputStream.close(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/semaphore/UnlimitedSemaphore.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.semaphore; 19 | 20 | import net.uncontended.precipice.BackPressure; 21 | import net.uncontended.precipice.Failable; 22 | import net.uncontended.precipice.GuardRail; 23 | 24 | import java.util.concurrent.atomic.AtomicLong; 25 | 26 | public class UnlimitedSemaphore> implements BackPressure, PrecipiceSemaphore { 27 | 28 | private final AtomicLong concurrencyLevel = new AtomicLong(0); 29 | 30 | @Override 31 | public Rejected acquirePermit(long number, long nanoTime) { 32 | concurrencyLevel.addAndGet(number); 33 | return null; 34 | } 35 | 36 | @Override 37 | public void releasePermit(long number, long nanoTime) { 38 | concurrencyLevel.addAndGet(-number); 39 | } 40 | 41 | 42 | @Override 43 | public void releasePermit(long number, Failable result, long nanoTime) { 44 | concurrencyLevel.addAndGet(-number); 45 | } 46 | 47 | @Override 48 | public & Failable> void registerGuardRail(GuardRail guardRail) { 49 | } 50 | 51 | 52 | @Override 53 | public long maxConcurrencyLevel() { 54 | return -1; 55 | } 56 | 57 | @Override 58 | public long remainingCapacity() { 59 | return -1; 60 | } 61 | 62 | @Override 63 | public long currentConcurrencyLevel() { 64 | return concurrencyLevel.get(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /precipice-core/src/test/java/net/uncontended/precipice/pattern/ShotgunTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.pattern; 19 | 20 | import org.junit.Test; 21 | 22 | import java.util.Iterator; 23 | 24 | import static org.junit.Assert.*; 25 | 26 | public class ShotgunTest { 27 | 28 | @Test 29 | public void indicesAreReturnedUniformly() { 30 | Shotgun shotgun = new Shotgun(3, 2); 31 | 32 | int firstTotal = 0; 33 | int secondTotal = 0; 34 | int thirdTotal = 0; 35 | for (int i = 0; i < 5000; ++i) { 36 | Iterator indices = shotgun.nextIndices().iterator(); 37 | int first = indices.next(); 38 | int second = indices.next(); 39 | int third = indices.next(); 40 | assertFalse(indices.hasNext()); 41 | assertNotEquals(first, second); 42 | assertNotEquals(first, third); 43 | assertNotEquals(second, third); 44 | firstTotal += first; 45 | secondTotal += second; 46 | thirdTotal += third; 47 | } 48 | 49 | double firstMean = (double) firstTotal / 5000; 50 | double secondMean = (double) secondTotal / 5000; 51 | double thirdMean = (double) thirdTotal / 5000; 52 | 53 | String message = "Concerning distribution of indices returned"; 54 | assertTrue(message, 0.15 > Math.abs(firstMean - secondMean)); 55 | assertTrue(message, 0.15 > Math.abs(firstMean - thirdMean)); 56 | assertTrue(message, 0.15 > Math.abs(secondMean - thirdMean)); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/Completable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice; 19 | 20 | /** 21 | * A context that can be completed with the result of a computation. 22 | * The context can only be completed once. This holds true for both an 23 | * successes and exceptions. So if it is completed with an exception, 24 | * it cannot be completed successfully. 25 | * 26 | * @param the type of the result for this promise 27 | * @param the type of the value for this completable 28 | */ 29 | public interface Completable { 30 | 31 | /** 32 | * Completes this context successfully with the result. A boolean will be 33 | * returned indicating if it was completed successfully. 34 | * 35 | * @param result of the computation 36 | * @param value of the computation 37 | * @return if the context was competed successfully 38 | */ 39 | boolean complete(Result result, V value); 40 | 41 | /** 42 | * Completes this context with an exception. A boolean will be returned 43 | * indicating if it was completed successfully. 44 | * 45 | * @param result of the computation 46 | * @param exception of the computation 47 | * @return if the context was competed successfully 48 | */ 49 | boolean completeExceptionally(Result result, Throwable exception); 50 | 51 | /** 52 | * Returns a view of the result of of this completable. 53 | * 54 | * @return the result view 55 | */ 56 | ResultView resultView(); 57 | } 58 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/latency/TotalLatency.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.latency; 19 | 20 | import net.uncontended.precipice.metrics.AbstractMetrics; 21 | import org.HdrHistogram.Histogram; 22 | 23 | public class TotalLatency> extends AbstractMetrics implements WritableLatency, PartitionedLatency { 24 | 25 | private final PartitionedLatency latency; 26 | 27 | public TotalLatency(PartitionedLatency latency) { 28 | super(latency.getMetricClazz()); 29 | this.latency = latency; 30 | } 31 | 32 | public TotalLatency(Class clazz) { 33 | super(clazz); 34 | latency = new ConcurrentHistogram<>(clazz); 35 | } 36 | 37 | @Override 38 | public void record(T result, long number, long nanoLatency) { 39 | latency.record(result, number, nanoLatency); 40 | } 41 | 42 | @Override 43 | public Histogram getHistogram(T metric) { 44 | return latency.getHistogram(metric); 45 | } 46 | 47 | @Override 48 | public long getValueAtPercentile(T metric, double percentile) { 49 | return latency.getValueAtPercentile(metric, percentile); 50 | } 51 | 52 | @Override 53 | public boolean isHDR() { 54 | return latency.isHDR(); 55 | } 56 | 57 | @Override 58 | public void reset() { 59 | latency.reset(); 60 | } 61 | 62 | @Override 63 | public void write(T metric, long number, long nanoLatency, long nanoTime) { 64 | record(metric, number, nanoLatency); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/latency/BaseHDRHistogram.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.latency; 19 | 20 | import net.uncontended.precipice.metrics.AbstractMetrics; 21 | import org.HdrHistogram.Histogram; 22 | 23 | public class BaseHDRHistogram> extends AbstractMetrics implements PartitionedLatency { 24 | protected final Histogram[] histograms; 25 | 26 | public BaseHDRHistogram(Class clazz, Histogram[] histograms) { 27 | super(clazz); 28 | this.histograms = histograms; 29 | } 30 | 31 | @Override 32 | public void record(T metric, long number, long nanoLatency) { 33 | Histogram histogram = histograms[metric.ordinal()]; 34 | long highestTrackableValue = histogram.getHighestTrackableValue(); 35 | long potentiallyTruncated = highestTrackableValue > nanoLatency ? nanoLatency : highestTrackableValue; 36 | histogram.recordValueWithCount(potentiallyTruncated, number); 37 | } 38 | 39 | @Override 40 | public Histogram getHistogram(T metric) { 41 | return histograms[metric.ordinal()]; 42 | } 43 | 44 | @Override 45 | public long getValueAtPercentile(T metric, double percentile) { 46 | return histograms[metric.ordinal()].getValueAtPercentile(percentile); 47 | } 48 | 49 | @Override 50 | public boolean isHDR() { 51 | return true; 52 | } 53 | 54 | @Override 55 | public void reset() { 56 | for (Histogram histogram : histograms) { 57 | histogram.reset(); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/CallService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice; 19 | 20 | import net.uncontended.precipice.factories.Synchronous; 21 | import net.uncontended.precipice.result.TimeoutableResult; 22 | import net.uncontended.precipice.timeout.PrecipiceTimeoutException; 23 | 24 | import java.util.concurrent.Callable; 25 | 26 | public class CallService> implements Precipice { 27 | 28 | private final GuardRail guardRail; 29 | 30 | public CallService(GuardRail guardRail) { 31 | this.guardRail = guardRail; 32 | } 33 | 34 | @Override 35 | public GuardRail guardRail() { 36 | return guardRail; 37 | } 38 | 39 | public T call(Callable callable) throws Exception { 40 | return call(callable, 1L); 41 | } 42 | 43 | public T call(Callable callable, long permitNumber) throws Exception { 44 | Completable completable = Synchronous.acquirePermitsAndCompletable(guardRail, permitNumber); 45 | 46 | try { 47 | T result = callable.call(); 48 | completable.complete(TimeoutableResult.SUCCESS, result); 49 | return result; 50 | } catch (PrecipiceTimeoutException e) { 51 | completable.completeExceptionally(TimeoutableResult.TIMEOUT, e); 52 | throw e; 53 | } catch (Exception e) { 54 | completable.completeExceptionally(TimeoutableResult.ERROR, e); 55 | throw e; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /precipice-core/src/test/java/net/uncontended/precipice/metrics/latency/RollingLatencyTest.java: -------------------------------------------------------------------------------- 1 | package net.uncontended.precipice.metrics.latency; 2 | 3 | import net.uncontended.precipice.metrics.IntervalIterator; 4 | import net.uncontended.precipice.metrics.tools.RollingMetrics; 5 | import net.uncontended.precipice.rejected.Rejected; 6 | import net.uncontended.precipice.rejected.Unrejectable; 7 | import net.uncontended.precipice.result.TimeoutableResult; 8 | import net.uncontended.precipice.time.Clock; 9 | import org.junit.Before; 10 | import org.junit.Test; 11 | import org.mockito.Mock; 12 | import org.mockito.MockitoAnnotations; 13 | 14 | import static org.junit.Assert.assertSame; 15 | import static org.mockito.Matchers.any; 16 | import static org.mockito.Matchers.eq; 17 | import static org.mockito.Mockito.*; 18 | 19 | public class RollingLatencyTest { 20 | 21 | @Mock 22 | private Clock systemTime; 23 | @Mock 24 | private RollingMetrics> baseMetrics; 25 | @Mock 26 | private PartitionedLatency histogram; 27 | 28 | 29 | private RollingLatency latencies; 30 | 31 | @Before 32 | public void setUp() { 33 | MockitoAnnotations.initMocks(this); 34 | when(baseMetrics.current()).thenReturn(histogram); 35 | when(histogram.getMetricClazz()).thenReturn(TimeoutableResult.class); 36 | latencies = new RollingLatency(baseMetrics); 37 | } 38 | 39 | @Test 40 | public void clazzComesFromHistogram() { 41 | assertSame(TimeoutableResult.class, latencies.getMetricClazz()); 42 | } 43 | 44 | @Test 45 | public void writeUsesBaseMetrics() { 46 | when(baseMetrics.current(2000L)).thenReturn(histogram); 47 | 48 | latencies.write(TimeoutableResult.ERROR, 5, 300L, 2000L); 49 | 50 | verify(histogram).record(TimeoutableResult.ERROR, 5, 300L); 51 | } 52 | 53 | @Test 54 | public void intervalsCallUsesNoOpForDefault() { 55 | IntervalIterator iterator = mock(IntervalIterator.class); 56 | when(baseMetrics.intervalsWithDefault(eq(2000L), any(NoOpLatency.class))).thenReturn(iterator); 57 | 58 | IntervalIterator> intervals = latencies.intervals(2000L); 59 | 60 | assertSame(iterator, intervals); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/tools/RollingMetrics.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.tools; 19 | 20 | import net.uncontended.precipice.metrics.IntervalIterator; 21 | import net.uncontended.precipice.metrics.Rolling; 22 | import net.uncontended.precipice.time.Clock; 23 | 24 | public class RollingMetrics implements Rolling { 25 | 26 | private final Allocator allocator; 27 | private final Clock clock; 28 | private final CircularBuffer buffer; 29 | 30 | public RollingMetrics(Allocator allocator, CircularBuffer buffer, Clock clock) { 31 | this.allocator = allocator; 32 | this.buffer = buffer; 33 | this.clock = clock; 34 | } 35 | 36 | @Override 37 | public T current() { 38 | return current(clock.nanoTime()); 39 | } 40 | 41 | @Override 42 | public T current(long nanoTime) { 43 | T current = buffer.getSlot(nanoTime); 44 | if (current == null) { 45 | current = buffer.putOrGet(nanoTime, allocator.allocateNew()); 46 | } 47 | return current; 48 | } 49 | 50 | @Override 51 | public IntervalIterator intervals() { 52 | return intervals(clock.nanoTime()); 53 | } 54 | 55 | @Override 56 | public IntervalIterator intervals(long nanoTime) { 57 | return buffer.intervals(nanoTime, null); 58 | } 59 | 60 | public IntervalIterator intervalsWithDefault(T default0) { 61 | return buffer.intervals(clock.nanoTime(), default0); 62 | } 63 | 64 | public IntervalIterator intervalsWithDefault(long nanoTime, T default0) { 65 | return buffer.intervals(nanoTime, default0); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/pattern/Shotgun.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.pattern; 19 | 20 | import java.util.Random; 21 | import java.util.concurrent.ThreadLocalRandom; 22 | 23 | public class Shotgun implements PatternStrategy { 24 | 25 | private final int acquireCount; 26 | private final int serviceCount; 27 | private final Integer[] serviceIndices; 28 | 29 | public Shotgun(int serviceCount, int acquireCount) { 30 | this.serviceCount = serviceCount; 31 | this.acquireCount = acquireCount; 32 | this.serviceIndices = new Integer[serviceCount]; 33 | for (int i = 0; i < serviceCount; ++i) { 34 | serviceIndices[i] = i; 35 | } 36 | } 37 | 38 | @Override 39 | public Iterable nextIndices() { 40 | SingleReaderArrayIterable iterable = new SingleReaderArrayIterable(serviceCount); 41 | Integer[] orderToTry = iterable.getIndices(); 42 | 43 | System.arraycopy(serviceIndices, 0, orderToTry, 0, serviceCount); 44 | shuffle(orderToTry); 45 | 46 | return iterable; 47 | } 48 | 49 | @Override 50 | public int acquireCount() { 51 | return acquireCount; 52 | } 53 | 54 | private static void shuffle(Integer[] orderToTry) { 55 | int index; 56 | Random random = ThreadLocalRandom.current(); 57 | for (int i = orderToTry.length - 1; i > 0; i--) { 58 | index = random.nextInt(i + 1); 59 | if (index != i) { 60 | orderToTry[index] ^= orderToTry[i]; 61 | orderToTry[i] ^= orderToTry[index]; 62 | orderToTry[index] ^= orderToTry[i]; 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/circuit/NoOpCircuitBreaker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.circuit; 19 | 20 | import net.uncontended.precipice.Failable; 21 | import net.uncontended.precipice.GuardRail; 22 | 23 | import java.util.concurrent.atomic.AtomicBoolean; 24 | 25 | public class NoOpCircuitBreaker> implements CircuitBreaker { 26 | private final AtomicBoolean circuitOpen = new AtomicBoolean(false); 27 | private final Rejected reason; 28 | 29 | public NoOpCircuitBreaker(Rejected reason) { 30 | this.reason = reason; 31 | } 32 | 33 | @Override 34 | public Rejected acquirePermit(long number, long nanoTime) { 35 | if (circuitOpen.get()) { 36 | return reason; 37 | } 38 | return null; 39 | } 40 | 41 | @Override 42 | public void releasePermit(long number, long nanoTime) { 43 | 44 | } 45 | 46 | @Override 47 | public void releasePermit(long number, Failable result, long nanoTime) { 48 | 49 | } 50 | 51 | @Override 52 | public & Failable> void registerGuardRail(GuardRail guardRail) { 53 | } 54 | 55 | @Override 56 | public boolean isOpen() { 57 | return circuitOpen.get(); 58 | } 59 | 60 | @Override 61 | public CircuitBreakerConfig getBreakerConfig() { 62 | return null; 63 | } 64 | 65 | @Override 66 | public void setBreakerConfig(CircuitBreakerConfig breakerConfig) { 67 | } 68 | 69 | @Override 70 | public void forceOpen() { 71 | circuitOpen.set(true); 72 | } 73 | 74 | @Override 75 | public void forceClosed() { 76 | circuitOpen.set(false); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /precipice-core/src/test/java/net/uncontended/precipice/metrics/tools/StrictFlipControlTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.tools; 19 | 20 | import org.junit.Test; 21 | 22 | import java.util.concurrent.CountDownLatch; 23 | import java.util.concurrent.Executor; 24 | import java.util.concurrent.Executors; 25 | import java.util.concurrent.locks.LockSupport; 26 | 27 | import static org.junit.Assert.assertTrue; 28 | 29 | public class StrictFlipControlTest { 30 | 31 | private final Executor executors = Executors.newCachedThreadPool(); 32 | private final FlipControl flipControl = new StrictFlipControl<>(); 33 | 34 | @Test 35 | public void testThatNoWritesHappenAfterFlip() throws InterruptedException { 36 | flipControl.flip(new BooleanHolder()); 37 | for (int j = 0; j < 5; ++j) { 38 | final CountDownLatch latch = new CountDownLatch(5); 39 | for (int i = 0; i < 10; ++i) { 40 | executors.execute(new Runnable() { 41 | @Override 42 | public void run() { 43 | long permit = flipControl.startRecord(); 44 | BooleanHolder active = flipControl.active(); 45 | LockSupport.parkNanos(10000); 46 | active.marker = false; 47 | flipControl.endRecord(permit); 48 | latch.countDown(); 49 | } 50 | }); 51 | } 52 | latch.await(); 53 | BooleanHolder old = flipControl.flip(new BooleanHolder()); 54 | old.marker = true; 55 | LockSupport.parkNanos(1000000); 56 | 57 | assertTrue(old.marker); 58 | } 59 | 60 | } 61 | 62 | private static class BooleanHolder { 63 | private volatile boolean marker; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /precipice-threadpool/src/main/java/net/uncontended/precipice/threadpool/utils/TaskFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.threadpool.utils; 19 | 20 | import net.uncontended.precipice.concurrent.PrecipicePromise; 21 | import net.uncontended.precipice.result.TimeoutableResult; 22 | import net.uncontended.precipice.threadpool.CancellableTask; 23 | 24 | import java.util.concurrent.Callable; 25 | import java.util.concurrent.TimeoutException; 26 | 27 | public class TaskFactory { 28 | 29 | private static final CancellableTask.ResultToStatus resultToStatus = new Success(); 30 | private static final CancellableTask.ThrowableToStatus throwableToStatus = new Error(); 31 | 32 | public static CancellableTask 33 | createTask(Callable callable, PrecipicePromise promise) { 34 | CancellableTask.ResultToStatus castedResultToStatus = 35 | (CancellableTask.ResultToStatus) resultToStatus; 36 | return new CancellableTask<>(castedResultToStatus, throwableToStatus, callable, promise); 37 | } 38 | 39 | private static class Success implements CancellableTask.ResultToStatus { 40 | 41 | @Override 42 | public TimeoutableResult resultToStatus(Object result) { 43 | return TimeoutableResult.SUCCESS; 44 | } 45 | } 46 | 47 | private static class Error implements CancellableTask.ThrowableToStatus { 48 | 49 | @Override 50 | public TimeoutableResult throwableToStatus(Throwable throwable) { 51 | if (throwable instanceof TimeoutException) { 52 | return TimeoutableResult.TIMEOUT; 53 | } else { 54 | return TimeoutableResult.ERROR; 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /precipice-core/src/test/java/net/uncontended/precipice/semaphore/UnlimitedSemaphoreTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.semaphore; 19 | 20 | import net.uncontended.precipice.rejected.Unrejectable; 21 | import org.junit.Test; 22 | 23 | import java.util.concurrent.CountDownLatch; 24 | import java.util.concurrent.Executor; 25 | import java.util.concurrent.Executors; 26 | import java.util.concurrent.ThreadLocalRandom; 27 | 28 | import static org.junit.Assert.assertEquals; 29 | 30 | public class UnlimitedSemaphoreTest { 31 | 32 | private final Executor executor = Executors.newCachedThreadPool(); 33 | 34 | private final UnlimitedSemaphore semaphore = new UnlimitedSemaphore<>(); 35 | 36 | @Test 37 | public void testSemaphore() throws InterruptedException { 38 | int acquireCount = ThreadLocalRandom.current().nextInt(20) + 5; 39 | CountDownLatch latch = new CountDownLatch(acquireCount); 40 | for (int i = 0; i < acquireCount; ++i) { 41 | executor.execute(new Runnable() { 42 | @Override 43 | public void run() { 44 | semaphore.acquirePermit(3, acquireCount); 45 | latch.countDown(); 46 | } 47 | }); 48 | } 49 | latch.await(); 50 | 51 | assertEquals(acquireCount * 3, semaphore.currentConcurrencyLevel()); 52 | 53 | CountDownLatch latch2 = new CountDownLatch(acquireCount); 54 | for (int i = 0; i < acquireCount; ++i) { 55 | executor.execute(new Runnable() { 56 | @Override 57 | public void run() { 58 | semaphore.releasePermit(3, acquireCount); 59 | latch2.countDown(); 60 | } 61 | }); 62 | } 63 | latch2.await(); 64 | 65 | assertEquals(0, semaphore.currentConcurrencyLevel()); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/tools/RollingBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.tools; 19 | 20 | import net.uncontended.precipice.time.Clock; 21 | import net.uncontended.precipice.time.SystemTime; 22 | 23 | import java.util.concurrent.TimeUnit; 24 | 25 | public abstract class RollingBuilder { 26 | 27 | protected Clock clock = SystemTime.getInstance(); 28 | protected int buckets = -1; 29 | protected long nanosPerBucket = -1; 30 | protected Allocator allocator; 31 | 32 | public RollingBuilder bucketCount(int buckets) { 33 | this.buckets = buckets; 34 | return this; 35 | } 36 | 37 | public RollingBuilder bucketResolution(long duration, TimeUnit unit) { 38 | nanosPerBucket = unit.toNanos(duration); 39 | return this; 40 | } 41 | 42 | public RollingBuilder withClock(Clock clock) { 43 | this.clock = clock; 44 | return this; 45 | } 46 | 47 | public RollingBuilder withAllocator(Allocator allocator) { 48 | this.allocator = allocator; 49 | return this; 50 | } 51 | 52 | public abstract S build(); 53 | 54 | protected RollingMetrics buildRollingMetrics() { 55 | if (allocator == null) { 56 | throw new IllegalArgumentException("Allocator cannot be null."); 57 | } 58 | if (buckets < 0) { 59 | throw new IllegalArgumentException("Number of buckets tracked must be positive. Found: " + buckets); 60 | } 61 | 62 | if (nanosPerBucket <= 0) { 63 | throw new IllegalArgumentException("Nano seconds per bucket must be greater than 0. Found: " + nanosPerBucket); 64 | } 65 | 66 | CircularBuffer circularBuffer = new CircularBuffer<>(buckets, nanosPerBucket, clock.nanoTime()); 67 | 68 | return new RollingMetrics<>(allocator, circularBuffer, clock); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/tools/MetricRecorder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.tools; 19 | 20 | import net.uncontended.precipice.metrics.Resettable; 21 | import net.uncontended.precipice.time.Clock; 22 | 23 | public class MetricRecorder implements Recorder { 24 | 25 | private final FlipControl flipControl; 26 | private final Clock clock; 27 | private T inactive; 28 | private volatile long intervalStart; 29 | 30 | public MetricRecorder(T active, T inactive, FlipControl flipControl, Clock clock) { 31 | this.flipControl = flipControl; 32 | this.clock = clock; 33 | this.flipControl.flip(active); 34 | this.inactive = inactive; 35 | this.intervalStart = clock.nanoTime(); 36 | } 37 | 38 | @Override 39 | public T activeInterval() { 40 | return flipControl.active(); 41 | } 42 | 43 | @Override 44 | public long activeIntervalStart() { 45 | return intervalStart; 46 | } 47 | 48 | @Override 49 | public T captureInterval() { 50 | return captureInterval(clock.nanoTime()); 51 | } 52 | 53 | @Override 54 | public T captureInterval(long nanotime) { 55 | inactive.reset(); 56 | return captureInterval(inactive, nanotime); 57 | } 58 | 59 | @Override 60 | public T captureInterval(T newInterval) { 61 | return captureInterval(newInterval, clock.nanoTime()); 62 | } 63 | 64 | @Override 65 | public synchronized T captureInterval(T newInterval, long nanoTime) { 66 | T newlyInactive = flipControl.flip(newInterval); 67 | inactive = newlyInactive; 68 | intervalStart = nanoTime; 69 | return newlyInactive; 70 | } 71 | 72 | public long startRecord() { 73 | return flipControl.startRecord(); 74 | } 75 | 76 | public void endRecord(long permit) { 77 | flipControl.endRecord(permit); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/BackPressure.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice; 19 | 20 | /** 21 | * A mechanism to provide back pressure for task execution. 22 | * 23 | * @param the type for rejection reasons 24 | */ 25 | public interface BackPressure> { 26 | 27 | /** 28 | * Acquires the request permits for task execution. If the execution is denied due 29 | * to back pressure, then a the rejected reason is returned. If the permits are 30 | * successfully acquired, then null is returned. 31 | * 32 | * @param number of permits requested 33 | * @param nanoTime currentInterval nanosecond time 34 | * @return the reason for rejection if permit acquisition fails 35 | */ 36 | Rejected acquirePermit(long number, long nanoTime); 37 | 38 | /** 39 | * Releases permits without considering the result of the execution. 40 | * 41 | * @param number of permits to release 42 | * @param nanoTime currentInterval nanosecond time 43 | */ 44 | void releasePermit(long number, long nanoTime); 45 | 46 | /** 47 | * Releases permits while considering the result of the execution. The result of the 48 | * execution may help inform the logic of the back pressure mechanism (depending on the 49 | * implementation). 50 | * 51 | * @param number of permits to release 52 | * @param result of the task execution 53 | * @param nanoTime currentInterval nanosecond time 54 | */ 55 | void releasePermit(long number, Failable result, long nanoTime); 56 | 57 | /** 58 | * This method will register a guard rail with this back pressure mechanism. It is called 59 | * when when constructing a guard rail. This allows back pressure decisions to be made 60 | * based upon the object associated with guard rail. 61 | * 62 | * @param guardRail the guard rail registered 63 | */ 64 | & Failable> void registerGuardRail(GuardRail guardRail); 65 | } 66 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/counts/Counters.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.counts; 19 | 20 | import net.uncontended.precipice.metrics.tools.Allocator; 21 | 22 | public final class Counters { 23 | 24 | private Counters() { 25 | } 26 | 27 | public static > Allocator> longAdder(Class clazz) { 28 | return new LongAdderAllocator<>(clazz); 29 | } 30 | 31 | public static > Allocator> atomicLong(Class clazz) { 32 | return new AtomicLongAllocator<>(clazz); 33 | } 34 | 35 | public static > Allocator> longCounter(Class clazz) { 36 | return new LongAllocator<>(clazz); 37 | } 38 | 39 | private static class LongAdderAllocator> implements Allocator> { 40 | 41 | private final Class clazz; 42 | 43 | private LongAdderAllocator(Class clazz) { 44 | this.clazz = clazz; 45 | } 46 | 47 | @Override 48 | public PartitionedCount allocateNew() { 49 | return new LongAdderCounter<>(clazz); 50 | } 51 | } 52 | 53 | private static class AtomicLongAllocator> implements Allocator> { 54 | 55 | private final Class clazz; 56 | 57 | private AtomicLongAllocator(Class clazz) { 58 | this.clazz = clazz; 59 | } 60 | 61 | @Override 62 | public PartitionedCount allocateNew() { 63 | return new AtomicLongCounter<>(clazz); 64 | } 65 | } 66 | 67 | private static class LongAllocator> implements Allocator> { 68 | 69 | private final Class clazz; 70 | 71 | private LongAllocator(Class clazz) { 72 | this.clazz = clazz; 73 | } 74 | 75 | @Override 76 | public PartitionedCount allocateNew() { 77 | return new LongCounter<>(clazz); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/time/TickingClock.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.time; 19 | 20 | import org.HdrHistogram.Histogram; 21 | 22 | import java.util.concurrent.TimeUnit; 23 | import java.util.concurrent.atomic.AtomicReference; 24 | import java.util.concurrent.locks.LockSupport; 25 | 26 | /** 27 | * Unstable and still in development. At this time, {@link SystemTime} should be used. 28 | */ 29 | public class TickingClock implements Clock { 30 | 31 | public Histogram gram = new Histogram(TimeUnit.MILLISECONDS.toNanos(100), 3); 32 | private static final AtomicReference instance = new AtomicReference<>(); 33 | private volatile Thread runner; 34 | private volatile boolean stopped = false; 35 | private volatile long currentMillis = System.currentTimeMillis(); 36 | private volatile long currentNanos = System.nanoTime(); 37 | 38 | @Override 39 | public long currentTimeMillis() { 40 | return currentMillis; 41 | } 42 | 43 | @Override 44 | public long nanoTime() { 45 | return currentNanos; 46 | } 47 | 48 | private void start() { 49 | runner = new Thread(new TTask()); 50 | runner.start(); 51 | } 52 | 53 | public void stop() { 54 | stopped = true; 55 | runner.interrupt(); 56 | } 57 | 58 | public static TickingClock getInstance() { 59 | if (instance.get() == null) { 60 | TickingClock newClock = new TickingClock(); 61 | if (instance.compareAndSet(null, newClock)) { 62 | newClock.start(); 63 | } 64 | } 65 | return instance.get(); 66 | } 67 | 68 | private class TTask implements Runnable { 69 | 70 | @Override 71 | public void run() { 72 | long waitTime = 50000; 73 | 74 | while (!stopped) { 75 | LockSupport.parkNanos(waitTime); 76 | currentMillis = System.currentTimeMillis(); 77 | long newTime = System.nanoTime(); 78 | gram.recordValue(newTime - currentNanos); 79 | currentNanos = newTime; 80 | 81 | } 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /precipice-samples/src/main/java/net/uncontended/precipice/samples/GuardRailWithFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.samples; 19 | 20 | import net.uncontended.precipice.CompletionContext; 21 | import net.uncontended.precipice.GuardRail; 22 | import net.uncontended.precipice.GuardRailBuilder; 23 | import net.uncontended.precipice.factories.Synchronous; 24 | import net.uncontended.precipice.metrics.counts.NoOpCounter; 25 | import net.uncontended.precipice.metrics.counts.TotalCounts; 26 | import net.uncontended.precipice.rejected.Unrejectable; 27 | import net.uncontended.precipice.result.SimpleResult; 28 | import net.uncontended.precipice.semaphore.UnlimitedSemaphore; 29 | 30 | import java.io.InputStream; 31 | import java.net.URL; 32 | import java.net.URLConnection; 33 | 34 | public final class GuardRailWithFactory { 35 | 36 | public static void main(String[] args) { 37 | TotalCounts resultCounts = new TotalCounts<>(SimpleResult.class); 38 | TotalCounts rejectedCounts = new TotalCounts<>(new NoOpCounter<>(Unrejectable.class)); 39 | 40 | GuardRailBuilder builder = new GuardRailBuilder<>(); 41 | builder.name("Example") 42 | .resultCounts(resultCounts) 43 | .rejectedCounts(rejectedCounts) 44 | .addBackPressure(new UnlimitedSemaphore()); 45 | 46 | GuardRail guardRail = builder.build(); 47 | 48 | CompletionContext completable = Synchronous.acquireSinglePermitAndCompletable(guardRail); 49 | 50 | try { 51 | URL url = new URL("http://www.google.com"); 52 | URLConnection urlConnection = url.openConnection(); 53 | completable.complete(SimpleResult.SUCCESS, readToString(urlConnection.getInputStream())); 54 | } catch (Exception ex) { 55 | completable.completeExceptionally(SimpleResult.ERROR, ex); 56 | } 57 | 58 | completable.getValue(); 59 | // or 60 | completable.getError(); 61 | } 62 | 63 | private static String readToString(InputStream inputStream) { 64 | return "Http Response"; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/counts/CountRecorder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.counts; 19 | 20 | import net.uncontended.precipice.metrics.AbstractMetrics; 21 | import net.uncontended.precipice.metrics.tools.MetricRecorder; 22 | import net.uncontended.precipice.metrics.tools.Recorder; 23 | 24 | public class CountRecorder> extends AbstractMetrics implements WritableCounts, Recorder> { 25 | 26 | private final MetricRecorder> metricRecorder; 27 | 28 | public CountRecorder(MetricRecorder> metricRecorder) { 29 | super(metricRecorder.activeInterval().getMetricClazz()); 30 | this.metricRecorder = metricRecorder; 31 | } 32 | 33 | @Override 34 | public void write(T result, long number, long nanoTime) { 35 | long permit = metricRecorder.startRecord(); 36 | try { 37 | metricRecorder.activeInterval().add(result, number); 38 | } finally { 39 | metricRecorder.endRecord(permit); 40 | } 41 | } 42 | 43 | @Override 44 | public PartitionedCount activeInterval() { 45 | return metricRecorder.activeInterval(); 46 | } 47 | 48 | @Override 49 | public long activeIntervalStart() { 50 | return metricRecorder.activeIntervalStart(); 51 | } 52 | 53 | @Override 54 | public PartitionedCount captureInterval() { 55 | return metricRecorder.captureInterval(); 56 | } 57 | 58 | @Override 59 | public PartitionedCount captureInterval(long nanotime) { 60 | return metricRecorder.captureInterval(nanotime); 61 | } 62 | 63 | @Override 64 | public PartitionedCount captureInterval(PartitionedCount newInterval) { 65 | return metricRecorder.captureInterval(newInterval); 66 | } 67 | 68 | @Override 69 | public synchronized PartitionedCount captureInterval(PartitionedCount newInterval, long nanoTime) { 70 | return metricRecorder.captureInterval(newInterval, nanoTime); 71 | } 72 | 73 | public static > CountRecorderBuilder builder(Class clazz) { 74 | return new CountRecorderBuilder<>(clazz); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/concurrent/PrecipiceFuture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.concurrent; 19 | 20 | import net.uncontended.precipice.Failable; 21 | import net.uncontended.precipice.PrecipiceFunction; 22 | import net.uncontended.precipice.ResultView; 23 | 24 | import java.util.concurrent.Future; 25 | import java.util.concurrent.TimeUnit; 26 | 27 | /** 28 | * A context containing the result of an asynchronous computation. 29 | * 30 | * @param the type of the result for this future 31 | * @param the type of the value for this future 32 | */ 33 | public interface PrecipiceFuture extends Future, ResultView { 34 | 35 | /** 36 | * Attaches a callback to be executed if the future is completed successfully. 37 | * The function will be passed the result of the future and the value. 38 | *

39 | * This method only is guaranteed to be safe if it is called once. Specific implementations 40 | * may provide stronger guarantees. 41 | * 42 | * @param fn function to be executed 43 | */ 44 | void onSuccess(PrecipiceFunction fn); 45 | 46 | /** 47 | * Attaches a callback to be executed if the future is not completed successfully. 48 | * The function will be passed the result of the future and any exception that occurred 49 | * during execution. 50 | *

51 | * This method only is guaranteed to be safe if it is called once. Specific implementations 52 | * may provide stronger guarantees. 53 | * 54 | * @param fn function to be executed 55 | */ 56 | void onError(PrecipiceFunction fn); 57 | 58 | /** 59 | * Block until the completion of the future. 60 | * 61 | * @throws InterruptedException 62 | */ 63 | void await() throws InterruptedException; 64 | 65 | /** 66 | * Block until the completion of the future or until the time duration is exceeded. 67 | * 68 | * @param duration the maximum duration to wait 69 | * @param unit the unit of the duration argument 70 | * @throws InterruptedException 71 | */ 72 | void await(long duration, TimeUnit unit) throws InterruptedException; 73 | 74 | } 75 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/semaphore/LongSemaphore.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.semaphore; 19 | 20 | import net.uncontended.precipice.BackPressure; 21 | import net.uncontended.precipice.Failable; 22 | import net.uncontended.precipice.GuardRail; 23 | 24 | import java.util.concurrent.atomic.AtomicLong; 25 | 26 | public class LongSemaphore> implements BackPressure, PrecipiceSemaphore { 27 | 28 | private final AtomicLong permitsRemaining; 29 | private final long maxConcurrencyLevel; 30 | private final Rejected reason; 31 | 32 | public LongSemaphore(Rejected reason, long maxConcurrencyLevel) { 33 | this.maxConcurrencyLevel = maxConcurrencyLevel; 34 | this.reason = reason; 35 | this.permitsRemaining = new AtomicLong(maxConcurrencyLevel); 36 | } 37 | 38 | @Override 39 | public Rejected acquirePermit(long number, long nanoTime) { 40 | for (; ; ) { 41 | long permitsRemaining = this.permitsRemaining.get(); 42 | long newRemaining = permitsRemaining - number; 43 | if (newRemaining >= 0) { 44 | if (this.permitsRemaining.compareAndSet(permitsRemaining, newRemaining)) { 45 | return null; 46 | } 47 | } else { 48 | return reason; 49 | } 50 | } 51 | } 52 | 53 | @Override 54 | public void releasePermit(long number, long nanoTime) { 55 | this.permitsRemaining.getAndAdd(number); 56 | } 57 | 58 | @Override 59 | public void releasePermit(long number, Failable result, long nanoTime) { 60 | this.permitsRemaining.getAndAdd(number); 61 | } 62 | 63 | @Override 64 | public & Failable> void registerGuardRail(GuardRail guardRail) { 65 | } 66 | 67 | @Override 68 | public long maxConcurrencyLevel() { 69 | return maxConcurrencyLevel; 70 | } 71 | 72 | @Override 73 | public long remainingCapacity() { 74 | return permitsRemaining.get(); 75 | } 76 | 77 | @Override 78 | public long currentConcurrencyLevel() { 79 | return maxConcurrencyLevel - permitsRemaining.get(); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/counts/RollingCounts.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.counts; 19 | 20 | import net.uncontended.precipice.metrics.AbstractMetrics; 21 | import net.uncontended.precipice.metrics.IntervalIterator; 22 | import net.uncontended.precipice.metrics.Rolling; 23 | import net.uncontended.precipice.metrics.tools.CircularBuffer; 24 | import net.uncontended.precipice.metrics.tools.RollingMetrics; 25 | import net.uncontended.precipice.time.SystemTime; 26 | 27 | public class RollingCounts> extends AbstractMetrics implements WritableCounts, Rolling> { 28 | 29 | private final NoOpCounter noOpCounter; 30 | 31 | private final RollingMetrics> rolling; 32 | 33 | public RollingCounts(Class clazz, int buckets, long nanosPerBucket) { 34 | this(new RollingMetrics>(Counters.longAdder(clazz), 35 | new CircularBuffer>(buckets, nanosPerBucket, System.nanoTime()), 36 | SystemTime.getInstance())); 37 | } 38 | 39 | public RollingCounts(RollingMetrics> rolling) { 40 | super(rolling.current().getMetricClazz()); 41 | this.rolling = rolling; 42 | this.noOpCounter = new NoOpCounter<>(getMetricClazz()); 43 | } 44 | 45 | @Override 46 | public void write(T metric, long number, long nanoTime) { 47 | current(nanoTime).add(metric, number); 48 | } 49 | 50 | @Override 51 | public PartitionedCount current() { 52 | return rolling.current(); 53 | } 54 | 55 | @Override 56 | public PartitionedCount current(long nanoTime) { 57 | return rolling.current(nanoTime); 58 | } 59 | 60 | @Override 61 | public IntervalIterator> intervals() { 62 | return rolling.intervalsWithDefault(noOpCounter); 63 | } 64 | 65 | @Override 66 | public IntervalIterator> intervals(long nanoTime) { 67 | return rolling.intervalsWithDefault(nanoTime, noOpCounter); 68 | } 69 | 70 | public static > RollingCountsBuilder builder(Class clazz) { 71 | return new RollingCountsBuilder<>(clazz); 72 | 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /precipice-core/src/test/java/net/uncontended/precipice/metrics/counts/RollingCountTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.counts; 19 | 20 | import net.uncontended.precipice.metrics.IntervalIterator; 21 | import net.uncontended.precipice.metrics.tools.RollingMetrics; 22 | import net.uncontended.precipice.result.TimeoutableResult; 23 | import net.uncontended.precipice.time.Clock; 24 | import org.junit.Before; 25 | import org.junit.Test; 26 | import org.mockito.Mock; 27 | import org.mockito.MockitoAnnotations; 28 | 29 | import static org.junit.Assert.assertSame; 30 | import static org.mockito.Matchers.any; 31 | import static org.mockito.Matchers.eq; 32 | import static org.mockito.Mockito.mock; 33 | import static org.mockito.Mockito.verify; 34 | import static org.mockito.Mockito.when; 35 | 36 | public class RollingCountTest { 37 | 38 | @Mock 39 | private Clock systemTime; 40 | @Mock 41 | private RollingMetrics> baseMetrics; 42 | @Mock 43 | private PartitionedCount counter; 44 | 45 | 46 | private RollingCounts counts; 47 | 48 | @Before 49 | public void setUp() { 50 | MockitoAnnotations.initMocks(this); 51 | when(baseMetrics.current()).thenReturn(counter); 52 | when(counter.getMetricClazz()).thenReturn(TimeoutableResult.class); 53 | counts = new RollingCounts(baseMetrics); 54 | } 55 | 56 | @Test 57 | public void clazzComesFromCounter() { 58 | assertSame(TimeoutableResult.class, counts.getMetricClazz()); 59 | } 60 | 61 | @Test 62 | public void writeUsesBaseMetrics() { 63 | when(baseMetrics.current(100L)).thenReturn(counter); 64 | 65 | counts.write(TimeoutableResult.ERROR, 3, 100L); 66 | 67 | verify(counter).add(TimeoutableResult.ERROR, 3); 68 | } 69 | 70 | @Test 71 | public void intervalsCallUsesNoOpForDefault() { 72 | IntervalIterator iterator = mock(IntervalIterator.class); 73 | when(baseMetrics.intervalsWithDefault(eq(100L), any(NoOpCounter.class))).thenReturn(iterator); 74 | 75 | IntervalIterator> intervals = counts.intervals(100L); 76 | 77 | assertSame(iterator, intervals); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /precipice-reporting/src/main/java/net/uncontended/precipice/reporting/registry/MetricRegistry.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.uncontended.precipice.reporting.registry; 18 | 19 | import net.uncontended.precipice.GuardRail; 20 | 21 | import java.util.Map; 22 | import java.util.concurrent.*; 23 | import java.util.concurrent.atomic.AtomicLong; 24 | 25 | /** 26 | * Should be considered experimental. Development is not complete. May be moved to precipice-reporting. 27 | */ 28 | public class MetricRegistry { 29 | 30 | private final long period; 31 | private final TimeUnit unit; 32 | private final Map> services = new ConcurrentHashMap<>(); 33 | private volatile MetricRegistryCallback>> callback; 34 | private final ScheduledExecutorService executorService; 35 | 36 | public MetricRegistry(long period, TimeUnit unit) { 37 | this.unit = unit; 38 | this.period = period; 39 | 40 | executorService = Executors.newSingleThreadScheduledExecutor(new RegistryThreadFactory()); 41 | executorService.scheduleAtFixedRate(new Task(), 0, period, unit); 42 | } 43 | 44 | 45 | public void register(GuardRail service) { 46 | services.put(service.getName(), new Summary<>(new SummaryProperties(), service)); 47 | } 48 | 49 | public boolean deregister(String name) { 50 | return null == services.remove(name); 51 | } 52 | 53 | public void shutdown() { 54 | executorService.shutdown(); 55 | } 56 | 57 | private class Task implements Runnable { 58 | 59 | @Override 60 | public void run() { 61 | for (Summary summary : services.values()) { 62 | summary.refresh(); 63 | } 64 | 65 | if (callback != null) { 66 | callback.apply(services); 67 | } 68 | } 69 | } 70 | 71 | private static class RegistryThreadFactory implements ThreadFactory { 72 | private static final AtomicLong counter = new AtomicLong(0); 73 | 74 | @Override 75 | public Thread newThread(Runnable r) { 76 | Thread thread = new Thread(r); 77 | thread.setName("metric-registry-thread-" + counter.incrementAndGet()); 78 | return thread; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/latency/LatencyRecorder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.latency; 19 | 20 | import net.uncontended.precipice.metrics.AbstractMetrics; 21 | import net.uncontended.precipice.metrics.tools.MetricRecorder; 22 | import net.uncontended.precipice.metrics.tools.Recorder; 23 | 24 | public class LatencyRecorder> extends AbstractMetrics implements WritableLatency, Recorder> { 25 | 26 | private final MetricRecorder> metricRecorder; 27 | 28 | public LatencyRecorder(MetricRecorder> metricRecorder) { 29 | super(metricRecorder.activeInterval().getMetricClazz()); 30 | this.metricRecorder = metricRecorder; 31 | } 32 | 33 | @Override 34 | public void write(T metric, long number, long nanoLatency, long nanoTime) { 35 | long permit = metricRecorder.startRecord(); 36 | try { 37 | metricRecorder.activeInterval().record(metric, number, nanoLatency); 38 | } finally { 39 | metricRecorder.endRecord(permit); 40 | } 41 | } 42 | 43 | @Override 44 | public PartitionedLatency activeInterval() { 45 | return metricRecorder.activeInterval(); 46 | } 47 | 48 | @Override 49 | public long activeIntervalStart() { 50 | return metricRecorder.activeIntervalStart(); 51 | } 52 | 53 | @Override 54 | public PartitionedLatency captureInterval() { 55 | return metricRecorder.captureInterval(); 56 | } 57 | 58 | @Override 59 | public PartitionedLatency captureInterval(long nanotime) { 60 | return metricRecorder.captureInterval(nanotime); 61 | } 62 | 63 | @Override 64 | public PartitionedLatency captureInterval(PartitionedLatency newInterval) { 65 | return metricRecorder.captureInterval(newInterval); 66 | } 67 | 68 | @Override 69 | public synchronized PartitionedLatency captureInterval(PartitionedLatency newInterval, long nanoTime) { 70 | return metricRecorder.captureInterval(newInterval, nanoTime); 71 | } 72 | 73 | public static > LatencyRecorderBuilder builder(Class clazz) { 74 | return new LatencyRecorderBuilder<>(clazz); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/circuit/CircuitBreakerConfigBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.circuit; 19 | 20 | public class CircuitBreakerConfigBuilder> { 21 | private final Rejected reason; 22 | private final Rejected forcedReason; 23 | public long trailingPeriodMillis = 5000; 24 | public long failureThreshold = Long.MAX_VALUE; 25 | public int failurePercentageThreshold = 50; 26 | public long healthRefreshMillis = 500; 27 | public long backOffTimeMillis = 1000; 28 | public long sampleSizeThreshold = 10; 29 | 30 | public CircuitBreakerConfigBuilder(Rejected reason) { 31 | this(reason, reason); 32 | } 33 | 34 | public CircuitBreakerConfigBuilder(Rejected reason, Rejected forcedReason) { 35 | this.reason = reason; 36 | this.forcedReason = forcedReason; 37 | } 38 | 39 | public CircuitBreakerConfigBuilder trailingPeriodMillis(long trailingPeriodMillis) { 40 | this.trailingPeriodMillis = trailingPeriodMillis; 41 | return this; 42 | } 43 | 44 | public CircuitBreakerConfigBuilder failureThreshold(long failureThreshold) { 45 | this.failureThreshold = failureThreshold; 46 | return this; 47 | } 48 | 49 | public CircuitBreakerConfigBuilder failurePercentageThreshold(int failurePercentageThreshold) { 50 | this.failurePercentageThreshold = failurePercentageThreshold; 51 | return this; 52 | } 53 | 54 | public CircuitBreakerConfigBuilder backOffTimeMillis(long backOffTimeMillis) { 55 | this.backOffTimeMillis = backOffTimeMillis; 56 | return this; 57 | } 58 | 59 | public CircuitBreakerConfigBuilder healthRefreshMillis(long healthRefreshMillis) { 60 | this.healthRefreshMillis = healthRefreshMillis; 61 | return this; 62 | } 63 | 64 | public CircuitBreakerConfigBuilder sampleSizeThreshold(long sampleSizeThreshold) { 65 | this.sampleSizeThreshold = sampleSizeThreshold; 66 | return this; 67 | } 68 | 69 | public CircuitBreakerConfig build() { 70 | return new CircuitBreakerConfig<>(reason, forcedReason, failureThreshold, failurePercentageThreshold, 71 | sampleSizeThreshold, trailingPeriodMillis, healthRefreshMillis, backOffTimeMillis); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/latency/RollingLatency.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.latency; 19 | 20 | import net.uncontended.precipice.metrics.AbstractMetrics; 21 | import net.uncontended.precipice.metrics.IntervalIterator; 22 | import net.uncontended.precipice.metrics.Rolling; 23 | import net.uncontended.precipice.metrics.tools.Allocator; 24 | import net.uncontended.precipice.metrics.tools.CircularBuffer; 25 | import net.uncontended.precipice.metrics.tools.RollingMetrics; 26 | import net.uncontended.precipice.time.SystemTime; 27 | 28 | public class RollingLatency> extends AbstractMetrics implements WritableLatency, Rolling> { 29 | 30 | private final RollingMetrics> rolling; 31 | private final NoOpLatency noOpLatency; 32 | 33 | public RollingLatency(Class clazz, int buckets, long nanosPerBucket) { 34 | this(Latency.atomicHDRHistogram(clazz), buckets, nanosPerBucket); 35 | } 36 | 37 | public RollingLatency(Allocator> allocator, int buckets, long nanosPerBucket) { 38 | this(new RollingMetrics>(allocator, 39 | new CircularBuffer>(buckets, nanosPerBucket, System.nanoTime()), 40 | SystemTime.getInstance())); 41 | } 42 | 43 | public RollingLatency(RollingMetrics> rolling) { 44 | super(rolling.current().getMetricClazz()); 45 | this.rolling = rolling; 46 | this.noOpLatency = new NoOpLatency<>(getMetricClazz()); 47 | } 48 | 49 | @Override 50 | public void write(T metric, long number, long nanoLatency, long nanoTime) { 51 | rolling.current(nanoTime).record(metric, number, nanoLatency); 52 | } 53 | 54 | @Override 55 | public PartitionedLatency current() { 56 | return rolling.current(); 57 | } 58 | 59 | @Override 60 | public PartitionedLatency current(long nanoTime) { 61 | return rolling.current(nanoTime); 62 | } 63 | 64 | @Override 65 | public IntervalIterator> intervals() { 66 | return rolling.intervalsWithDefault(noOpLatency); 67 | } 68 | 69 | @Override 70 | public IntervalIterator> intervals(long nanoTime) { 71 | return rolling.intervalsWithDefault(nanoTime, noOpLatency); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/rate/RateLimiter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.rate; 19 | 20 | import net.uncontended.precipice.BackPressure; 21 | import net.uncontended.precipice.Failable; 22 | import net.uncontended.precipice.GuardRail; 23 | 24 | import java.util.concurrent.TimeUnit; 25 | import java.util.concurrent.atomic.AtomicLong; 26 | 27 | /** 28 | * Unstable and still in development. 29 | */ 30 | public class RateLimiter> implements BackPressure { 31 | 32 | private final Rejected rejectedReason; 33 | private final long allowedPerPeriod; 34 | private final AtomicLong count = new AtomicLong(0); 35 | private final AtomicLong rolloverTime; 36 | private final long nanoDuration; 37 | 38 | public RateLimiter(Rejected rejectedReason, long allowedPerPeriod, long duration, TimeUnit timeUnit) { 39 | this.rejectedReason = rejectedReason; 40 | this.allowedPerPeriod = allowedPerPeriod; 41 | this.nanoDuration = timeUnit.toNanos(duration); 42 | this.rolloverTime = new AtomicLong(System.nanoTime() + nanoDuration); 43 | } 44 | 45 | @Override 46 | public Rejected acquirePermit(long number, long nanoTime) { 47 | adjustTime(nanoTime); 48 | 49 | for (; ; ) { 50 | long currentCount = count.get(); 51 | long proposedCount = currentCount + number; 52 | if (proposedCount > allowedPerPeriod) { 53 | return rejectedReason; 54 | } else if (count.compareAndSet(currentCount, proposedCount)) { 55 | return null; 56 | } 57 | } 58 | } 59 | 60 | private void adjustTime(long nanoTime) { 61 | for (; ; ) { 62 | long localRolloverTime = rolloverTime.get(); 63 | if (localRolloverTime > nanoTime) { 64 | return; 65 | } else if (rolloverTime.compareAndSet(localRolloverTime, nanoTime + nanoDuration)) { 66 | count.set(0); 67 | } 68 | } 69 | } 70 | 71 | @Override 72 | public void releasePermit(long number, long nanoTime) { 73 | } 74 | 75 | @Override 76 | public void releasePermit(long number, Failable result, long nanoTime) { 77 | } 78 | 79 | @Override 80 | public & Failable> void registerGuardRail(GuardRail guardRail) { 81 | 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /precipice-threadpool/src/main/java/net/uncontended/precipice/threadpool/experimental/ExchangingQueue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.threadpool.experimental; 19 | 20 | import java.util.concurrent.atomic.AtomicInteger; 21 | import java.util.concurrent.locks.LockSupport; 22 | 23 | public class ExchangingQueue { 24 | 25 | private final T[] queue; 26 | private final int capacity; 27 | private final int mask; 28 | private final AtomicInteger head = new AtomicInteger(0); 29 | private final AtomicInteger tail = new AtomicInteger(0); 30 | private volatile Thread waiter = null; 31 | 32 | @SuppressWarnings("unchecked") 33 | public ExchangingQueue(final int capacity) { 34 | int adjustedCapacity = 1 << 32 - Integer.numberOfLeadingZeros(capacity - 1); 35 | this.capacity = adjustedCapacity; 36 | mask = adjustedCapacity - 1; 37 | queue = (T[]) new Object[adjustedCapacity]; 38 | } 39 | 40 | public boolean offer(final T element) { 41 | if (null == element) { 42 | throw new NullPointerException("Cannot put null in the queue"); 43 | } 44 | final int currentTail = tail.get(); 45 | final int wrapPoint = currentTail - capacity; 46 | 47 | if (head.get() <= wrapPoint) { 48 | return false; 49 | } 50 | queue[currentTail & mask] = element; 51 | tail.lazySet(currentTail + 1); 52 | if (waiter != null) { 53 | LockSupport.unpark(waiter); 54 | } 55 | return true; 56 | } 57 | 58 | public T poll() { 59 | final int currentHead = head.get(); 60 | 61 | if (currentHead >= tail.get()) { 62 | return null; 63 | } 64 | 65 | int index = currentHead & mask; 66 | final T element = queue[index]; 67 | queue[index] = null; 68 | head.lazySet(currentHead + 1); 69 | return element; 70 | 71 | } 72 | 73 | public T blockingPoll() throws InterruptedException { 74 | for (; ; ) { 75 | T element = poll(); 76 | if (element != null) { 77 | return element; 78 | } 79 | waiter = Thread.currentThread(); 80 | LockSupport.park(); 81 | waiter = null; 82 | if (Thread.currentThread().isInterrupted()) { 83 | throw new InterruptedException(); 84 | } 85 | } 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/circuit/HealthGauge.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.circuit; 19 | 20 | import net.uncontended.precipice.Failable; 21 | import net.uncontended.precipice.metrics.IntervalIterator; 22 | import net.uncontended.precipice.metrics.Rolling; 23 | import net.uncontended.precipice.metrics.counts.PartitionedCount; 24 | 25 | import java.util.concurrent.CopyOnWriteArrayList; 26 | import java.util.concurrent.TimeUnit; 27 | 28 | public class HealthGauge { 29 | 30 | private final CopyOnWriteArrayList> gauges = new CopyOnWriteArrayList<>(); 31 | 32 | public synchronized HealthSnapshot getHealth(long timePeriod, TimeUnit timeUnit, long nanoTime) { 33 | long total = 0; 34 | long failures = 0; 35 | 36 | for (InternalGauge gauge : gauges) { 37 | gauge.refreshHealth(timePeriod, timeUnit, nanoTime); 38 | total += gauge.total; 39 | failures += gauge.failures; 40 | } 41 | return new HealthSnapshot(total, failures); 42 | } 43 | 44 | public & Failable> void add(Rolling> metrics) { 45 | gauges.add(new InternalGauge<>(metrics)); 46 | } 47 | 48 | private static class InternalGauge & Failable> { 49 | 50 | private final Rolling> metrics; 51 | private final Class type; 52 | private long total = 0; 53 | private long failures = 0; 54 | 55 | private InternalGauge(Rolling> metrics) { 56 | this.metrics = metrics; 57 | type = metrics.current().getMetricClazz(); 58 | } 59 | 60 | private void refreshHealth(long timePeriod, TimeUnit timeUnit, long nanoTime) { 61 | total = 0; 62 | failures = 0; 63 | IntervalIterator> counters = metrics.intervals(nanoTime); 64 | counters.limit(timePeriod, timeUnit); 65 | 66 | PartitionedCount metricCounter; 67 | while (counters.hasNext()) { 68 | metricCounter = counters.next(); 69 | for (Result result : type.getEnumConstants()) { 70 | long metricCount = metricCounter.getCount(result); 71 | total += metricCount; 72 | 73 | if (result.isFailure()) { 74 | failures += metricCount; 75 | } 76 | } 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/pattern/RoundRobinLoadBalancer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.pattern; 19 | 20 | import java.util.Random; 21 | import java.util.concurrent.ThreadLocalRandom; 22 | import java.util.concurrent.atomic.AtomicLong; 23 | 24 | public class RoundRobinLoadBalancer implements PatternStrategy { 25 | 26 | // TODO: The arrays can probably be cached 27 | 28 | private final long flipPoint; 29 | private final int size; 30 | private final int maxAcquireAttempts; 31 | private final AtomicLong counter; 32 | 33 | public RoundRobinLoadBalancer(int size) { 34 | this(size, size); 35 | } 36 | 37 | public RoundRobinLoadBalancer(int size, int maxAcquireAttempts) { 38 | this(size, maxAcquireAttempts, new AtomicLong(0)); 39 | } 40 | 41 | public RoundRobinLoadBalancer(int size, int maxAcquireAttempts, AtomicLong counter) { 42 | this.size = size; 43 | this.maxAcquireAttempts = maxAcquireAttempts; 44 | this.counter = counter; 45 | this.flipPoint = Long.MAX_VALUE - maxAcquireAttempts; 46 | } 47 | 48 | @Override 49 | public Iterable nextIndices() { 50 | long index = counter.getAndIncrement(); 51 | 52 | if (index >= flipPoint) { 53 | resetCounter(index); 54 | } 55 | 56 | SingleReaderArrayIterable iterable = new SingleReaderArrayIterable(maxAcquireAttempts); 57 | 58 | Integer[] orderToTry = iterable.getIndices(); 59 | for (int i = 0; i < maxAcquireAttempts; ++i) { 60 | orderToTry[i] = (int) ((index + i) % size); 61 | } 62 | shuffleTail(orderToTry); 63 | return iterable; 64 | } 65 | 66 | @Override 67 | public int acquireCount() { 68 | return 1; 69 | } 70 | 71 | private static void shuffleTail(Integer[] orderToTry) { 72 | int index; 73 | Random random = ThreadLocalRandom.current(); 74 | for (int i = orderToTry.length - 1; i > 1; i--) { 75 | index = random.nextInt(i) + 1; 76 | if (index != i) { 77 | orderToTry[index] ^= orderToTry[i]; 78 | orderToTry[i] ^= orderToTry[index]; 79 | orderToTry[index] ^= orderToTry[i]; 80 | } 81 | } 82 | } 83 | 84 | private void resetCounter(long start) { 85 | long index = start; 86 | for (; ; ) { 87 | if (index < flipPoint || counter.compareAndSet(index + 1, 0)) { 88 | break; 89 | } 90 | index = counter.get(); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/GuardRailBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice; 19 | 20 | import net.uncontended.precipice.metrics.counts.WritableCounts; 21 | import net.uncontended.precipice.metrics.latency.NoOpLatency; 22 | import net.uncontended.precipice.metrics.latency.WritableLatency; 23 | import net.uncontended.precipice.time.Clock; 24 | 25 | public class GuardRailBuilder & Failable, Rejected extends Enum> { 26 | 27 | private final GuardRailProperties properties = new GuardRailProperties<>(); 28 | 29 | 30 | public GuardRailBuilder name(String name) { 31 | properties.name = name; 32 | return this; 33 | } 34 | 35 | public GuardRailBuilder addBackPressure(BackPressure backPressure) { 36 | properties.backPressureMap.put(Integer.toString(properties.backPressureMap.size()), backPressure); 37 | return this; 38 | } 39 | 40 | public GuardRailBuilder addBackPressure(String name, BackPressure backPressure) { 41 | properties.backPressureMap.put(name, backPressure); 42 | return this; 43 | } 44 | 45 | public GuardRailBuilder resultCounts(WritableCounts resultCounts) { 46 | properties.resultCounts = resultCounts; 47 | return this; 48 | } 49 | 50 | public GuardRailBuilder rejectedCounts(WritableCounts rejectedCounts) { 51 | properties.rejectedCounts = rejectedCounts; 52 | return this; 53 | } 54 | 55 | public GuardRailBuilder resultLatency(WritableLatency resultLatency) { 56 | properties.resultLatency = resultLatency; 57 | return this; 58 | } 59 | 60 | public GuardRailBuilder clock(Clock clock) { 61 | properties.clock = clock; 62 | return this; 63 | } 64 | 65 | public GuardRail build() { 66 | if (properties.name == null) { 67 | throw new IllegalArgumentException("Name is required."); 68 | } else if (properties.resultCounts == null) { 69 | throw new IllegalArgumentException("Result counts are required."); 70 | } else if (properties.rejectedCounts == null) { 71 | throw new IllegalArgumentException("Rejected counts are required."); 72 | } 73 | 74 | if (properties.resultLatency == null) { 75 | properties.resultLatency = new NoOpLatency<>(properties.resultCounts.getMetricClazz()); 76 | } 77 | 78 | return GuardRail.create(properties); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/metrics/counts/Accumulator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.metrics.counts; 19 | 20 | import net.uncontended.precipice.metrics.IntervalIterator; 21 | 22 | import java.util.Iterator; 23 | import java.util.concurrent.TimeUnit; 24 | 25 | public final class Accumulator { 26 | 27 | public static > long count(Iterator> intervals, T type) { 28 | long count = 0; 29 | PartitionedCount metricCounter; 30 | while (intervals.hasNext()) { 31 | metricCounter = intervals.next(); 32 | count += metricCounter.getCount(type); 33 | } 34 | return count; 35 | } 36 | 37 | public static > long countForPeriod(IntervalIterator> intervals, T type, 38 | long duration, TimeUnit unit) { 39 | intervals.limit(duration, unit); 40 | return count(intervals, type); 41 | } 42 | 43 | public static > Counts counts(Iterator> intervals) { 44 | Counts counts = new Counts<>(); 45 | PartitionedCount metricCounter; 46 | Class metricClazz = null; 47 | while (intervals.hasNext()) { 48 | metricCounter = intervals.next(); 49 | long[] countArray = counts.array(); 50 | if (countArray == null) { 51 | metricClazz = metricCounter.getMetricClazz(); 52 | counts.init(metricClazz); 53 | countArray = counts.array(); 54 | } 55 | 56 | for (T type : metricClazz.getEnumConstants()) { 57 | countArray[type.ordinal()] += metricCounter.getCount(type); 58 | } 59 | 60 | } 61 | return counts; 62 | } 63 | 64 | public static > Counts countsForPeriod(IntervalIterator> intervals, 65 | long duration, TimeUnit unit) { 66 | intervals.limit(duration, unit); 67 | return counts(intervals); 68 | } 69 | 70 | public static class Counts> { 71 | private long[] counts = null; 72 | 73 | public long get(T type) { 74 | if (counts != null) { 75 | return counts[type.ordinal()]; 76 | } 77 | return 0L; 78 | } 79 | 80 | void init(Class clazz) { 81 | counts = new long[clazz.getEnumConstants().length]; 82 | } 83 | 84 | long[] array() { 85 | return counts; 86 | } 87 | 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/circuit/experimental/RefactoredBreaker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.circuit.experimental; 19 | 20 | import net.uncontended.precipice.Failable; 21 | import net.uncontended.precipice.GuardRail; 22 | import net.uncontended.precipice.circuit.CircuitBreaker; 23 | import net.uncontended.precipice.circuit.CircuitBreakerConfig; 24 | 25 | public class RefactoredBreaker> extends AbstractBreaker implements CircuitBreaker { 26 | 27 | private final Rejected reason; 28 | private final Rejected forcedReason; 29 | private final long backOffTimeNanos; 30 | private final HealthChecker checker; 31 | 32 | private volatile long lastTestedNanoTime; 33 | 34 | public RefactoredBreaker(Rejected reason, Rejected forcedReason, HealthChecker checker, long backOffTimeNanos) { 35 | this.reason = reason; 36 | this.forcedReason = forcedReason; 37 | this.checker = checker; 38 | this.backOffTimeNanos = backOffTimeNanos; 39 | } 40 | 41 | @Override 42 | public CircuitBreakerConfig getBreakerConfig() { 43 | return null; 44 | } 45 | 46 | @Override 47 | public void setBreakerConfig(CircuitBreakerConfig breakerConfig) { 48 | 49 | } 50 | 51 | @Override 52 | public Rejected acquirePermit(long number, long nanoTime) { 53 | int state = this.state.get(); 54 | if (state == OPEN) { 55 | // This potentially allows a couple of tests through. Should think about this decision 56 | if (nanoTime - (backOffTimeNanos + lastTestedNanoTime) < 0) { 57 | return reason; 58 | } 59 | lastTestedNanoTime = nanoTime; 60 | } 61 | return state != FORCED_OPEN ? null : forcedReason; 62 | } 63 | 64 | @Override 65 | public void releasePermit(long number, long nanoTime) { 66 | 67 | } 68 | 69 | @Override 70 | public void releasePermit(long number, Failable result, long nanoTime) { 71 | if (result.isSuccess()) { 72 | if (state.get() == OPEN) { 73 | // Explore whether this can get stuck in a loop with open and closing 74 | state.compareAndSet(OPEN, CLOSED); 75 | } 76 | } else { 77 | if (state.get() == CLOSED) { 78 | if (!checker.isHealthy(nanoTime)) { 79 | lastTestedNanoTime = nanoTime; 80 | state.compareAndSet(CLOSED, OPEN); 81 | } 82 | } 83 | } 84 | } 85 | 86 | @Override 87 | public & Failable> void registerGuardRail(GuardRail guardRail) { 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /precipice-core/src/main/java/net/uncontended/precipice/factories/Asynchronous.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.uncontended.precipice.factories; 19 | 20 | import net.uncontended.precipice.Completable; 21 | import net.uncontended.precipice.Failable; 22 | import net.uncontended.precipice.GuardRail; 23 | import net.uncontended.precipice.concurrent.Eventual; 24 | import net.uncontended.precipice.rejected.RejectedException; 25 | 26 | public final class Asynchronous { 27 | 28 | private Asynchronous() { 29 | } 30 | 31 | public static & Failable, Rejected extends Enum, R> Eventual 32 | acquireSinglePermitAndPromise(GuardRail guardRail) { 33 | return acquirePermitsAndPromise(guardRail, 1L, null); 34 | } 35 | 36 | public static & Failable, Rejected extends Enum, R> Eventual 37 | acquireSinglePermitAndPromise(GuardRail guardRail, Completable externalCompletable) { 38 | return acquirePermitsAndPromise(guardRail, 1L, externalCompletable); 39 | } 40 | 41 | public static & Failable, Rejected extends Enum, R> Eventual 42 | acquirePermitsAndPromise(GuardRail guardRail, long number) { 43 | return acquirePermitsAndPromise(guardRail, number, null); 44 | } 45 | 46 | public static & Failable, Rejected extends Enum, R> Eventual 47 | acquirePermitsAndPromise(GuardRail guardRail, long number, Completable externalCompletable) { 48 | long startTime = guardRail.getClock().nanoTime(); 49 | Rejected rejected = guardRail.acquirePermits(number, startTime); 50 | if (rejected != null) { 51 | throw new RejectedException(rejected); 52 | } 53 | return getPromise(guardRail, number, startTime, externalCompletable); 54 | } 55 | 56 | public static & Failable, Rejected extends Enum, R> Eventual 57 | getPromise(GuardRail guardRail, long permitNumber, long nanoTime) { 58 | return getPromise(guardRail, permitNumber, nanoTime, null); 59 | } 60 | 61 | public static & Failable, Rejected extends Enum, R> Eventual 62 | getPromise(GuardRail guardRail, long permitNumber, long nanoTime, Completable externalCompletable) { 63 | Eventual promise = new Eventual<>(permitNumber, nanoTime, externalCompletable); 64 | promise.internalOnComplete(guardRail.releaseFunction()); 65 | return promise; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /precipice-reporting/src/test/java/net/uncontended/precipice/reporting/registry/SummaryTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Timothy Brooks 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.uncontended.precipice.reporting.registry; 18 | 19 | import net.uncontended.precipice.metrics.counts.PartitionedCount; 20 | import net.uncontended.precipice.metrics.Rolling; 21 | import net.uncontended.precipice.result.SimpleResult; 22 | import org.junit.Before; 23 | 24 | public class SummaryTest { 25 | 26 | private Rolling> resultCounts; 27 | private Rolling> rejectedCounts; 28 | private Summary summary; 29 | private long startTime; 30 | 31 | @Before 32 | public void setUp() { 33 | SummaryProperties properties = new SummaryProperties(); 34 | properties.bufferSize = 4; 35 | 36 | // resultCounts = new RollingCountMetrics<>(SimpleResult.class, 8, 500, TimeUnit.MILLISECONDS); 37 | // addRejectedMetrics = new RollingCountMetrics<>(Rejected.class, 8, 500, TimeUnit.MILLISECONDS); 38 | // startTime = System.nanoTime(); 39 | // 40 | // GuardRailBuilder builder = new GuardRailBuilder<>(); 41 | // builder.name("Test"); 42 | // builder.resultCounts(resultCounts); 43 | // builder.rejectedCounts(rejectedCounts); 44 | // summary = new Summary<>(properties, builder.build()); 45 | } 46 | 47 | // @Test 48 | // public void testRefresh() { 49 | // 50 | // for (int i = 0; i < 12; ++i) { 51 | // resultCounts.add(SimpleResult.SUCCESS, 1, startTime + (i * TimeUnit.MILLISECONDS.toNanos(100))); 52 | // resultCounts.add(SimpleResult.ERROR, 1, startTime + (i * TimeUnit.MILLISECONDS.toNanos(100))); 53 | // } 54 | // 55 | // summary.refresh(10000, startTime + TimeUnit.SECONDS.toNanos(1)); 56 | // 57 | // for (int i = 12; i < 15; ++i) { 58 | // resultCounts.add(SimpleResult.SUCCESS, 1, startTime + (i * TimeUnit.MILLISECONDS.toNanos(100))); 59 | // resultCounts.add(SimpleResult.ERROR, 1, startTime + (i * TimeUnit.MILLISECONDS.toNanos(100))); 60 | // } 61 | // 62 | // summary.refresh(11100, startTime + TimeUnit.SECONDS.toNanos(2)); 63 | // 64 | // summary.refresh(12030, startTime + TimeUnit.SECONDS.toNanos(3)); 65 | // 66 | // summary.refresh(16020, startTime + TimeUnit.SECONDS.toNanos(4)); 67 | // 68 | // for (Slice slice : summary.getSlices()) { 69 | // System.out.println("Start: " + slice.startEpoch); 70 | // System.out.println("End: " + slice.endEpoch); 71 | // System.out.println(Arrays.toString(slice.resultCounts)); 72 | // } 73 | // } 74 | 75 | private enum Rejected { 76 | REJECTED_1, 77 | REJECTED_2; 78 | } 79 | } 80 | --------------------------------------------------------------------------------