Java Code Examples for reactor.core.scheduler.Schedulers#fromExecutorService()

The following examples show how to use reactor.core.scheduler.Schedulers#fromExecutorService() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: FluxPublishOnTest.java    From reactor-core with Apache License 2.0 6 votes vote down vote up
@Test
public void crossRangePerfDefault() {
	AssertSubscriber<Integer> ts = AssertSubscriber.create();

	Scheduler scheduler = Schedulers.fromExecutorService(exec);

	int count = 1000;

	Flux<Integer> source = Flux.range(1, count)
	                           .flatMap(v -> Flux.range(v, 2), false, 128, 32);

	source.publishOn(scheduler)
	      .subscribe(ts);

	if (!ts.await(Duration.ofSeconds(10))
	       .isTerminated()) {
		ts.cancel();
	}

	ts.assertValueCount(count * 2)
	  .assertNoError()
	  .assertComplete();
}
 
Example 2
Source File: DefaultLocalScheduler.java    From titus-control-plane with Apache License 2.0 6 votes vote down vote up
@Override
public ScheduleReference schedule(ScheduleDescriptor scheduleDescriptor, Consumer<ExecutionContext> action, ExecutorService executorService) {
    Scheduler actionScheduler;
    Runnable cleanup;
    if (executorService != null) {
        actionScheduler = Schedulers.fromExecutorService(executorService);
        cleanup = executorService::shutdown;
    } else {
        actionScheduler = this.scheduler;
        cleanup = DO_NOTHING;
    }

    return scheduleInternal(scheduleDescriptor, executionContext -> Mono.defer(() -> {
        try {
            action.accept(executionContext);
            return Mono.empty();
        } catch (Exception e) {
            return Mono.error(e);
        }
    }), actionScheduler, cleanup);
}
 
Example 3
Source File: SimpleFifoPoolTest.java    From reactor-pool with Apache License 2.0 6 votes vote down vote up
@Test
@Tag("loops")
void acquireReleaseRaceWithMinSize_loop() {
    final Scheduler racer = Schedulers.fromExecutorService(Executors.newFixedThreadPool(2));
    AtomicInteger newCount = new AtomicInteger();
    try {
        PoolConfig<PoolableTest> testConfig = from(Mono.fromCallable(() -> new PoolableTest(newCount.getAndIncrement())))
                .sizeBetween(4, 5)
                .buildConfig();
        SimpleFifoPool<PoolableTest> pool = new SimpleFifoPool<>(testConfig);

        for (int i = 0; i < 100; i++) {
            RaceTestUtils.race(() -> pool.acquire().block().release().block(),
                    () -> pool.acquire().block().release().block(),
                    racer);
        }
        //we expect that only 3 element was created
        assertThat(newCount).as("elements created in total").hasValue(4);
    }
    finally {
        racer.dispose();
    }
}
 
Example 4
Source File: SimpleFifoPoolTest.java    From reactor-pool with Apache License 2.0 5 votes vote down vote up
@Test
void defaultThreadDeliveringWhenNoElementsAndFull() throws InterruptedException {
    AtomicReference<String> threadName = new AtomicReference<>();
    Scheduler acquireScheduler = Schedulers.newSingle("acquire");
    Scheduler releaseScheduler = Schedulers.fromExecutorService(
            Executors.newSingleThreadScheduledExecutor((r -> new Thread(r,"release"))));
    PoolConfig<PoolableTest> testConfig = poolableTestConfig(1, 1,
            Mono.fromCallable(PoolableTest::new)
                .subscribeOn(Schedulers.newParallel("poolable test allocator")));
    SimpleFifoPool<PoolableTest> pool = new SimpleFifoPool<>(testConfig);

    //the pool is started with one elements, and has capacity for 1.
    //we actually first acquire that element so that next acquire will wait for a release
    PooledRef<PoolableTest> uniqueSlot = pool.acquire().block();
    assertThat(uniqueSlot).isNotNull();

    //we prepare next acquire
    Mono<PooledRef<PoolableTest>> borrower = pool.acquire();
    CountDownLatch latch = new CountDownLatch(1);

    //we actually perform the acquire from its dedicated thread, capturing the thread on which the element will actually get delivered
    acquireScheduler.schedule(() -> borrower.subscribe(v -> threadName.set(Thread.currentThread().getName()),
            e -> latch.countDown(), latch::countDown));
    //after a short while, we release the acquired unique element from a third thread
    releaseScheduler.schedule(uniqueSlot.release()::block, 500, TimeUnit.MILLISECONDS);
    latch.await(1, TimeUnit.SECONDS);

    assertThat(threadName.get())
            .isEqualTo("release");
}
 
