diff --git a/src/main/java/run/halo/sitemap/CachedSitemapGetter.java b/src/main/java/run/halo/sitemap/CachedSitemapGetter.java index 295a1a3..bbe95e1 100644 --- a/src/main/java/run/halo/sitemap/CachedSitemapGetter.java +++ b/src/main/java/run/halo/sitemap/CachedSitemapGetter.java @@ -1,39 +1,33 @@ package run.halo.sitemap; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; +import com.github.benmanes.caffeine.cache.AsyncCache; +import com.github.benmanes.caffeine.cache.Caffeine; import java.time.Duration; import lombok.AllArgsConstructor; -import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; -import reactor.core.scheduler.Schedulers; @Component @AllArgsConstructor public class CachedSitemapGetter { - private final Cache cache = CacheBuilder.newBuilder() - .concurrencyLevel(Runtime.getRuntime().availableProcessors()) - .initialCapacity(8) - .maximumSize(8) + private final AsyncCache cache = Caffeine.newBuilder() .expireAfterWrite(Duration.ofSeconds(30)) - .build(); + .maximumSize(8) + .buildAsync(); private final DefaultSitemapEntryLister lister; public Mono get(SitemapGeneratorOptions options) { - return Mono.fromCallable(() -> cache.get(options, () -> lister.list(options) - .collectList() - .map(entries -> { - String xml = new SitemapBuilder() - .buildSitemapXml(entries); - cache.put(options, xml); - return xml; - }) - .defaultIfEmpty(StringUtils.EMPTY) - .block() - )) - .subscribeOn(Schedulers.boundedElastic()); + String key = options.getSiteUrl().toString(); + return Mono.fromFuture(() -> + cache.get(key, (k, executor) -> + lister.list(options) + .collectList() + .map(entries -> new SitemapBuilder().buildSitemapXml(entries)) + .defaultIfEmpty("") + .toFuture() + ) + ); } } diff --git a/src/test/java/run/halo/sitemap/CachedSitemapGetterTest.java b/src/test/java/run/halo/sitemap/CachedSitemapGetterTest.java index d2ba984..eb0a60d 100644 --- a/src/test/java/run/halo/sitemap/CachedSitemapGetterTest.java +++ b/src/test/java/run/halo/sitemap/CachedSitemapGetterTest.java @@ -1,10 +1,12 @@ package run.halo.sitemap; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.net.MalformedURLException; +import java.net.URL; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; @@ -22,33 +24,33 @@ public class CachedSitemapGetterTest { @Mock private DefaultSitemapEntryLister lister; private CachedSitemapGetter getter; + private SitemapGeneratorOptions options; @BeforeEach - void setUp() { + void setUp() throws MalformedURLException { when(lister.list(any())).thenReturn( Flux.just(SitemapEntry.builder().loc("http://localhost:8090/about").build())); getter = new CachedSitemapGetter(lister); + options = SitemapGeneratorOptions.builder() + .siteUrl(new URL("http://localhost:8090")) + .build(); } @Test void get() throws InterruptedException, ExecutionException { - var options = mock(SitemapGeneratorOptions.class); - getter.get(options).block(); - verify(lister).list(options); + verify(lister).list(any()); var executorService = Executors.newCachedThreadPool(); List> futures = IntStream.range(0, 10) - .mapToObj(i -> executorService.submit(() -> { - getter.get(options).block(); - })) + .mapToObj(i -> executorService.submit(() -> getter.get(options).block())) .toList(); for (Future future : futures) { future.get(); } - verify(lister).list(options); + verify(lister, times(1)).list(any()); } }