|
14 | 14 |
|
15 | 15 | package com.rabbitmq.stream.impl;
|
16 | 16 |
|
17 |
| -import com.codahale.metrics.ConsoleReporter; |
18 |
| -import com.codahale.metrics.Histogram; |
19 |
| -import com.codahale.metrics.MetricRegistry; |
| 17 | +import static com.rabbitmq.stream.impl.Assertions.assertThat; |
| 18 | +import static com.rabbitmq.stream.impl.TestUtils.sync; |
| 19 | +import static com.rabbitmq.stream.impl.TestUtils.waitAtMost; |
| 20 | + |
| 21 | +import com.codahale.metrics.*; |
20 | 22 | import com.google.common.util.concurrent.RateLimiter;
|
| 23 | +import com.rabbitmq.stream.impl.TestUtils.Sync; |
| 24 | +import java.util.Locale; |
21 | 25 | import java.util.Random;
|
22 |
| -import java.util.concurrent.TimeUnit; |
| 26 | +import java.util.concurrent.atomic.AtomicBoolean; |
| 27 | +import java.util.concurrent.atomic.AtomicInteger; |
23 | 28 | import java.util.stream.IntStream;
|
24 | 29 | import org.junit.jupiter.api.Test;
|
25 | 30 |
|
26 | 31 | public class DynamicBatchTest {
|
27 | 32 |
|
| 33 | + private static void simulateActivity(long duration) { |
| 34 | + try { |
| 35 | + Thread.sleep(duration); |
| 36 | + } catch (InterruptedException e) { |
| 37 | + throw new RuntimeException(e); |
| 38 | + } |
| 39 | + } |
| 40 | + |
| 41 | + private static void printHistogram(Histogram histogram) { |
| 42 | + Locale locale = Locale.getDefault(); |
| 43 | + System.out.printf(locale, " count = %d%n", histogram.getCount()); |
| 44 | + Snapshot snapshot = histogram.getSnapshot(); |
| 45 | + System.out.printf(locale, " min = %d%n", snapshot.getMin()); |
| 46 | + System.out.printf(locale, " max = %d%n", snapshot.getMax()); |
| 47 | + System.out.printf(locale, " mean = %2.2f%n", snapshot.getMean()); |
| 48 | + System.out.printf(locale, " stddev = %2.2f%n", snapshot.getStdDev()); |
| 49 | + System.out.printf(locale, " median = %2.2f%n", snapshot.getMedian()); |
| 50 | + System.out.printf(locale, " 75%% <= %2.2f%n", snapshot.get75thPercentile()); |
| 51 | + System.out.printf(locale, " 95%% <= %2.2f%n", snapshot.get95thPercentile()); |
| 52 | + System.out.printf(locale, " 98%% <= %2.2f%n", snapshot.get98thPercentile()); |
| 53 | + System.out.printf(locale, " 99%% <= %2.2f%n", snapshot.get99thPercentile()); |
| 54 | + System.out.printf(locale, " 99.9%% <= %2.2f%n", snapshot.get999thPercentile()); |
| 55 | + } |
| 56 | + |
28 | 57 | @Test
|
29 |
| - void test() { |
| 58 | + void itemAreProcessed() { |
30 | 59 | MetricRegistry metrics = new MetricRegistry();
|
31 | 60 | Histogram batchSizeMetrics = metrics.histogram("batch-size");
|
32 |
| - ConsoleReporter reporter = |
33 |
| - ConsoleReporter.forRegistry(metrics) |
34 |
| - .convertRatesTo(TimeUnit.SECONDS) |
35 |
| - .convertDurationsTo(TimeUnit.MILLISECONDS) |
36 |
| - .build(); |
37 |
| - |
38 | 61 | int itemCount = 3000;
|
39 |
| - TestUtils.Sync sync = TestUtils.sync(itemCount); |
| 62 | + Sync sync = sync(itemCount); |
40 | 63 | Random random = new Random();
|
41 |
| - DynamicBatch<String> batch = |
42 |
| - new DynamicBatch<>( |
43 |
| - (items, replay) -> { |
44 |
| - batchSizeMetrics.update(items.size()); |
45 |
| - try { |
46 |
| - Thread.sleep(random.nextInt(10) + 1); |
47 |
| - } catch (InterruptedException e) { |
48 |
| - throw new RuntimeException(e); |
49 |
| - } |
50 |
| - sync.down(items.size()); |
51 |
| - return true; |
52 |
| - }, |
53 |
| - 100); |
54 |
| - try { |
55 |
| - RateLimiter rateLimiter = RateLimiter.create(3000); |
56 |
| - long start = System.nanoTime(); |
| 64 | + DynamicBatch.BatchConsumer<String> action = |
| 65 | + items -> { |
| 66 | + batchSizeMetrics.update(items.size()); |
| 67 | + simulateActivity(random.nextInt(10) + 1); |
| 68 | + sync.down(items.size()); |
| 69 | + return true; |
| 70 | + }; |
| 71 | + try (DynamicBatch<String> batch = new DynamicBatch<>(action, 100)) { |
| 72 | + RateLimiter rateLimiter = RateLimiter.create(10000); |
57 | 73 | IntStream.range(0, itemCount)
|
58 | 74 | .forEach(
|
59 | 75 | i -> {
|
60 | 76 | rateLimiter.acquire();
|
61 | 77 | batch.add(String.valueOf(i));
|
62 | 78 | });
|
63 |
| - Assertions.assertThat(sync).completes(); |
64 |
| - long end = System.nanoTime(); |
65 |
| - // System.out.println("Done in " + Duration.ofNanos(end - start)); |
66 |
| - // reporter.report(); |
67 |
| - } finally { |
68 |
| - batch.close(); |
| 79 | + assertThat(sync).completes(); |
| 80 | + // printHistogram(batchSizeMetrics); |
| 81 | + } |
| 82 | + } |
| 83 | + |
| 84 | + @Test |
| 85 | + void failedProcessingIsReplayed() throws Exception { |
| 86 | + int itemCount = 10000; |
| 87 | + AtomicInteger collected = new AtomicInteger(0); |
| 88 | + AtomicInteger processed = new AtomicInteger(0); |
| 89 | + AtomicBoolean canProcess = new AtomicBoolean(true); |
| 90 | + DynamicBatch.BatchConsumer<String> action = |
| 91 | + items -> { |
| 92 | + boolean result; |
| 93 | + if (canProcess.get()) { |
| 94 | + collected.addAndGet(items.size()); |
| 95 | + processed.addAndGet(items.size()); |
| 96 | + result = true; |
| 97 | + } else { |
| 98 | + result = false; |
| 99 | + } |
| 100 | + return result; |
| 101 | + }; |
| 102 | + try (DynamicBatch<String> batch = new DynamicBatch<>(action, 100)) { |
| 103 | + int firstRoundCount = itemCount / 5; |
| 104 | + IntStream.range(0, firstRoundCount) |
| 105 | + .forEach( |
| 106 | + i -> { |
| 107 | + batch.add(String.valueOf(i)); |
| 108 | + }); |
| 109 | + waitAtMost(() -> processed.get() == firstRoundCount); |
| 110 | + canProcess.set(false); |
| 111 | + IntStream.range(firstRoundCount, itemCount) |
| 112 | + .forEach( |
| 113 | + i -> { |
| 114 | + batch.add(String.valueOf(i)); |
| 115 | + }); |
| 116 | + canProcess.set(true); |
| 117 | + waitAtMost(() -> processed.get() == itemCount); |
| 118 | + waitAtMost(() -> collected.get() == itemCount); |
69 | 119 | }
|
70 | 120 | }
|
71 | 121 | }
|
0 commit comments