Example 5
Source File: DefaultDirectKubeApiServerIntegrator.java    From titus-control-plane with Apache License 2.0 5 votes vote down vote up
@Inject
public DefaultDirectKubeApiServerIntegrator(DirectKubeConfiguration configuration,
                                            KubeApiFacade kubeApiFacade,
                                            TaskToPodConverter taskToPodConverter,
                                            TitusRuntime titusRuntime) {
    this.configuration = configuration;
    this.kubeApiFacade = kubeApiFacade;
    this.taskToPodConverter = taskToPodConverter;
    this.podCreateErrorToReasonCodeResolver = new PodCreateErrorToResultCodeResolver(configuration);
    this.titusRuntime = titusRuntime;

    this.metrics = new DefaultDirectKubeApiServerIntegratorMetrics(titusRuntime);
    metrics.observePodsCollection(pods);

    this.apiClientExecutor = ExecutorsExt.instrumentedFixedSizeThreadPool(titusRuntime.getRegistry(), "kube-apiclient", configuration.getApiClientThreadPoolSize());
    this.apiClientScheduler = Schedulers.fromExecutorService(apiClientExecutor);

    FitFramework fit = titusRuntime.getFitFramework();
    if (fit.isActive()) {
        FitInjection fitKubeInjection = fit.newFitInjectionBuilder("directKubeIntegration")
                .withDescription("DefaultDirectKubeApiServerIntegrator injection")
                .build();
        fit.getRootComponent().getChild(DirectKubeApiServerIntegrator.COMPONENT).addInjection(fitKubeInjection);
        this.fitKubeInjection = Optional.of(fitKubeInjection);
    } else {
        this.fitKubeInjection = Optional.empty();
    }
}
 
Example 6
Source File: SimpleLifoPoolTest.java    From reactor-pool with Apache License 2.0 5 votes vote down vote up
@Test
void consistentThreadDeliveringWhenNoElementsAndFull() throws InterruptedException {
    Scheduler deliveryScheduler = Schedulers.newSingle("delivery");
    AtomicReference<String> threadName = new AtomicReference<>();
    Scheduler acquireScheduler = Schedulers.newSingle("acquire");
    Scheduler releaseScheduler = Schedulers.fromExecutorService(
            Executors.newSingleThreadScheduledExecutor((r -> new Thread(r,"release"))));
    PoolConfig<PoolableTest> testConfig = poolableTestConfig(1, 1,
            Mono.fromCallable(PoolableTest::new)
                .subscribeOn(Schedulers.newParallel("poolable test allocator")),
            deliveryScheduler);
    SimpleLifoPool<PoolableTest> pool = new SimpleLifoPool<>(testConfig);

    //the pool is started with one elements, and has capacity for 1.
    //we actually first acquire that element so that next acquire will wait for a release
    PooledRef<PoolableTest> uniqueSlot = pool.acquire().block();
    assertThat(uniqueSlot).isNotNull();

    //we prepare next acquire
    Mono<PoolableTest> borrower = Mono.fromDirect(pool.withPoolable(Mono::just));
    CountDownLatch latch = new CountDownLatch(1);

    //we actually perform the acquire from its dedicated thread, capturing the thread on which the element will actually get delivered
    acquireScheduler.schedule(() -> borrower.subscribe(v -> threadName.set(Thread.currentThread().getName()),
            e -> latch.countDown(), latch::countDown));
    //after a short while, we release the acquired unique element from a third thread
    releaseScheduler.schedule(uniqueSlot.release()::block, 500, TimeUnit.MILLISECONDS);
    latch.await(1, TimeUnit.SECONDS);

    assertThat(threadName.get())
            .startsWith("delivery-");
}
 
Example 7
Source File: SimpleLifoPoolTest.java    From reactor-pool with Apache License 2.0 5 votes vote down vote up
@Test
void defaultThreadDeliveringWhenNoElementsAndFull() throws InterruptedException {
    AtomicReference<String> threadName = new AtomicReference<>();
    Scheduler acquireScheduler = Schedulers.newSingle("acquire");
    Scheduler releaseScheduler = Schedulers.fromExecutorService(
            Executors.newSingleThreadScheduledExecutor((r -> new Thread(r,"release"))));
    PoolConfig<PoolableTest> testConfig = poolableTestConfig(1, 1,
            Mono.fromCallable(PoolableTest::new)
                .subscribeOn(Schedulers.newParallel("poolable test allocator")));
    SimpleLifoPool<PoolableTest> pool = new SimpleLifoPool<>(testConfig);

    //the pool is started with one elements, and has capacity for 1.
    //we actually first acquire that element so that next acquire will wait for a release
    PooledRef<PoolableTest> uniqueSlot = pool.acquire().block();
    assertThat(uniqueSlot).isNotNull();

    //we prepare next acquire
    Mono<PoolableTest> borrower = Mono.fromDirect(pool.withPoolable(Mono::just));
    CountDownLatch latch = new CountDownLatch(1);

    //we actually perform the acquire from its dedicated thread, capturing the thread on which the element will actually get delivered
    acquireScheduler.schedule(() -> borrower.subscribe(v -> threadName.set(Thread.currentThread().getName()),
            e -> latch.countDown(), latch::countDown));
    //after a short while, we release the acquired unique element from a third thread
    releaseScheduler.schedule(uniqueSlot.release()::block, 500, TimeUnit.MILLISECONDS);
    latch.await(1, TimeUnit.SECONDS);

    assertThat(threadName.get())
            .isEqualTo("release");
}
 
Example 8
Source File: SimpleLifoPoolTest.java    From reactor-pool with Apache License 2.0 5 votes vote down vote up
@Test
void consistentThreadDeliveringWhenNoElementsAndFull() throws InterruptedException {
    Scheduler deliveryScheduler = Schedulers.newSingle("delivery");
    AtomicReference<String> threadName = new AtomicReference<>();
    Scheduler acquireScheduler = Schedulers.newSingle("acquire");
    Scheduler releaseScheduler = Schedulers.fromExecutorService(
            Executors.newSingleThreadScheduledExecutor((r -> new Thread(r,"release"))));
    PoolConfig<PoolableTest> testConfig = poolableTestConfig(1, 1,
            Mono.fromCallable(PoolableTest::new)
                .subscribeOn(Schedulers.newParallel("poolable test allocator")),
            deliveryScheduler);
    SimpleLifoPool<PoolableTest> pool = new SimpleLifoPool<>(testConfig);

    //the pool is started with one elements, and has capacity for 1.
    //we actually first acquire that element so that next acquire will wait for a release
    PooledRef<PoolableTest> uniqueSlot = pool.acquire().block();
    assertThat(uniqueSlot).isNotNull();

    //we prepare next acquire
    Mono<PooledRef<PoolableTest>> borrower = pool.acquire();
    CountDownLatch latch = new CountDownLatch(1);

    //we actually perform the acquire from its dedicated thread, capturing the thread on which the element will actually get delivered
    acquireScheduler.schedule(() -> borrower.subscribe(v -> threadName.set(Thread.currentThread().getName()),
            e -> latch.countDown(), latch::countDown));
    //after a short while, we release the acquired unique element from a third thread
    releaseScheduler.schedule(uniqueSlot.release()::block, 500, TimeUnit.MILLISECONDS);
    latch.await(1, TimeUnit.SECONDS);

    assertThat(threadName.get())
            .startsWith("delivery-");
}
 
Example 9
Source File: SimpleLifoPoolTest.java    From reactor-pool with Apache License 2.0 5 votes vote down vote up
@Test
void defaultThreadDeliveringWhenNoElementsAndFull() throws InterruptedException {
    AtomicReference<String> threadName = new AtomicReference<>();
    Scheduler acquireScheduler = Schedulers.newSingle("acquire");
    Scheduler releaseScheduler = Schedulers.fromExecutorService(
            Executors.newSingleThreadScheduledExecutor((r -> new Thread(r,"release"))));
    PoolConfig<PoolableTest> testConfig = poolableTestConfig(1, 1,
            Mono.fromCallable(PoolableTest::new)
                .subscribeOn(Schedulers.newParallel("poolable test allocator")));
    SimpleLifoPool<PoolableTest> pool = new SimpleLifoPool<>(testConfig);

    //the pool is started with one elements, and has capacity for 1.
    //we actually first acquire that element so that next acquire will wait for a release
    PooledRef<PoolableTest> uniqueSlot = pool.acquire().block();
    assertThat(uniqueSlot).isNotNull();

    //we prepare next acquire
    Mono<PooledRef<PoolableTest>> borrower = pool.acquire();
    CountDownLatch latch = new CountDownLatch(1);

    //we actually perform the acquire from its dedicated thread, capturing the thread on which the element will actually get delivered
    acquireScheduler.schedule(() -> borrower.subscribe(v -> threadName.set(Thread.currentThread().getName()),
            e -> latch.countDown(), latch::countDown));
    //after a short while, we release the acquired unique element from a third thread
    releaseScheduler.schedule(uniqueSlot.release()::block, 500, TimeUnit.MILLISECONDS);
    latch.await(1, TimeUnit.SECONDS);

    assertThat(threadName.get())
            .isEqualTo("release");
}
 
Example 10
Source File: SimpleFifoPoolTest.java    From reactor-pool with Apache License 2.0 5 votes vote down vote up
@Test
void consistentThreadDeliveringWhenNoElementsAndFull() throws InterruptedException {
    Scheduler deliveryScheduler = Schedulers.newSingle("delivery");
    AtomicReference<String> threadName = new AtomicReference<>();
    Scheduler acquireScheduler = Schedulers.newSingle("acquire");
    Scheduler releaseScheduler = Schedulers.fromExecutorService(
            Executors.newSingleThreadScheduledExecutor((r -> new Thread(r,"release"))));
    PoolConfig<PoolableTest> testConfig = poolableTestConfig(1, 1,
            Mono.fromCallable(PoolableTest::new)
                .subscribeOn(Schedulers.newParallel("poolable test allocator")),
            deliveryScheduler);
    SimpleFifoPool<PoolableTest> pool = new SimpleFifoPool<>(testConfig);

    //the pool is started with one elements, and has capacity for 1.
    //we actually first acquire that element so that next acquire will wait for a release
    PooledRef<PoolableTest> uniqueSlot = pool.acquire().block();
    assertThat(uniqueSlot).isNotNull();

    //we prepare next acquire
    Mono<PoolableTest> borrower = Mono.fromDirect(pool.withPoolable(Mono::just));
    CountDownLatch latch = new CountDownLatch(1);

    //we actually perform the acquire from its dedicated thread, capturing the thread on which the element will actually get delivered
    acquireScheduler.schedule(() -> borrower.subscribe(v -> threadName.set(Thread.currentThread().getName()),
            e -> latch.countDown(), latch::countDown));
    //after a short while, we release the acquired unique element from a third thread
    releaseScheduler.schedule(uniqueSlot.release()::block, 500, TimeUnit.MILLISECONDS);
    latch.await(1, TimeUnit.SECONDS);

    assertThat(threadName.get())
            .startsWith("delivery-");
}
 
Example 11
Source File: SimpleFifoPoolTest.java    From reactor-pool with Apache License 2.0 5 votes vote down vote up
@Test
void defaultThreadDeliveringWhenNoElementsAndFull() throws InterruptedException {
    AtomicReference<String> threadName = new AtomicReference<>();
    Scheduler acquireScheduler = Schedulers.newSingle("acquire");
    Scheduler releaseScheduler = Schedulers.fromExecutorService(
            Executors.newSingleThreadScheduledExecutor((r -> new Thread(r,"release"))));
    PoolConfig<PoolableTest> testConfig = poolableTestConfig(1, 1,
            Mono.fromCallable(PoolableTest::new)
                .subscribeOn(Schedulers.newParallel("poolable test allocator")));
    SimpleFifoPool<PoolableTest> pool = new SimpleFifoPool<>(testConfig);

    //the pool is started with one elements, and has capacity for 1.
    //we actually first acquire that element so that next acquire will wait for a release
    PooledRef<PoolableTest> uniqueSlot = pool.acquire().block();
    assertThat(uniqueSlot).isNotNull();

    //we prepare next acquire
    Mono<PoolableTest> borrower = Mono.fromDirect(pool.withPoolable(Mono::just));
    CountDownLatch latch = new CountDownLatch(1);

    //we actually perform the acquire from its dedicated thread, capturing the thread on which the element will actually get delivered
    acquireScheduler.schedule(() -> borrower.subscribe(v -> threadName.set(Thread.currentThread().getName()),
            e -> latch.countDown(), latch::countDown));
    //after a short while, we release the acquired unique element from a third thread
    releaseScheduler.schedule(uniqueSlot.release()::block, 500, TimeUnit.MILLISECONDS);
    latch.await(1, TimeUnit.SECONDS);

    assertThat(threadName.get())
            .isEqualTo("release");
}
 
Example 12
Source File: SimpleFifoPoolTest.java    From reactor-pool with Apache License 2.0 5 votes vote down vote up
@Test
void consistentThreadDeliveringWhenNoElementsAndFull() throws InterruptedException {
    Scheduler deliveryScheduler = Schedulers.newSingle("delivery");
    AtomicReference<String> threadName = new AtomicReference<>();
    Scheduler acquireScheduler = Schedulers.newSingle("acquire");
    Scheduler releaseScheduler = Schedulers.fromExecutorService(
            Executors.newSingleThreadScheduledExecutor((r -> new Thread(r,"release"))));
    PoolConfig<PoolableTest> testConfig = poolableTestConfig(1, 1,
            Mono.fromCallable(PoolableTest::new)
                .subscribeOn(Schedulers.newParallel("poolable test allocator")),
            deliveryScheduler);
    SimpleFifoPool<PoolableTest> pool = new SimpleFifoPool<>(testConfig);

    //the pool is started with one elements, and has capacity for 1.
    //we actually first acquire that element so that next acquire will wait for a release
    PooledRef<PoolableTest> uniqueSlot = pool.acquire().block();
    assertThat(uniqueSlot).isNotNull();

    //we prepare next acquire
    Mono<PooledRef<PoolableTest>> borrower = pool.acquire();
    CountDownLatch latch = new CountDownLatch(1);

    //we actually perform the acquire from its dedicated thread, capturing the thread on which the element will actually get delivered
    acquireScheduler.schedule(() -> borrower.subscribe(v -> threadName.set(Thread.currentThread().getName()),
            e -> latch.countDown(), latch::countDown));
    //after a short while, we release the acquired unique element from a third thread
    releaseScheduler.schedule(uniqueSlot.release()::block, 500, TimeUnit.MILLISECONDS);
    latch.await(1, TimeUnit.SECONDS);

    assertThat(threadName.get())
            .startsWith("delivery-");
}
 
