|
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