Skip to content

Commit

Permalink
Flush RecipeRunStats on exception to record stats for failing recip…
Browse files Browse the repository at this point in the history
…es (#4449)
  • Loading branch information
pstreef authored Aug 27, 2024
1 parent b4d3672 commit 32a986d
Showing 1 changed file with 46 additions and 44 deletions.
90 changes: 46 additions & 44 deletions rewrite-core/src/main/java/org/openrewrite/RecipeScheduler.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,58 +60,60 @@ private LargeSourceSet runRecipeCycles(Recipe recipe, LargeSourceSet sourceSet,

LargeSourceSet after = sourceSet;

for (int i = 1; i <= maxCycles; i++) {
if (ctx.getMessage(PANIC) != null) {
break;
}

// this root cursor is shared by all `TreeVisitor` instances used created from `getVisitor` and
// single source applicable tests so that data can be shared at the root (especially for caching
// use cases like sharing a `JavaTypeCache` between `JavaTemplate` parsers).
Cursor rootCursor = new Cursor(null, Cursor.ROOT_VALUE);
try {
RecipeRunCycle<LargeSourceSet> cycle = new RecipeRunCycle<>(recipe, i, rootCursor, ctxWithWatch,
recipeRunStats, sourceFileResults, errorsTable, LargeSourceSet::edit);
ctxWithWatch.putCycle(cycle);
after.beforeCycle(i == maxCycles);

// pre-transformation scanning phase where there can only be modifications to capture exceptions
// occurring during the scanning phase
if (hasScanningRecipe(recipe)) {
after = cycle.scanSources(after);
try {
for (int i = 1; i <= maxCycles; i++) {
if (ctx.getMessage(PANIC) != null) {
break;
}

// transformation phases
after = cycle.generateSources(after);
after = cycle.editSources(after);
// this root cursor is shared by all `TreeVisitor` instances used created from `getVisitor` and
// single source applicable tests so that data can be shared at the root (especially for caching
// use cases like sharing a `JavaTypeCache` between `JavaTemplate` parsers).
Cursor rootCursor = new Cursor(null, Cursor.ROOT_VALUE);
try {
RecipeRunCycle<LargeSourceSet> cycle = new RecipeRunCycle<>(recipe, i, rootCursor, ctxWithWatch,
recipeRunStats, sourceFileResults, errorsTable, LargeSourceSet::edit);
ctxWithWatch.putCycle(cycle);
after.beforeCycle(i == maxCycles);

// pre-transformation scanning phase where there can only be modifications to capture exceptions
// occurring during the scanning phase
if (hasScanningRecipe(recipe)) {
after = cycle.scanSources(after);
}

// transformation phases
after = cycle.generateSources(after);
after = cycle.editSources(after);

boolean anyRecipeCausingAnotherCycle = false;
for (Recipe madeChanges : cycle.getMadeChangesInThisCycle()) {
if (madeChanges.causesAnotherCycle()) {
anyRecipeCausingAnotherCycle = true;
boolean anyRecipeCausingAnotherCycle = false;
for (Recipe madeChanges : cycle.getMadeChangesInThisCycle()) {
if (madeChanges.causesAnotherCycle()) {
anyRecipeCausingAnotherCycle = true;
}
}
}

if (i >= minCycles &&
(cycle.getMadeChangesInThisCycle().isEmpty() || !anyRecipeCausingAnotherCycle)) {
after.afterCycle(true);
break;
}
if (i >= minCycles &&
(cycle.getMadeChangesInThisCycle().isEmpty() || !anyRecipeCausingAnotherCycle)) {
after.afterCycle(true);
break;
}

after.afterCycle(i == maxCycles);
ctxWithWatch.resetHasNewMessages();
} finally {
// Clear any messages that were added to the root cursor during the cycle. This is important
// to avoid leaking memory in the case when a recipe defines a static TreeVisitor. That
// TreeVisitor will still contain a reference to this rootCursor and any messages in it
// after recipe execution completes. The pattern of holding a static TreeVisitor isn't
// recommended, but isn't possible for us to guard against at an API level, and so we are
// defensive about memory consumption here.
rootCursor.clearMessages();
after.afterCycle(i == maxCycles);
ctxWithWatch.resetHasNewMessages();
} finally {
// Clear any messages that were added to the root cursor during the cycle. This is important
// to avoid leaking memory in the case when a recipe defines a static TreeVisitor. That
// TreeVisitor will still contain a reference to this rootCursor and any messages in it
// after recipe execution completes. The pattern of holding a static TreeVisitor isn't
// recommended, but isn't possible for us to guard against at an API level, and so we are
// defensive about memory consumption here.
rootCursor.clearMessages();
}
}
} finally {
recipeRunStats.flush(ctx);
}

recipeRunStats.flush(ctx);
return after;
}

Expand Down

0 comments on commit 32a986d

Please sign in to comment.