Example 13
Source File: SimpleFifoPoolTest.java    From reactor-pool with Apache License 2.0 4 votes vote down vote up
void consistentThreadDeliveringWhenNoElementsAndFullAndRaceDrain(int i) throws InterruptedException {
    Scheduler deliveryScheduler = Schedulers.newSingle("delivery");
    AtomicReference<String> threadName = new AtomicReference<>();
    AtomicInteger newCount = new AtomicInteger();

    Scheduler acquire1Scheduler = Schedulers.newSingle("acquire1");
    Scheduler racerReleaseScheduler = Schedulers.fromExecutorService(
            Executors.newSingleThreadScheduledExecutor((r -> new Thread(r,"racerRelease"))));
    Scheduler racerAcquireScheduler = Schedulers.newSingle("racerAcquire");

    PoolConfig<PoolableTest> testConfig = poolableTestConfig(1, 1,
            Mono.fromCallable(() -> new PoolableTest(newCount.getAndIncrement()))
                .subscribeOn(Schedulers.newParallel("poolable test allocator")),
            deliveryScheduler);
    SimpleFifoPool<PoolableTest> pool = new SimpleFifoPool<>(testConfig);

    //the pool is started with one elements, and has capacity for 1.
    //we actually first acquire that element so that next acquire will wait for a release
    PooledRef<PoolableTest> uniqueSlot = pool.acquire().block();
    assertThat(uniqueSlot).isNotNull();

    //we prepare next acquire
    Mono<PoolableTest> borrower = Mono.fromDirect(pool.withPoolable(Mono::just));
    CountDownLatch latch = new CountDownLatch(1);

    //we actually perform the acquire from its dedicated thread, capturing the thread on which the element will actually get delivered
    acquire1Scheduler.schedule(() -> borrower.subscribe(v -> threadName.set(Thread.currentThread().getName())
            , e -> latch.countDown(), latch::countDown));

    //in parallel, we'll both attempt a second acquire AND release the unique element (each on their dedicated threads
    Mono<PooledRef<PoolableTest>> otherBorrower = pool.acquire();
    racerAcquireScheduler.schedule(() -> otherBorrower.subscribe().dispose(), 100, TimeUnit.MILLISECONDS);
    racerReleaseScheduler.schedule(uniqueSlot.release()::block, 100, TimeUnit.MILLISECONDS);
    latch.await(1, TimeUnit.SECONDS);

    //we expect that, consistently, the poolable is delivered on a `delivery` thread
    assertThat(threadName.get()).as("round #" + i).startsWith("delivery-");

    //we expect that only 1 element was created
    assertThat(newCount).as("elements created in round " + i).hasValue(1);
}
 
