/** * {@inheritDoc} */ @Override public void changeConfig(final BulkheadConfig newConfig) { synchronized (configChangesLock) { int delta = newConfig.getMaxConcurrentCalls() - config.getMaxConcurrentCalls(); if (delta < 0) { semaphore.acquireUninterruptibly(-delta); } else if (delta > 0) { semaphore.release(delta); } config = newConfig; } }
/** * Creates a bulkhead using a configuration supplied * * @param name the name of this bulkhead * @param bulkheadConfig custom bulkhead configuration */ public SemaphoreBulkhead(String name, BulkheadConfig bulkheadConfig) { this.name = name; this.config = bulkheadConfig != null ? bulkheadConfig : BulkheadConfig.ofDefaults(); // init semaphore this.semaphore = new Semaphore(this.config.getMaxConcurrentCalls(), true); this.metrics = new BulkheadMetrics(); this.eventProcessor = new BulkheadEventProcessor(); }
@Test public void shouldReturnTheCorrectName() { Bulkhead bulkhead = registry.bulkhead("test"); assertThat(bulkhead).isNotNull(); assertThat(bulkhead.getName()).isEqualTo("test"); assertThat(bulkhead.getBulkheadConfig().getMaxConcurrentCalls()).isEqualTo(25); assertThat(bulkhead.getMetrics().getAvailableConcurrentCalls()).isEqualTo(25); }
@Test public void testBuildCustom() { // given int maxConcurrent = 66; long maxWait = 555; // when BulkheadConfig config = BulkheadConfig.custom() .maxConcurrentCalls(maxConcurrent) .maxWaitTime(maxWait) .build(); // then assertThat(config).isNotNull(); assertThat(config.getMaxConcurrentCalls()).isEqualTo(maxConcurrent); assertThat(config.getMaxWaitTime()).isEqualTo(maxWait); }
@Test public void changeWaitTimeInIdleState() { BulkheadConfig originalConfig = BulkheadConfig.custom() .maxConcurrentCalls(3) .maxWaitTime(5000) .build(); SemaphoreBulkhead bulkhead = new SemaphoreBulkhead("test", originalConfig); assertThat(bulkhead.getBulkheadConfig().getMaxConcurrentCalls()).isEqualTo(3); assertThat(bulkhead.getBulkheadConfig().getMaxWaitTime()).isEqualTo(5000); BulkheadConfig newConfig = BulkheadConfig.custom() .maxConcurrentCalls(3) .maxWaitTime(3000) .build(); bulkhead.changeConfig(newConfig); assertThat(bulkhead.getBulkheadConfig().getMaxConcurrentCalls()).isEqualTo(3); assertThat(bulkhead.getBulkheadConfig().getMaxWaitTime()).isEqualTo(3000); newConfig = BulkheadConfig.custom() .maxConcurrentCalls(3) .maxWaitTime(7000) .build(); bulkhead.changeConfig(newConfig); assertThat(bulkhead.getBulkheadConfig().getMaxConcurrentCalls()).isEqualTo(3); assertThat(bulkhead.getBulkheadConfig().getMaxWaitTime()).isEqualTo(7000); bulkhead.changeConfig(newConfig); }
@Test public void changePermissionsInIdleState() { BulkheadConfig originalConfig = BulkheadConfig.custom() .maxConcurrentCalls(3) .maxWaitTime(5000) .build(); SemaphoreBulkhead bulkhead = new SemaphoreBulkhead("test", originalConfig); assertThat(bulkhead.getBulkheadConfig().getMaxConcurrentCalls()).isEqualTo(3); assertThat(bulkhead.getBulkheadConfig().getMaxWaitTime()).isEqualTo(5000); BulkheadConfig newConfig = BulkheadConfig.custom() .maxConcurrentCalls(5) .maxWaitTime(5000) .build(); bulkhead.changeConfig(newConfig); assertThat(bulkhead.getBulkheadConfig().getMaxConcurrentCalls()).isEqualTo(5); assertThat(bulkhead.getBulkheadConfig().getMaxWaitTime()).isEqualTo(5000); newConfig = BulkheadConfig.custom() .maxConcurrentCalls(2) .maxWaitTime(5000) .build(); bulkhead.changeConfig(newConfig); assertThat(bulkhead.getBulkheadConfig().getMaxConcurrentCalls()).isEqualTo(2); assertThat(bulkhead.getBulkheadConfig().getMaxWaitTime()).isEqualTo(5000); bulkhead.changeConfig(newConfig); }
assertThat(bulkhead.getBulkheadConfig().getMaxConcurrentCalls()).isEqualTo(1); Thread bulkheadThread = new Thread(() -> { bulkhead.isCallPermitted(); assertThat(bulkhead.getBulkheadConfig().getMaxConcurrentCalls()).isEqualTo(2); assertThat(bulkhead.getBulkheadConfig().getMaxWaitTime()).isEqualTo(0); assertThat(bulkhead.getMetrics().getAvailableConcurrentCalls()).isEqualTo(1); .until(() -> changerThread.getState().equals(WAITING)); assertThat(bulkhead.getBulkheadConfig().getMaxConcurrentCalls()).isEqualTo(2); assertThat(bulkhead.getBulkheadConfig().getMaxConcurrentCalls()).isEqualTo(1); assertThat(bulkhead.getBulkheadConfig().getMaxConcurrentCalls()).isEqualTo(1);
@Test public void changePermissionsCountWhileOneThreadIsWaitingForPermission() { BulkheadConfig originalConfig = BulkheadConfig.custom() .maxConcurrentCalls(1) .maxWaitTime(500000) .build(); SemaphoreBulkhead bulkhead = new SemaphoreBulkhead("test", originalConfig); assertThat(bulkhead.getMetrics().getAvailableConcurrentCalls()).isEqualTo(1); bulkhead.isCallPermitted(); assertThat(bulkhead.getMetrics().getAvailableConcurrentCalls()).isEqualTo(0); assertThat(bulkhead.getBulkheadConfig().getMaxConcurrentCalls()).isEqualTo(1); Thread bulkheadThread = new Thread(() -> { bulkhead.isCallPermitted(); bulkhead.onComplete(); }); bulkheadThread.setDaemon(true); bulkheadThread.start(); await().atMost(1, SECONDS) .until(() -> bulkheadThread.getState().equals(TIMED_WAITING)); assertThat(bulkhead.getMetrics().getAvailableConcurrentCalls()).isEqualTo(0); BulkheadConfig newConfig = BulkheadConfig.custom() .maxConcurrentCalls(2) .maxWaitTime(500000) .build(); bulkhead.changeConfig(newConfig); await().atMost(1, SECONDS) .until(() -> bulkheadThread.getState().equals(TERMINATED)); assertThat(bulkhead.getBulkheadConfig().getMaxConcurrentCalls()).isEqualTo(2); assertThat(bulkhead.getMetrics().getAvailableConcurrentCalls()).isEqualTo(1); }
@Test public void changeWaitingTimeWhileOneThreadIsWaitingForPermission() { BulkheadConfig originalConfig = BulkheadConfig.custom() .maxConcurrentCalls(1) .maxWaitTime(500000) .build(); SemaphoreBulkhead bulkhead = new SemaphoreBulkhead("test", originalConfig); assertThat(bulkhead.getMetrics().getAvailableConcurrentCalls()).isEqualTo(1); bulkhead.isCallPermitted(); assertThat(bulkhead.getMetrics().getAvailableConcurrentCalls()).isEqualTo(0); assertThat(bulkhead.getBulkheadConfig().getMaxConcurrentCalls()).isEqualTo(1); Thread bulkheadThread = new Thread(() -> { bulkhead.isCallPermitted(); bulkhead.onComplete(); }); bulkheadThread.setDaemon(true); bulkheadThread.start(); await().atMost(1, SECONDS) .until(() -> bulkheadThread.getState().equals(TIMED_WAITING)); assertThat(bulkhead.getMetrics().getAvailableConcurrentCalls()).isEqualTo(0); BulkheadConfig newConfig = BulkheadConfig.custom() .maxConcurrentCalls(1) .maxWaitTime(0) .build(); bulkhead.changeConfig(newConfig); assertThat(bulkhead.tryEnterBulkhead()).isFalse(); // main thread is not blocked // previously blocked thread is still waiting await().atMost(1, SECONDS) .until(() -> bulkheadThread.getState().equals(TIMED_WAITING)); }
assertThat(bulkhead.getBulkheadConfig().getMaxConcurrentCalls()).isEqualTo(3); Thread bulkheadThread = new Thread(() -> { bulkhead.isCallPermitted(); .until(() -> secondChangerThread.getState().equals(TERMINATED)); assertThat(bulkhead.getBulkheadConfig().getMaxConcurrentCalls()).isEqualTo(4); assertThat(bulkhead.getMetrics().getAvailableConcurrentCalls()).isEqualTo(3); // main thread is still holding