org.gradle.api.internalivyservice.resolutionstrategy.DefaultCachePolicy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle-api Show documentation
Show all versions of gradle-api Show documentation
Gradle 6.9.1 API redistribution.
/*
* Copyright 2011 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.api.internal.artifacts.ivyservice.resolutionstrategy;
import org.gradle.api.Action;
import org.gradle.api.artifacts.ArtifactIdentifier;
import org.gradle.api.artifacts.ModuleIdentifier;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
import org.gradle.api.artifacts.ResolvedModuleVersion;
import org.gradle.api.artifacts.component.ModuleComponentIdentifier;
import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier;
import org.gradle.api.internal.artifacts.cache.ArtifactResolutionControl;
import org.gradle.api.internal.artifacts.cache.DependencyResolutionControl;
import org.gradle.api.internal.artifacts.cache.ModuleResolutionControl;
import org.gradle.api.internal.artifacts.cache.ResolutionControl;
import org.gradle.api.internal.artifacts.configurations.MutationValidator;
import org.gradle.api.internal.artifacts.configurations.dynamicversion.CachePolicy;
import org.gradle.api.internal.artifacts.configurations.dynamicversion.Expiry;
import org.gradle.api.internal.artifacts.ivyservice.modulecache.dynamicversions.DefaultResolvedModuleVersion;
import java.io.File;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import static org.gradle.api.internal.artifacts.configurations.MutationValidator.MutationType.STRATEGY;
public class DefaultCachePolicy implements CachePolicy {
private static final int SECONDS_IN_DAY = 24 * 60 * 60;
private static final int MILLISECONDS_IN_DAY = SECONDS_IN_DAY * 1000;
final List> dependencyCacheRules;
final List> moduleCacheRules;
final List> artifactCacheRules;
private MutationValidator mutationValidator = MutationValidator.IGNORE;
private long keepDynamicVersionsFor = MILLISECONDS_IN_DAY;
private long keepChangingModulesFor = MILLISECONDS_IN_DAY;
public DefaultCachePolicy() {
this.dependencyCacheRules = new ArrayList<>();
this.moduleCacheRules = new ArrayList<>();
this.artifactCacheRules = new ArrayList<>();
cacheDynamicVersionsFor(SECONDS_IN_DAY, TimeUnit.SECONDS);
cacheChangingModulesFor(SECONDS_IN_DAY, TimeUnit.SECONDS);
cacheMissingArtifactsFor(SECONDS_IN_DAY, TimeUnit.SECONDS);
}
DefaultCachePolicy(DefaultCachePolicy policy) {
this.dependencyCacheRules = new ArrayList<>(policy.dependencyCacheRules);
this.moduleCacheRules = new ArrayList<>(policy.moduleCacheRules);
this.artifactCacheRules = new ArrayList<>(policy.artifactCacheRules);
}
/**
* Sets the validator to invoke prior to each mutation.
*/
public void setMutationValidator(MutationValidator validator) {
this.mutationValidator = validator;
}
@Override
public void setOffline() {
eachDependency(DependencyResolutionControl::useCachedResult);
eachModule(ModuleResolutionControl::useCachedResult);
eachArtifact(ArtifactResolutionControl::useCachedResult);
}
@Override
public void setRefreshDependencies() {
eachDependency(dependencyResolutionControl -> dependencyResolutionControl.refresh());
eachModule(moduleResolutionControl -> moduleResolutionControl.refresh());
eachArtifact(artifactResolutionControl -> artifactResolutionControl.refresh());
}
public void cacheDynamicVersionsFor(final int value, final TimeUnit unit) {
keepDynamicVersionsFor = unit.toMillis(value);
eachDependency(dependencyResolutionControl -> {
if (!dependencyResolutionControl.getCachedResult().isEmpty()) {
dependencyResolutionControl.cacheFor(value, unit);
}
});
}
public void cacheChangingModulesFor(final int value, final TimeUnit units) {
keepChangingModulesFor = units.toMillis(value);
eachModule(moduleResolutionControl -> {
if (moduleResolutionControl.isChanging()) {
moduleResolutionControl.cacheFor(value, units);
}
});
eachArtifact(artifactResolutionControl -> {
if (artifactResolutionControl.belongsToChangingModule()) {
artifactResolutionControl.cacheFor(value, units);
}
});
}
private void cacheMissingArtifactsFor(final int value, final TimeUnit units) {
eachArtifact(artifactResolutionControl -> {
if (artifactResolutionControl.getCachedResult() == null) {
artifactResolutionControl.cacheFor(value, units);
}
});
}
/**
* Apply a rule to control resolution of dependencies.
*
* @param rule the rule to apply
*/
private void eachDependency(Action rule) {
mutationValidator.validateMutation(STRATEGY);
dependencyCacheRules.add(0, rule);
}
/**
* Apply a rule to control resolution of modules.
*
* @param rule the rule to apply
*/
private void eachModule(Action rule) {
mutationValidator.validateMutation(STRATEGY);
moduleCacheRules.add(0, rule);
}
/**
* Apply a rule to control resolution of artifacts.
*
* @param rule the rule to apply
*/
private void eachArtifact(Action rule) {
mutationValidator.validateMutation(STRATEGY);
artifactCacheRules.add(0, rule);
}
@Override
public Expiry versionListExpiry(ModuleIdentifier moduleIdentifier, Set moduleVersions, Duration age) {
CachedDependencyResolutionControl dependencyResolutionControl = new CachedDependencyResolutionControl(moduleIdentifier, moduleVersions, age.toMillis(), keepDynamicVersionsFor);
for (Action rule : dependencyCacheRules) {
rule.execute(dependencyResolutionControl);
if (dependencyResolutionControl.ruleMatch()) {
break;
}
}
return dependencyResolutionControl;
}
@Override
public Expiry missingModuleExpiry(ModuleComponentIdentifier component, Duration age) {
return mustRefreshModule(component, null, age, false);
}
@Override
public Expiry moduleExpiry(ModuleComponentIdentifier component, ResolvedModuleVersion resolvedModuleVersion, Duration age) {
return mustRefreshModule(component, resolvedModuleVersion, age, false);
}
@Override
public Expiry moduleExpiry(ResolvedModuleVersion resolvedModuleVersion, Duration age, boolean changing) {
return mustRefreshModule(resolvedModuleVersion.getId(), resolvedModuleVersion, age, changing);
}
@Override
public Expiry changingModuleExpiry(ModuleComponentIdentifier component, ResolvedModuleVersion resolvedModuleVersion, Duration age) {
return mustRefreshModule(component, resolvedModuleVersion, age, true);
}
private Expiry mustRefreshModule(ModuleComponentIdentifier component, ResolvedModuleVersion version, Duration age, boolean changingModule) {
return mustRefreshModule(DefaultModuleVersionIdentifier.newId(component.getModuleIdentifier(), component.getVersion()), version, age, changingModule);
}
private CachedModuleResolutionControl mustRefreshModule(ModuleVersionIdentifier moduleVersionId, ResolvedModuleVersion version, Duration age, boolean changingModule) {
CachedModuleResolutionControl moduleResolutionControl = new CachedModuleResolutionControl(moduleVersionId, version, changingModule, age.toMillis(), changingModule ? keepChangingModulesFor: Long.MAX_VALUE);
for (Action rule : moduleCacheRules) {
rule.execute(moduleResolutionControl);
if (moduleResolutionControl.ruleMatch()) {
break;
}
}
return moduleResolutionControl;
}
@Override
public Expiry moduleArtifactsExpiry(ModuleVersionIdentifier moduleVersionId, Set artifacts,
Duration age, boolean belongsToChangingModule, boolean moduleDescriptorInSync) {
CachedModuleResolutionControl resolutionControl = mustRefreshModule(moduleVersionId, new DefaultResolvedModuleVersion(moduleVersionId), age, belongsToChangingModule);
if (belongsToChangingModule && !moduleDescriptorInSync) {
resolutionControl.refresh();
}
return resolutionControl;
}
@Override
public Expiry artifactExpiry(ArtifactIdentifier artifactIdentifier, File cachedArtifactFile, Duration age, boolean belongsToChangingModule, boolean moduleDescriptorInSync) {
CachedArtifactResolutionControl artifactResolutionControl = new CachedArtifactResolutionControl(artifactIdentifier, cachedArtifactFile, age.toMillis(), keepChangingModulesFor, belongsToChangingModule);
for (Action rule : artifactCacheRules) {
rule.execute(artifactResolutionControl);
if (artifactResolutionControl.ruleMatch()) {
break;
}
}
if (belongsToChangingModule && !moduleDescriptorInSync) {
artifactResolutionControl.refresh();
}
return artifactResolutionControl;
}
DefaultCachePolicy copy() {
return new DefaultCachePolicy(this);
}
private abstract static class AbstractResolutionControl implements ResolutionControl, Expiry {
private final A request;
private final B cachedResult;
private final long ageMillis;
private long keepForMillis;
private boolean ruleMatch;
private boolean mustCheck;
private AbstractResolutionControl(A request, B cachedResult, long ageMillis, long keepForMillis) {
this.request = request;
this.cachedResult = cachedResult;
this.ageMillis = correctForClockShift(ageMillis);
this.keepForMillis = keepForMillis;
}
/**
* If the age < 0, then it's probable that we've had a clock shift. In this case, treat the age as 1ms.
*/
private long correctForClockShift(long ageMillis) {
if (ageMillis < 0) {
return 1;
}
return ageMillis;
}
@Override
public A getRequest() {
return request;
}
@Override
public B getCachedResult() {
return cachedResult;
}
@Override
public void cacheFor(int value, TimeUnit units) {
keepForMillis = TimeUnit.MILLISECONDS.convert(value, units);
setMustCheck(ageMillis > keepForMillis);
}
@Override
public void useCachedResult() {
setMustCheck(false);
}
@Override
public void refresh() {
setMustCheck(true);
}
private void setMustCheck(boolean val) {
ruleMatch = true;
mustCheck = val;
}
public boolean ruleMatch() {
return ruleMatch;
}
@Override
public Duration getKeepFor() {
if (mustCheck && ageMillis > 0) {
// Must check and was not cached in this build, so do not keep the value
return Duration.ZERO;
}
if (keepForMillis == Long.MAX_VALUE) {
return Duration.ofMillis(Long.MAX_VALUE);
}
return Duration.ofMillis(Math.max(0, keepForMillis - ageMillis));
}
@Override
public boolean isMustCheck() {
return mustCheck && ageMillis > 0;
}
}
private class CachedDependencyResolutionControl extends AbstractResolutionControl> implements DependencyResolutionControl {
private CachedDependencyResolutionControl(ModuleIdentifier request, Set result, long ageMillis, long keepForMillis) {
super(request, result, ageMillis, keepForMillis);
}
}
private class CachedModuleResolutionControl extends AbstractResolutionControl implements ModuleResolutionControl {
private final boolean changing;
private CachedModuleResolutionControl(ModuleVersionIdentifier moduleVersionId, ResolvedModuleVersion cachedVersion, boolean changing, long ageMillis, long keepForMillis) {
super(moduleVersionId, cachedVersion, ageMillis, keepForMillis);
this.changing = changing;
}
@Override
public boolean isChanging() {
return changing;
}
}
private class CachedArtifactResolutionControl extends AbstractResolutionControl implements ArtifactResolutionControl {
private final boolean belongsToChangingModule;
private CachedArtifactResolutionControl(ArtifactIdentifier artifactIdentifier, File cachedResult, long ageMillis, long keepForMillis, boolean belongsToChangingModule) {
super(artifactIdentifier, cachedResult, ageMillis, keepForMillis);
this.belongsToChangingModule = belongsToChangingModule;
}
@Override
public boolean belongsToChangingModule() {
return belongsToChangingModule;
}
}
}