Example 14
Source File: SimpleFifoPoolTest.java    From reactor-pool with Apache License 2.0 4 votes vote down vote up
void defaultThreadDeliveringWhenNoElementsAndFullAndRaceDrain(int round, AtomicInteger releaserWins, AtomicInteger borrowerWins) throws InterruptedException {
    AtomicReference<String> threadName = new AtomicReference<>();
    AtomicInteger newCount = new AtomicInteger();
    Scheduler acquire1Scheduler = Schedulers.newSingle("acquire1");
    Scheduler racerReleaseScheduler = Schedulers.fromExecutorService(
            Executors.newSingleThreadScheduledExecutor((r -> new Thread(r,"racerRelease"))));
    Scheduler racerAcquireScheduler = Schedulers.fromExecutorService(
            Executors.newSingleThreadScheduledExecutor((r -> new Thread(r,"racerAcquire"))));
    Scheduler allocatorScheduler = Schedulers.newParallel("poolable test allocator");

    try {
        PoolConfig<PoolableTest> testConfig = poolableTestConfig(1, 1,
                Mono.fromCallable(() -> new PoolableTest(newCount.getAndIncrement()))
                    .subscribeOn(allocatorScheduler));

        SimpleFifoPool<PoolableTest> pool = new SimpleFifoPool<>(testConfig);

        //the pool is started with one elements, and has capacity for 1.
        //we actually first acquire that element so that next acquire will wait for a release
        PooledRef<PoolableTest> uniqueSlot = pool.acquire().block();
        assertThat(uniqueSlot).isNotNull();

        //we prepare next acquire
        Mono<PoolableTest> borrower = Mono.fromDirect(pool.withPoolable(Mono::just));
        CountDownLatch latch = new CountDownLatch(3);

        //we actually perform the acquire from its dedicated thread, capturing the thread on which the element will actually get delivered
        acquire1Scheduler.schedule(() -> borrower.subscribe(v -> threadName.set(Thread.currentThread().getName())
                , e -> latch.countDown(), latch::countDown));

        //in parallel, we'll both attempt concurrent acquire AND release the unique element (each on their dedicated threads)
        racerAcquireScheduler.schedule(() -> {
            pool.acquire().block();
            latch.countDown();
        }, 100, TimeUnit.MILLISECONDS);
        racerReleaseScheduler.schedule(() -> {
            uniqueSlot.release().block();
            latch.countDown();
        }, 100, TimeUnit.MILLISECONDS);

        assertThat(latch.await(1, TimeUnit.SECONDS)).as("1s").isTrue();

        assertThat(newCount).as("created 1 poolable in round " + round).hasValue(1);

        //we expect that sometimes the race will let the second borrower thread drain, which would mean first borrower
        //will get the element delivered from racerAcquire thread. Yet the rest of the time it would get drained by racerRelease.
        if (threadName.get().startsWith("racerRelease")) releaserWins.incrementAndGet();
        else if (threadName.get().startsWith("racerAcquire")) borrowerWins.incrementAndGet();
        else System.out.println(threadName.get());
    }
    finally {
        acquire1Scheduler.dispose();
        racerAcquireScheduler.dispose();
        racerReleaseScheduler.dispose();
        allocatorScheduler.dispose();
    }
}
 
Example 15
Source File: SimpleLifoPoolTest.java    From reactor-pool with Apache License 2.0 4 votes vote down vote up
void consistentThreadDeliveringWhenNoElementsAndFullAndRaceDrain(int i) throws InterruptedException {
    Scheduler allocatorScheduler = Schedulers.newParallel("poolable test allocator");
    Scheduler deliveryScheduler = Schedulers.newSingle("delivery");
    Scheduler acquire1Scheduler = Schedulers.newSingle("acquire1");
    Scheduler racerScheduler = Schedulers.fromExecutorService(Executors.newFixedThreadPool(2, r -> new Thread(r, "racer")));
    try {
        AtomicReference<String> threadName = new AtomicReference<>();
        AtomicInteger newCount = new AtomicInteger();

        PoolConfig<PoolableTest> testConfig = poolableTestConfig(1, 1,
                Mono.fromCallable(() -> new PoolableTest(newCount.getAndIncrement()))
                    .subscribeOn(allocatorScheduler),
                deliveryScheduler);
        SimpleLifoPool<PoolableTest> pool = new SimpleLifoPool<>(testConfig);

        //the pool is started with one elements, and has capacity for 1.
        //we actually first acquire that element so that next acquire will wait for a release
        PooledRef<PoolableTest> uniqueSlot = pool.acquire().block();
        assertThat(uniqueSlot).isNotNull();

        //we prepare two more acquires
        Mono<PooledRef<PoolableTest>> firstBorrower = pool.acquire();
        Mono<PooledRef<PoolableTest>> secondBorrower = pool.acquire();

        CountDownLatch latch = new CountDownLatch(1);

        //we'll enqueue a first acquire from a first thread
        //in parallel, we'll race a second acquire AND release the unique element (each on their dedicated threads)
        //we expect the release might sometimes win, which would mean acquire 1 would get served. mostly we want to verify delivery thread though
        acquire1Scheduler.schedule(() -> firstBorrower.subscribe(v -> threadName.compareAndSet(null, Thread.currentThread().getName())
                , e -> latch.countDown(), latch::countDown));
        RaceTestUtils.race(() -> secondBorrower.subscribe(v -> threadName.compareAndSet(null, Thread.currentThread().getName())
                , e -> latch.countDown(), latch::countDown),
                uniqueSlot.release()::block);

        latch.await(1, TimeUnit.SECONDS);

        //we expect that, consistently, the poolable is delivered on a `delivery` thread
        assertThat(threadName.get()).as("round #" + i).startsWith("delivery-");

        //we expect that only 1 element was created
        assertThat(newCount).as("elements created in round " + i).hasValue(1);
    }
    finally {
        allocatorScheduler.dispose();
        deliveryScheduler.dispose();
        racerScheduler.dispose();
        acquire1Scheduler.dispose();
    }
}
 
Example 16
Source File: SimpleFifoPoolTest.java    From reactor-pool with Apache License 2.0 4 votes vote down vote up
void consistentThreadDeliveringWhenNoElementsAndFullAndRaceDrain(int i) throws InterruptedException {
    Scheduler deliveryScheduler = Schedulers.newSingle("delivery");
    AtomicReference<String> threadName = new AtomicReference<>();
    AtomicInteger newCount = new AtomicInteger();

    Scheduler acquire1Scheduler = Schedulers.newSingle("acquire1");
    Scheduler racerReleaseScheduler = Schedulers.fromExecutorService(
            Executors.newSingleThreadScheduledExecutor((r -> new Thread(r,"racerRelease"))));
    Scheduler racerAcquireScheduler = Schedulers.newSingle("racerAcquire");

    PoolConfig<PoolableTest> testConfig = poolableTestConfig(1, 1,
            Mono.fromCallable(() -> new PoolableTest(newCount.getAndIncrement()))
                .subscribeOn(Schedulers.newParallel("poolable test allocator")),
            deliveryScheduler);
    SimpleFifoPool<PoolableTest> pool = new SimpleFifoPool<>(testConfig);

    //the pool is started with one elements, and has capacity for 1.
    //we actually first acquire that element so that next acquire will wait for a release
    PooledRef<PoolableTest> uniqueSlot = pool.acquire().block();
    assertThat(uniqueSlot).isNotNull();

    //we prepare next acquire
    Mono<PooledRef<PoolableTest>> borrower = pool.acquire();
    CountDownLatch latch = new CountDownLatch(1);

    //we actually perform the acquire from its dedicated thread, capturing the thread on which the element will actually get delivered
    acquire1Scheduler.schedule(() -> borrower.subscribe(v -> threadName.set(Thread.currentThread().getName())
            , e -> latch.countDown(), latch::countDown));

    //in parallel, we'll both attempt a second acquire AND release the unique element (each on their dedicated threads
    Mono<PooledRef<PoolableTest>> otherBorrower = pool.acquire();
    racerAcquireScheduler.schedule(() -> otherBorrower.subscribe().dispose(), 100, TimeUnit.MILLISECONDS);
    racerReleaseScheduler.schedule(uniqueSlot.release()::block, 100, TimeUnit.MILLISECONDS);
    latch.await(1, TimeUnit.SECONDS);

    //we expect that, consistently, the poolable is delivered on a `delivery` thread
    assertThat(threadName.get()).as("round #" + i).startsWith("delivery-");

    //we expect that only 1 element was created
    assertThat(newCount).as("elements created in round " + i).hasValue(1);
}
 
Example 17
Source File: SimpleLifoPoolTest.java    From reactor-pool with Apache License 2.0 4 votes vote down vote up
void consistentThreadDeliveringWhenNoElementsAndFullAndRaceDrain(int i) throws InterruptedException {
    Scheduler allocatorScheduler = Schedulers.newParallel("poolable test allocator");
    Scheduler deliveryScheduler = Schedulers.newSingle("delivery");
    Scheduler acquire1Scheduler = Schedulers.newSingle("acquire1");
    Scheduler racerScheduler = Schedulers.fromExecutorService(
            Executors.newFixedThreadPool(2, (r -> new Thread(r,"racer"))));

    try {
        AtomicReference<String> threadName = new AtomicReference<>();
        AtomicInteger newCount = new AtomicInteger();


        PoolConfig<PoolableTest> testConfig = poolableTestConfig(1, 1,
                Mono.fromCallable(() -> new PoolableTest(newCount.getAndIncrement()))
                    .subscribeOn(allocatorScheduler),
                deliveryScheduler);
        SimpleLifoPool<PoolableTest> pool = new SimpleLifoPool<>(testConfig);

        //the pool is started with one elements, and has capacity for 1.
        //we actually first acquire that element so that next acquire will wait for a release
        PooledRef<PoolableTest> uniqueSlot = pool.acquire().block();
        assertThat(uniqueSlot).isNotNull();

        //we prepare next acquire
        Mono<PoolableTest> firstBorrower = Mono.fromDirect(pool.withPoolable(Mono::just));
        Mono<PoolableTest> otherBorrower = Mono.fromDirect(pool.withPoolable(Mono::just));

        CountDownLatch latch = new CountDownLatch(3);

        //we actually perform the acquire from its dedicated thread, capturing the thread on which the element will actually get delivered
        acquire1Scheduler.schedule(() -> firstBorrower.subscribe(v -> threadName.set(Thread.currentThread().getName())
                , e -> latch.countDown(), latch::countDown));

        //in parallel, we'll race a second acquire AND release the unique element (each on their dedicated threads)
        //since LIFO we expect that if the release loses, it will server acquire1
        RaceTestUtils.race(
                () -> otherBorrower.subscribe(v -> threadName.set(Thread.currentThread().getName())
                        , e -> latch.countDown(), latch::countDown),
                () -> {
                    uniqueSlot.release().block();
                    latch.countDown();
                },
                racerScheduler);
        latch.await(1, TimeUnit.SECONDS);

        //we expect that, consistently, the poolable is delivered on a `delivery` thread
        assertThat(threadName.get()).as("round #" + i).startsWith("delivery-");

        //2 elements MIGHT be created if the first acquire wins (since we're in auto-release mode)
        assertThat(newCount.get()).as("1 or 2 elements created in round " + i).isIn(1, 2);
    }
    finally {
        allocatorScheduler.dispose();
        deliveryScheduler.dispose();
        acquire1Scheduler.dispose();
        racerScheduler.dispose();
    }
}
 
