Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flush/record RecipeRunStats on exception to record stats on Timeout (and other failures) #4449

Merged
merged 1 commit into from
Aug 27, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading