Make InMemoryMetricRepository.increment() thread safe
This commit is contained in:
parent
eb246d6bed
commit
7a6131c466
|
@ -31,18 +31,26 @@ public class InMemoryMetricRepository implements MetricRepository {
|
||||||
|
|
||||||
private ConcurrentMap<String, Measurement> metrics = new ConcurrentHashMap<String, Measurement>();
|
private ConcurrentMap<String, Measurement> metrics = new ConcurrentHashMap<String, Measurement>();
|
||||||
|
|
||||||
|
private ConcurrentMap<String, Object> locks = new ConcurrentHashMap<String, Object>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void increment(String metricName, int amount, Date timestamp) {
|
public void increment(String metricName, int amount, Date timestamp) {
|
||||||
Measurement current = this.metrics.get(metricName);
|
Measurement current = this.metrics.get(metricName);
|
||||||
if (current != null) {
|
if (current != null) {
|
||||||
Metric metric = current.getMetric();
|
Object lock = this.locks.putIfAbsent(metricName, new Object());
|
||||||
this.metrics.replace(metricName, current,
|
if (lock == null) {
|
||||||
new Measurement(timestamp, metric.increment(amount)));
|
lock = this.locks.get(metricName);
|
||||||
}
|
}
|
||||||
else {
|
synchronized (lock) {
|
||||||
this.metrics.putIfAbsent(metricName, new Measurement(timestamp, new Metric(
|
current = this.metrics.get(metricName);
|
||||||
metricName, amount)));
|
Metric metric = current.getMetric();
|
||||||
|
this.metrics.replace(metricName, current, new Measurement(timestamp,
|
||||||
|
metric.increment(amount)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
this.metrics.putIfAbsent(metricName, new Measurement(timestamp, new Metric(
|
||||||
|
metricName, amount)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -16,24 +16,65 @@
|
||||||
|
|
||||||
package org.springframework.boot.actuate.metrics;
|
package org.springframework.boot.actuate.metrics;
|
||||||
|
|
||||||
import org.junit.Ignore;
|
import java.util.ArrayList;
|
||||||
import org.junit.Test;
|
import java.util.Collection;
|
||||||
import org.springframework.boot.actuate.metrics.InMemoryMetricRepository;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import static org.junit.Assert.fail;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link InMemoryMetricRepository}.
|
* Tests for {@link InMemoryMetricRepository}.
|
||||||
*/
|
*/
|
||||||
@Ignore
|
|
||||||
public class InMemoryMetricRepositoryTests {
|
public class InMemoryMetricRepositoryTests {
|
||||||
|
|
||||||
// FIXME write tests
|
private InMemoryMetricRepository repository = new InMemoryMetricRepository();
|
||||||
// FIXME possibly also add Metric/Measurement tests
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void increment() {
|
||||||
fail("Not yet implemented");
|
this.repository.increment("foo", 1, new Date());
|
||||||
|
assertEquals(1.0, this.repository.findOne("foo").getValue(), 0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void incrementConcurrent() throws Exception {
|
||||||
|
Collection<Callable<Boolean>> tasks = new ArrayList<Callable<Boolean>>();
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
tasks.add(new Callable<Boolean>() {
|
||||||
|
@Override
|
||||||
|
public Boolean call() throws Exception {
|
||||||
|
InMemoryMetricRepositoryTests.this.repository.increment("foo", 1,
|
||||||
|
new Date());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
tasks.add(new Callable<Boolean>() {
|
||||||
|
@Override
|
||||||
|
public Boolean call() throws Exception {
|
||||||
|
InMemoryMetricRepositoryTests.this.repository.increment("foo", -1,
|
||||||
|
new Date());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
List<Future<Boolean>> all = Executors.newFixedThreadPool(10).invokeAll(tasks);
|
||||||
|
for (Future<Boolean> future : all) {
|
||||||
|
assertTrue(future.get(1, TimeUnit.SECONDS));
|
||||||
|
}
|
||||||
|
assertEquals(0, this.repository.findOne("foo").getValue(), 0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void set() {
|
||||||
|
this.repository.set("foo", 1, new Date());
|
||||||
|
assertEquals(1.0, this.repository.findOne("foo").getValue(), 0.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue