wip
diff --git a/subprojects/build-cache-http/src/main/java/org/gradle/caching/http/internal/AsyncHttpBuildCacheService.java b/subprojects/build-cache-http/src/main/java/org/gradle/caching/http/internal/AsyncHttpBuildCacheService.java new file mode 100644 index 0000000..ab3e247 --- /dev/null +++ b/subprojects/build-cache-http/src/main/java/org/gradle/caching/http/internal/AsyncHttpBuildCacheService.java
@@ -0,0 +1,49 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.caching.http.internal; + +import org.gradle.caching.AsyncBuildCacheService; +import org.gradle.caching.BuildCacheEntryReader; +import org.gradle.caching.BuildCacheEntryWriter; +import org.gradle.caching.BuildCacheException; +import org.gradle.caching.BuildCacheKey; + +import java.io.IOException; +import java.util.concurrent.CompletableFuture; + +public class AsyncHttpBuildCacheService implements AsyncBuildCacheService { + + @Override + public CompletableFuture<Boolean> contains(BuildCacheKey key) { + return AsyncBuildCacheService.super.contains(key); + } + + @Override + public CompletableFuture<Boolean> loadAsync(BuildCacheKey key, BuildCacheEntryReader reader) throws BuildCacheException { + return null; + } + + @Override + public CompletableFuture<Void> store(BuildCacheKey key, BuildCacheEntryWriter writer) throws BuildCacheException { + return null; + } + + @Override + public void close() throws IOException { + + } +}
diff --git a/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/AsyncNextGenBuildCacheHandler.java b/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/AsyncNextGenBuildCacheHandler.java new file mode 100644 index 0000000..c030e89 --- /dev/null +++ b/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/AsyncNextGenBuildCacheHandler.java
@@ -0,0 +1,39 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.caching.internal.controller; + +import org.gradle.caching.BuildCacheEntryReader; +import org.gradle.caching.BuildCacheEntryWriter; +import org.gradle.caching.BuildCacheException; +import org.gradle.caching.BuildCacheKey; + +import java.io.Closeable; +import java.util.concurrent.CompletableFuture; + +public interface AsyncNextGenBuildCacheHandler extends Closeable { + + boolean canLoad(); + + boolean canStore(); + + CompletableFuture<Boolean> contains(BuildCacheKey key); + + CompletableFuture<Boolean> load(BuildCacheKey key, BuildCacheEntryReader reader) throws BuildCacheException; + + CompletableFuture<Void> store(BuildCacheKey key, BuildCacheEntryWriter writer) throws BuildCacheException; + +}
diff --git a/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/DefaultNextGenBuildCacheAccess.java b/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/DefaultNextGenBuildCacheAccess.java index 71aabbd..188d0ba 100644 --- a/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/DefaultNextGenBuildCacheAccess.java +++ b/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/DefaultNextGenBuildCacheAccess.java
@@ -44,14 +44,14 @@ public class DefaultNextGenBuildCacheAccess implements NextGenBuildCacheAccess { private static final CompletableFuture<?>[] EMPTY_COMPLETABLE_FUTURE_ARRAY = new CompletableFuture<?>[0]; private final NextGenBuildCacheHandler local; - private final NextGenBuildCacheHandler remote; + private final AsyncNextGenBuildCacheHandler remote; private final BufferProvider bufferProvider; private final ManagedThreadPoolExecutor remoteProcessor; private final ConcurrencyCounter counter; public DefaultNextGenBuildCacheAccess( NextGenBuildCacheHandler local, - NextGenBuildCacheHandler remote, + AsyncNextGenBuildCacheHandler remote, BufferProvider bufferProvider, ExecutorFactory executorFactory ) { @@ -66,6 +66,8 @@ public DefaultNextGenBuildCacheAccess( @Override public <T> void load(Map<BuildCacheKey, T> entries, LoadHandler<T> handler) { List<CompletableFuture<Void>> remoteDownloads = new ArrayList<>(); + + entries.forEach((key, payload) -> { boolean foundLocally = local.canLoad() && local.load(key, input -> handler.handle(input, payload)); if (!foundLocally && remote.canLoad()) { @@ -85,6 +87,7 @@ public <T> void store(Map<BuildCacheKey, T> entries, StoreHandler<T> handler) { return; } if (!local.contains(key)) { + //FIXME could be async? local.store(key, handler.handle(payload)); } // TODO Add error handling
diff --git a/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/service/BaseRemoteBuildCacheServiceHandle.java b/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/service/BaseRemoteBuildCacheServiceHandle.java index 2371e37..9abda9d 100644 --- a/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/service/BaseRemoteBuildCacheServiceHandle.java +++ b/subprojects/build-cache/src/main/java/org/gradle/caching/internal/controller/service/BaseRemoteBuildCacheServiceHandle.java
@@ -82,11 +82,11 @@ public final Optional<BuildCacheLoadResult> maybeLoad(BuildCacheKey key, File lo } protected void loadInner(String description, BuildCacheKey key, LoadTarget loadTarget) { - service.load(key, loadTarget); + service.loadAsync(key, loadTarget); } protected void loadInner(BuildCacheKey key, BuildCacheEntryReader entryReader) { - service.load(key, entryReader); + service.loadAsync(key, entryReader); } private Optional<BuildCacheLoadResult> maybeUnpack(LoadTarget loadTarget, Function<File, BuildCacheLoadResult> unpackFunction) {
diff --git a/subprojects/core-api/src/main/java/org/gradle/caching/AsyncBuildCacheService.java b/subprojects/core-api/src/main/java/org/gradle/caching/AsyncBuildCacheService.java new file mode 100644 index 0000000..ff452fc --- /dev/null +++ b/subprojects/core-api/src/main/java/org/gradle/caching/AsyncBuildCacheService.java
@@ -0,0 +1,67 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.caching; + +import org.gradle.api.Incubating; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +public interface AsyncBuildCacheService extends BuildCacheService { // TODO temp fix to reduce the scope of the changes and just downcast where required -> DefaultNextGenBuildCacheAccess + @Incubating + default CompletableFuture<Boolean> containsAsync(BuildCacheKey key) { + return loadAsync(key, __ -> {}); + } + + CompletableFuture<Boolean> loadAsync(BuildCacheKey key, BuildCacheEntryReader reader) throws BuildCacheException; + + CompletableFuture<Void> storeAsync(BuildCacheKey key, BuildCacheEntryWriter writer) throws BuildCacheException; + + + @Override + default boolean contains(BuildCacheKey key) { + try { + return containsAsync(key).get(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } catch (ExecutionException e) { + throw new RuntimeException(e); + } + } + + @Override + default boolean load(BuildCacheKey key, BuildCacheEntryReader reader) throws BuildCacheException { + try { + return loadAsync(key, reader).get(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } catch (ExecutionException e) { + throw new RuntimeException(e); + } + } + + @Override + default void store(BuildCacheKey key, BuildCacheEntryWriter writer) throws BuildCacheException { + try { + storeAsync(key, writer).get(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } catch (ExecutionException e) { + throw new RuntimeException(e); + } + } +}
diff --git a/subprojects/core/src/main/java/org/gradle/caching/internal/services/AbstractBuildCacheControllerFactory.java b/subprojects/core/src/main/java/org/gradle/caching/internal/services/AbstractBuildCacheControllerFactory.java index 336fe52..a197b7b 100644 --- a/subprojects/core/src/main/java/org/gradle/caching/internal/services/AbstractBuildCacheControllerFactory.java +++ b/subprojects/core/src/main/java/org/gradle/caching/internal/services/AbstractBuildCacheControllerFactory.java
@@ -21,6 +21,7 @@ import org.gradle.StartParameter; import org.gradle.api.internal.GeneratedSubclasses; import org.gradle.api.internal.cache.StringInterner; +import org.gradle.caching.AsyncBuildCacheService; import org.gradle.caching.BuildCacheService; import org.gradle.caching.BuildCacheServiceFactory; import org.gradle.caching.configuration.BuildCache; @@ -81,7 +82,7 @@ public AbstractBuildCacheControllerFactory( abstract protected BuildCacheController doCreateController( @Nullable DescribedBuildCacheService<DirectoryBuildCache, L> localDescribedService, - @Nullable DescribedBuildCacheService<BuildCache, BuildCacheService> remoteDescribedService + @Nullable DescribedBuildCacheService<BuildCache, AsyncBuildCacheService> remoteDescribedService ); @Override
diff --git a/subprojects/core/src/main/java/org/gradle/caching/internal/services/LegacyBuildCacheControllerFactory.java b/subprojects/core/src/main/java/org/gradle/caching/internal/services/LegacyBuildCacheControllerFactory.java index 587bd1d..3938af8 100644 --- a/subprojects/core/src/main/java/org/gradle/caching/internal/services/LegacyBuildCacheControllerFactory.java +++ b/subprojects/core/src/main/java/org/gradle/caching/internal/services/LegacyBuildCacheControllerFactory.java
@@ -20,6 +20,7 @@ import org.gradle.api.internal.cache.StringInterner; import org.gradle.api.internal.file.temp.TemporaryFileProvider; import org.gradle.api.logging.configuration.ShowStacktrace; +import org.gradle.caching.AsyncBuildCacheService; import org.gradle.caching.BuildCacheService; import org.gradle.caching.configuration.BuildCache; import org.gradle.caching.internal.controller.BuildCacheController; @@ -62,7 +63,7 @@ public LegacyBuildCacheControllerFactory( @Override protected BuildCacheController doCreateController( @Nullable DescribedBuildCacheService<DirectoryBuildCache, DirectoryBuildCacheService> localDescribedService, - @Nullable DescribedBuildCacheService<BuildCache, BuildCacheService> remoteDescribedService + @Nullable DescribedBuildCacheService<BuildCache, AsyncBuildCacheService> remoteDescribedService ) { BuildCacheServicesConfiguration config = toConfiguration( localDescribedService, @@ -88,7 +89,7 @@ protected BuildCacheController doCreateController( private static BuildCacheServicesConfiguration toConfiguration( @Nullable DescribedBuildCacheService<DirectoryBuildCache, DirectoryBuildCacheService> local, - @Nullable DescribedBuildCacheService<BuildCache, BuildCacheService> remote + @Nullable DescribedBuildCacheService<BuildCache, AsyncBuildCacheService> remote ) { boolean localPush = local != null && local.config.isPush(); boolean remotePush = remote != null && remote.config.isPush();
diff --git a/subprojects/core/src/main/java/org/gradle/caching/internal/services/NextGenBuildCacheControllerFactory.java b/subprojects/core/src/main/java/org/gradle/caching/internal/services/NextGenBuildCacheControllerFactory.java index d62111d..b48bd72 100644 --- a/subprojects/core/src/main/java/org/gradle/caching/internal/services/NextGenBuildCacheControllerFactory.java +++ b/subprojects/core/src/main/java/org/gradle/caching/internal/services/NextGenBuildCacheControllerFactory.java
@@ -18,12 +18,14 @@ import org.gradle.StartParameter; import org.gradle.api.internal.cache.StringInterner; +import org.gradle.caching.AsyncBuildCacheService; import org.gradle.caching.BuildCacheEntryReader; import org.gradle.caching.BuildCacheEntryWriter; import org.gradle.caching.BuildCacheException; import org.gradle.caching.BuildCacheKey; import org.gradle.caching.BuildCacheService; import org.gradle.caching.configuration.BuildCache; +import org.gradle.caching.internal.controller.AsyncNextGenBuildCacheHandler; import org.gradle.caching.internal.controller.BuildCacheController; import org.gradle.caching.internal.controller.DefaultNextGenBuildCacheAccess; import org.gradle.caching.internal.controller.GZipNextGenBuildCacheAccess; @@ -42,6 +44,7 @@ import javax.annotation.Nullable; import java.io.IOException; +import java.util.concurrent.CompletableFuture; public final class NextGenBuildCacheControllerFactory extends AbstractBuildCacheControllerFactory<H2BuildCacheService> { @@ -76,12 +79,12 @@ public NextGenBuildCacheControllerFactory( @Override protected BuildCacheController doCreateController( @Nullable DescribedBuildCacheService<DirectoryBuildCache, H2BuildCacheService> localDescribedService, - @Nullable DescribedBuildCacheService<BuildCache, BuildCacheService> remoteDescribedService + @Nullable DescribedBuildCacheService<BuildCache, AsyncBuildCacheService> remoteDescribedService ) { IncubationLogger.incubatingFeatureUsed("Next generation build cache"); NextGenBuildCacheHandler local = resolveService(localDescribedService); - NextGenBuildCacheHandler remote = resolveService(remoteDescribedService); + AsyncNextGenBuildCacheHandler remote = resolveRemoteService(remoteDescribedService); return new NextGenBuildCacheController( buildInvocationScopeId.getId().asString(), @@ -107,6 +110,12 @@ private static NextGenBuildCacheHandler resolveService(@Nullable DescribedBuildC : DISABLED_BUILD_CACHE_HANDLER; } + private static AsyncNextGenBuildCacheHandler resolveRemoteService(@Nullable DescribedBuildCacheService<? extends BuildCache, ? extends AsyncBuildCacheService> describedService) { + return describedService != null && describedService.config.isEnabled() + ? new AsyncDefaultNextGenBuildCacheHandler(describedService.service, describedService.config.isPush()) + : DISABLED_ASYNC_BUILD_CACHE_HANDLER; + } + private static final NextGenBuildCacheHandler DISABLED_BUILD_CACHE_HANDLER = new NextGenBuildCacheHandler() { @Override public boolean canLoad() { @@ -137,6 +146,81 @@ public void close() { } }; + private static final AsyncNextGenBuildCacheHandler DISABLED_ASYNC_BUILD_CACHE_HANDLER = new AsyncNextGenBuildCacheHandler() { + @Override + public boolean canLoad() { + return false; + } + + @Override + public boolean canStore() { + return false; + } + + @Override + public CompletableFuture<Boolean> contains(BuildCacheKey key) { + return null; + } + + @Override + public CompletableFuture<Boolean> load(BuildCacheKey key, BuildCacheEntryReader reader) throws BuildCacheException { + return null; + } + + @Override + public CompletableFuture<Void> store(BuildCacheKey key, BuildCacheEntryWriter writer) throws BuildCacheException { + return null; + } + + @Override + public void close() throws IOException { + + } + } + + + + private static class AsyncDefaultNextGenBuildCacheHandler implements AsyncNextGenBuildCacheHandler { + private final AsyncBuildCacheService service; + private final boolean pushEnabled; + + public AsyncDefaultNextGenBuildCacheHandler(AsyncBuildCacheService service, boolean pushEnabled) { + this.service = service; + this.pushEnabled = pushEnabled; + } + + @Override + public boolean canLoad() { + return false; + } + + @Override + public boolean canStore() { + return false; + } + + @Override + public CompletableFuture<Boolean> contains(BuildCacheKey key) { + return null; + } + + @Override + public CompletableFuture<Boolean> load(BuildCacheKey key, BuildCacheEntryReader reader) throws BuildCacheException { + return null; + } + + @Override + public CompletableFuture<Void> store(BuildCacheKey key, BuildCacheEntryWriter writer) throws BuildCacheException { + return null; + } + + @Override + public void close() throws IOException { + + } + } + + private static class DefaultNextGenBuildCacheHandler implements NextGenBuildCacheHandler { private final BuildCacheService service; private final boolean pushEnabled; @@ -163,7 +247,7 @@ public boolean contains(BuildCacheKey key) { @Override public boolean load(BuildCacheKey key, BuildCacheEntryReader reader) throws BuildCacheException { - return service.load(key, reader); + return service.loadAsync(key, reader); } @Override