Example 18
Source File: SimpleFifoPoolTest.java    From reactor-pool with Apache License 2.0 4 votes vote down vote up
void defaultThreadDeliveringWhenNoElementsAndFullAndRaceDrain(int round, AtomicInteger releaserWins, AtomicInteger borrowerWins) throws InterruptedException {
    AtomicReference<String> threadName = new AtomicReference<>();
    AtomicInteger newCount = new AtomicInteger();
    Scheduler acquire1Scheduler = Schedulers.newSingle("acquire1");
    Scheduler racerReleaseScheduler = Schedulers.fromExecutorService(
            Executors.newSingleThreadScheduledExecutor((r -> new Thread(r,"racerRelease"))));
    Scheduler racerAcquireScheduler = Schedulers.fromExecutorService(
            Executors.newSingleThreadScheduledExecutor((r -> new Thread(r,"racerAcquire"))));

    PoolConfig<PoolableTest> testConfig = poolableTestConfig(1, 1,
            Mono.fromCallable(() -> new PoolableTest(newCount.getAndIncrement()))
                .subscribeOn(Schedulers.newParallel("poolable test allocator")));

    SimpleFifoPool<PoolableTest> pool = new SimpleFifoPool<>(testConfig);

    //the pool is started with one elements, and has capacity for 1.
    //we actually first acquire that element so that next acquire will wait for a release
    PooledRef<PoolableTest> uniqueSlot = pool.acquire().block();
    assertThat(uniqueSlot).isNotNull();

    //we prepare next acquire
    Mono<PooledRef<PoolableTest>> borrower = pool.acquire();
    CountDownLatch latch = new CountDownLatch(1);

    //we actually perform the acquire from its dedicated thread, capturing the thread on which the element will actually get delivered
    acquire1Scheduler.schedule(() -> borrower.subscribe(v -> threadName.set(Thread.currentThread().getName())
            , e -> latch.countDown(), latch::countDown));

    //in parallel, we'll both attempt concurrent acquire AND release the unique element (each on their dedicated threads)
    racerAcquireScheduler.schedule(pool.acquire()::block, 100, TimeUnit.MILLISECONDS);
    racerReleaseScheduler.schedule(uniqueSlot.release()::block, 100, TimeUnit.MILLISECONDS);
    latch.await(1, TimeUnit.SECONDS);

    assertThat(newCount).as("created 1 poolable in round " + round).hasValue(1);

    //we expect that sometimes the race will let the second borrower thread drain, which would mean first borrower
    //will get the element delivered from racerAcquire thread. Yet the rest of the time it would get drained by racerRelease.
    if (threadName.get().startsWith("racerRelease")) releaserWins.incrementAndGet();
    else if (threadName.get().startsWith("racerAcquire")) borrowerWins.incrementAndGet();
    else System.out.println(threadName.get());
}
 
Example 19
Source File: ExecutorConfiguration.java    From jetlinks-community with Apache License 2.0 4 votes vote down vote up
@Bean
public Scheduler reactorScheduler(ScheduledExecutorService executorService) {
    return Schedulers.fromExecutorService(executorService);
}
 
Example 20
Source File: BlockingTests.java    From reactor-core with Apache License 2.0 4 votes vote down vote up
@BeforeClass
public static void before() {
	scheduler = Schedulers.fromExecutorService(Executors.newSingleThreadExecutor());
	nonBlockingScheduler = Schedulers.newSingle("nonBlockingScheduler");
}