Skip to content

Commit fe3f779

Browse files
committed
Cache delegate recipes per recipe instance to avoid repeated construction
The Gradle/Maven dependency wrapper recipes (`AddDependency`, `ChangeDependency`, `UpgradeDependencyVersion`, `UpgradeTransitiveDependencyVersion`) each delegate to a Gradle and a Maven `ScanningRecipe`. Previously a fresh delegate instance was constructed on every `getInitialValue`/`getScanner`/`getVisitor`/`validate` call (and, in `AddDependency`, once per source file inside the scanner's `visit`). Each `ScanningRecipe` construction runs `UUID.randomUUID()` for its accumulator-message key, which draws from `SecureRandom` and dominated profiles of recipe-heavy runs. Memoize each delegate lazily on the wrapper recipe instance (a `final transient AtomicReference` that is excluded from the generated constructor and from `equals`/`hashCode`) so it is built at most once per wrapper instance and reused across the scanning and editing phases. The delegate is derived from the wrapper's options, so it belongs to the recipe instance rather than the accumulator: callers such as `rewrite-spring` deliberately reuse a single accumulator across two wrapper instances that have different options, so caching the delegate on the accumulator would reuse the wrong options. The `Accumulator` types are left unchanged, preserving their public constructors for downstream callers that build them directly.
1 parent 567f4e5 commit fe3f779

4 files changed

Lines changed: 102 additions & 22 deletions

File tree

src/main/java/org/openrewrite/java/dependencies/AddDependency.java

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,16 @@
1515
*/
1616
package org.openrewrite.java.dependencies;
1717

18+
import lombok.AccessLevel;
1819
import lombok.EqualsAndHashCode;
20+
import lombok.Getter;
1921
import lombok.Value;
2022
import org.jspecify.annotations.Nullable;
2123
import org.openrewrite.*;
2224
import org.openrewrite.maven.tree.Scope;
2325

26+
import java.util.concurrent.atomic.AtomicReference;
27+
2428
@EqualsAndHashCode(callSuper = false)
2529
@Value
2630
public class AddDependency extends ScanningRecipe<AddDependency.Accumulator> {
@@ -141,10 +145,13 @@ public Accumulator getInitialValue(ExecutionContext ctx) {
141145
@Override
142146
public TreeVisitor<?, ExecutionContext> getScanner(Accumulator acc) {
143147
return new TreeVisitor<Tree, ExecutionContext>() {
148+
final TreeVisitor<?, ExecutionContext> gradleAddDep = gradleAddDep().getScanner(acc.gradleAccumulator);
149+
final TreeVisitor<?, ExecutionContext> mavenAddDep = mavenAddDep().getScanner(acc.mavenAccumulator);
150+
144151
@Override
145152
public @Nullable Tree visit(@Nullable Tree tree, ExecutionContext ctx) {
146-
gradleAddDep().getScanner(acc.gradleAccumulator).visit(tree, ctx);
147-
mavenAddDep().getScanner(acc.mavenAccumulator).visit(tree, ctx);
153+
gradleAddDep.visit(tree, ctx);
154+
mavenAddDep.visit(tree, ctx);
148155
return tree;
149156
}
150157
};
@@ -184,20 +191,36 @@ public static class Accumulator {
184191
org.openrewrite.maven.AddDependency.Scanned mavenAccumulator;
185192
}
186193

194+
@Getter(AccessLevel.NONE)
195+
private final transient AtomicReference<org.openrewrite.gradle.AddDependency> gradleDelegate = new AtomicReference<>();
196+
197+
@Getter(AccessLevel.NONE)
198+
private final transient AtomicReference<org.openrewrite.maven.AddDependency> mavenDelegate = new AtomicReference<>();
199+
187200
private org.openrewrite.gradle.AddDependency gradleAddDep() {
188-
String configurationName = null;
189-
if(configuration != null) {
190-
configurationName = configuration;
191-
} else if(scope != null) {
192-
configurationName = Scope.asGradleConfigurationName(Scope.fromName(scope));
201+
org.openrewrite.gradle.AddDependency recipe = gradleDelegate.get();
202+
if (recipe == null) {
203+
String configurationName = null;
204+
if(configuration != null) {
205+
configurationName = configuration;
206+
} else if(scope != null) {
207+
configurationName = Scope.asGradleConfigurationName(Scope.fromName(scope));
208+
}
209+
recipe = new org.openrewrite.gradle.AddDependency(groupId, artifactId, version, versionPattern,
210+
configurationName, onlyIfUsing, classifier, extension, familyPattern, acceptTransitive);
211+
gradleDelegate.set(recipe);
193212
}
194-
return new org.openrewrite.gradle.AddDependency(groupId, artifactId, version, versionPattern,
195-
configurationName, onlyIfUsing, classifier, extension, familyPattern, acceptTransitive);
213+
return recipe;
196214
}
197215

198216
private org.openrewrite.maven.AddDependency mavenAddDep() {
199-
return new org.openrewrite.maven.AddDependency(groupId, artifactId, version != null ? version : "latest.release",
200-
versionPattern, scope, releasesOnly, onlyIfUsing, type, classifier, optional, familyPattern,
201-
acceptTransitive);
217+
org.openrewrite.maven.AddDependency recipe = mavenDelegate.get();
218+
if (recipe == null) {
219+
recipe = new org.openrewrite.maven.AddDependency(groupId, artifactId, version != null ? version : "latest.release",
220+
versionPattern, scope, releasesOnly, onlyIfUsing, type, classifier, optional, familyPattern,
221+
acceptTransitive);
222+
mavenDelegate.set(recipe);
223+
}
224+
return recipe;
202225
}
203226
}

src/main/java/org/openrewrite/java/dependencies/ChangeDependency.java

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,16 @@
1515
*/
1616
package org.openrewrite.java.dependencies;
1717

18+
import lombok.AccessLevel;
1819
import lombok.Data;
1920
import lombok.EqualsAndHashCode;
2021
import lombok.Getter;
2122
import lombok.RequiredArgsConstructor;
2223
import org.jspecify.annotations.Nullable;
2324
import org.openrewrite.*;
2425

26+
import java.util.concurrent.atomic.AtomicReference;
27+
2528
import static java.util.Objects.requireNonNull;
2629

2730
@EqualsAndHashCode(callSuper = false)
@@ -152,16 +155,32 @@ public boolean isAcceptable(SourceFile sourceFile, ExecutionContext ctx) {
152155
};
153156
}
154157

158+
@Getter(AccessLevel.NONE)
159+
private final transient AtomicReference<org.openrewrite.maven.ChangeDependencyGroupIdAndArtifactId> mavenDelegate = new AtomicReference<>();
160+
161+
@Getter(AccessLevel.NONE)
162+
private final transient AtomicReference<org.openrewrite.gradle.ChangeDependency> gradleDelegate = new AtomicReference<>();
163+
155164
org.openrewrite.maven.ChangeDependencyGroupIdAndArtifactId getMavenChangeDependency() {
156-
return new org.openrewrite.maven.ChangeDependencyGroupIdAndArtifactId(
157-
oldGroupId, oldArtifactId, newGroupId, newArtifactId,
158-
newVersion, versionPattern, overrideManagedVersion, changeManagedDependency);
165+
org.openrewrite.maven.ChangeDependencyGroupIdAndArtifactId recipe = mavenDelegate.get();
166+
if (recipe == null) {
167+
recipe = new org.openrewrite.maven.ChangeDependencyGroupIdAndArtifactId(
168+
oldGroupId, oldArtifactId, newGroupId, newArtifactId,
169+
newVersion, versionPattern, overrideManagedVersion, changeManagedDependency);
170+
mavenDelegate.set(recipe);
171+
}
172+
return recipe;
159173
}
160174

161175
org.openrewrite.gradle.ChangeDependency getGradleChangeDependency() {
162-
return new org.openrewrite.gradle.ChangeDependency(
163-
oldGroupId, oldArtifactId, newGroupId, newArtifactId,
164-
newVersion, versionPattern, overrideManagedVersion, true);
176+
org.openrewrite.gradle.ChangeDependency recipe = gradleDelegate.get();
177+
if (recipe == null) {
178+
recipe = new org.openrewrite.gradle.ChangeDependency(
179+
oldGroupId, oldArtifactId, newGroupId, newArtifactId,
180+
newVersion, versionPattern, overrideManagedVersion, true);
181+
gradleDelegate.set(recipe);
182+
}
183+
return recipe;
165184
}
166185

167186
@Data

src/main/java/org/openrewrite/java/dependencies/UpgradeDependencyVersion.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.openrewrite.java.dependencies;
1717

18+
import lombok.AccessLevel;
1819
import lombok.Data;
1920
import lombok.EqualsAndHashCode;
2021
import lombok.Getter;
@@ -23,6 +24,7 @@
2324
import org.openrewrite.*;
2425

2526
import java.util.List;
27+
import java.util.concurrent.atomic.AtomicReference;
2628

2729
import static java.util.Objects.requireNonNull;
2830

@@ -139,12 +141,28 @@ public boolean isAcceptable(SourceFile sourceFile, ExecutionContext ctx) {
139141
};
140142
}
141143

144+
@Getter(AccessLevel.NONE)
145+
private final transient AtomicReference<org.openrewrite.maven.UpgradeDependencyVersion> mavenDelegate = new AtomicReference<>();
146+
147+
@Getter(AccessLevel.NONE)
148+
private final transient AtomicReference<org.openrewrite.gradle.UpgradeDependencyVersion> gradleDelegate = new AtomicReference<>();
149+
142150
org.openrewrite.maven.UpgradeDependencyVersion getUpgradeMavenDependencyVersion() {
143-
return new org.openrewrite.maven.UpgradeDependencyVersion(groupId, artifactId, newVersion, versionPattern, overrideManagedVersion, retainVersions);
151+
org.openrewrite.maven.UpgradeDependencyVersion recipe = mavenDelegate.get();
152+
if (recipe == null) {
153+
recipe = new org.openrewrite.maven.UpgradeDependencyVersion(groupId, artifactId, newVersion, versionPattern, overrideManagedVersion, retainVersions);
154+
mavenDelegate.set(recipe);
155+
}
156+
return recipe;
144157
}
145158

146159
public org.openrewrite.gradle.UpgradeDependencyVersion getUpgradeGradleDependencyVersion() {
147-
return new org.openrewrite.gradle.UpgradeDependencyVersion(groupId, artifactId, newVersion, versionPattern);
160+
org.openrewrite.gradle.UpgradeDependencyVersion recipe = gradleDelegate.get();
161+
if (recipe == null) {
162+
recipe = new org.openrewrite.gradle.UpgradeDependencyVersion(groupId, artifactId, newVersion, versionPattern);
163+
gradleDelegate.set(recipe);
164+
}
165+
return recipe;
148166
}
149167

150168
@Data

src/main/java/org/openrewrite/java/dependencies/UpgradeTransitiveDependencyVersion.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,16 @@
1515
*/
1616
package org.openrewrite.java.dependencies;
1717

18+
import lombok.AccessLevel;
1819
import lombok.EqualsAndHashCode;
20+
import lombok.Getter;
1921
import lombok.Value;
2022
import org.jspecify.annotations.Nullable;
2123
import org.openrewrite.*;
2224
import org.openrewrite.maven.AddManagedDependency;
2325

26+
import java.util.concurrent.atomic.AtomicReference;
27+
2428
@EqualsAndHashCode(callSuper = false)
2529
@Value
2630
public class UpgradeTransitiveDependencyVersion extends ScanningRecipe<UpgradeTransitiveDependencyVersion.Accumulator> {
@@ -154,11 +158,27 @@ public boolean isAcceptable(SourceFile sourceFile, ExecutionContext ctx) {
154158
};
155159
}
156160

161+
@Getter(AccessLevel.NONE)
162+
private final transient AtomicReference<org.openrewrite.gradle.UpgradeTransitiveDependencyVersion> gradleDelegate = new AtomicReference<>();
163+
164+
@Getter(AccessLevel.NONE)
165+
private final transient AtomicReference<org.openrewrite.maven.UpgradeTransitiveDependencyVersion> mavenDelegate = new AtomicReference<>();
166+
157167
private org.openrewrite.gradle.UpgradeTransitiveDependencyVersion getGradleUpgradeTransitive() {
158-
return new org.openrewrite.gradle.UpgradeTransitiveDependencyVersion(groupId, artifactId, version, versionPattern, because, null);
168+
org.openrewrite.gradle.UpgradeTransitiveDependencyVersion recipe = gradleDelegate.get();
169+
if (recipe == null) {
170+
recipe = new org.openrewrite.gradle.UpgradeTransitiveDependencyVersion(groupId, artifactId, version, versionPattern, because, null);
171+
gradleDelegate.set(recipe);
172+
}
173+
return recipe;
159174
}
160175

161176
private org.openrewrite.maven.UpgradeTransitiveDependencyVersion getMavenUpgradeTransitive() {
162-
return new org.openrewrite.maven.UpgradeTransitiveDependencyVersion(groupId, artifactId, version, scope, type, classifier, versionPattern, releasesOnly, onlyIfUsing, addToRootPom, because);
177+
org.openrewrite.maven.UpgradeTransitiveDependencyVersion recipe = mavenDelegate.get();
178+
if (recipe == null) {
179+
recipe = new org.openrewrite.maven.UpgradeTransitiveDependencyVersion(groupId, artifactId, version, scope, type, classifier, versionPattern, releasesOnly, onlyIfUsing, addToRootPom, because);
180+
mavenDelegate.set(recipe);
181+
}
182+
return recipe;
163183
}
164184
}

0 commit comments

Comments
 (0)