package eu.lucaventuri.fibry; import eu.lucaventuri.common.SystemUtils; import org.junit.Test; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Flow; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; class PublisherTest implements Flow.Publisher<Integer> { private final AtomicInteger numSent = new AtomicInteger(); private final int numMax = 1000; @Override public void subscribe(Flow.Subscriber<? super Integer> subscriber) { subscriber.onSubscribe(new Flow.Subscription() { private final AtomicBoolean completed = new AtomicBoolean(false); private final AtomicInteger numMessagesToSend = new AtomicInteger(); private final Actor<Flow.Subscriber<? super Integer>, Void, Void> actorRefill = ActorSystem.anonymous().newActor(sub -> { while (numSent.get() < numMax && numMessagesToSend.get() > 0) { subscriber.onNext(numSent.incrementAndGet()); numMessagesToSend.decrementAndGet(); } if (numSent.get() >= numMax) { if (completed.compareAndSet(false, true)) subscriber.onComplete(); } }); @Override public void request(long n) { if (numSent.get() >= numMax) return; numMessagesToSend.accumulateAndGet((int) n, Math::max); actorRefill.sendMessage(subscriber); } @Override public void cancel() { numSent.set(numMax); } }); } } public class TestReactiveSubscribers { @Test public void testReactive() throws InterruptedException { final AtomicLong maxQueueSize = new AtomicLong(); final AtomicLong maxNum = new AtomicLong(); final AtomicInteger numReceived = new AtomicInteger(); final CountDownLatch latch = new CountDownLatch(1); var pub = new PublisherTest(); var sub = ActorSystem.anonymous().initialState(new AtomicInteger()).<Integer>newActor((num, actor) -> { numReceived.incrementAndGet(); actor.getState().addAndGet(num); if (num>maxNum.get()) maxNum.set(num); long queueLen = ((Actor) actor).getQueueLength(); if (maxQueueSize.get() < queueLen) maxQueueSize.set(queueLen); SystemUtils.sleep(1); }).asReactiveSubscriber(100, null, actor -> { System.out.println("Total: " + actor.getState().get()); System.out.println("Max Queue size: " + maxQueueSize.get()); System.out.println("Messages received: " + numReceived.get()); System.out.println("Max Num: " + maxNum.get()); latch.countDown(); }); pub.subscribe(sub); latch.await(); } }