From a091060b2b5f16367ce35b47bb1c3e6e32f29022 Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Wed, 4 Sep 2013 15:06:41 +0200 Subject: [PATCH] SONAR-4602 Evict dryRun cache when changing issues --- .../org/sonar/core/dryrun/DryRunCache.java | 10 ++---- .../server/issue/IssueBulkChangeService.java | 15 +++++++-- .../org/sonar/server/issue/IssueService.java | 32 ++++++++++++------- .../issue/IssueBulkChangeServiceTest.java | 14 ++++++-- .../sonar/server/issue/IssueServiceTest.java | 15 +++++---- 5 files changed, 57 insertions(+), 29 deletions(-) diff --git a/sonar-core/src/main/java/org/sonar/core/dryrun/DryRunCache.java b/sonar-core/src/main/java/org/sonar/core/dryrun/DryRunCache.java index 277e73ba8f7..104234b1f28 100644 --- a/sonar-core/src/main/java/org/sonar/core/dryrun/DryRunCache.java +++ b/sonar-core/src/main/java/org/sonar/core/dryrun/DryRunCache.java @@ -19,9 +19,8 @@ */ package org.sonar.core.dryrun; -import org.sonar.api.ServerExtension; - import org.apache.commons.io.FileUtils; +import org.sonar.api.ServerExtension; import org.sonar.api.platform.ServerFileSystem; import org.sonar.core.properties.PropertiesDao; import org.sonar.core.properties.PropertyDto; @@ -93,11 +92,8 @@ public class DryRunCache implements ServerExtension { propertiesDao.setProperty(new PropertyDto().setKey(SONAR_DRY_RUN_CACHE_LAST_UPDATE_KEY).setValue(String.valueOf(System.nanoTime()))); } - public void reportResourceModification(long projectId) { - // Delete folder where dryRun DB are stored - FileUtils.deleteQuietly(getCacheLocation(projectId)); - - ResourceDto rootProject = resourceDao.getRootProjectByComponentId(projectId); + public void reportResourceModification(String resourceKey) { + ResourceDto rootProject = resourceDao.getRootProjectByComponentKey(resourceKey); propertiesDao.setProperty(new PropertyDto().setKey(SONAR_DRY_RUN_CACHE_LAST_UPDATE_KEY).setResourceId(rootProject.getId()) .setValue(String.valueOf(System.nanoTime()))); } diff --git a/sonar-server/src/main/java/org/sonar/server/issue/IssueBulkChangeService.java b/sonar-server/src/main/java/org/sonar/server/issue/IssueBulkChangeService.java index 7fbbc7efc42..94cbc26300d 100644 --- a/sonar-server/src/main/java/org/sonar/server/issue/IssueBulkChangeService.java +++ b/sonar-server/src/main/java/org/sonar/server/issue/IssueBulkChangeService.java @@ -30,13 +30,16 @@ import org.sonar.api.issue.IssueQueryResult; import org.sonar.api.issue.internal.DefaultIssue; import org.sonar.api.issue.internal.IssueChangeContext; import org.sonar.api.web.UserRole; +import org.sonar.core.dryrun.DryRunCache; import org.sonar.core.issue.IssueNotifications; import org.sonar.core.issue.db.IssueStorage; import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.user.UserSession; import java.util.Date; +import java.util.HashSet; import java.util.List; +import java.util.Set; import static com.google.common.collect.Lists.newArrayList; @@ -47,13 +50,15 @@ public class IssueBulkChangeService { private final DefaultIssueFinder issueFinder; private final IssueStorage issueStorage; private final IssueNotifications issueNotifications; + private final DryRunCache dryRunCache; private final List actions; - public IssueBulkChangeService(DefaultIssueFinder issueFinder, IssueStorage issueStorage, IssueNotifications issueNotifications, List actions) { + public IssueBulkChangeService(DefaultIssueFinder issueFinder, IssueStorage issueStorage, IssueNotifications issueNotifications, List actions, DryRunCache dryRunCache) { this.issueFinder = issueFinder; this.issueStorage = issueStorage; this.issueNotifications = issueNotifications; this.actions = actions; + this.dryRunCache = dryRunCache; } public IssueBulkChangeResult execute(IssueBulkChangeQuery issueBulkChangeQuery, UserSession userSession) { @@ -67,6 +72,7 @@ public class IssueBulkChangeService { List bulkActions = getActionsToApply(issueBulkChangeQuery, issues, userSession); IssueChangeContext issueChangeContext = IssueChangeContext.createUser(new Date(), userSession.login()); + Set concernedProjects = new HashSet(); for (Issue issue : issues) { ActionContext actionContext = new ActionContext(issue, issueChangeContext); for (Action action : bulkActions) { @@ -79,8 +85,13 @@ public class IssueBulkChangeService { } issueStorage.save((DefaultIssue) issue); issueNotifications.sendChanges((DefaultIssue) issue, issueChangeContext, issueQueryResult); + concernedProjects.add(((DefaultIssue) issue).projectKey()); } } + // Purge dryRun cache + for (String projectKey : concernedProjects) { + dryRunCache.reportResourceModification(projectKey); + } LOG.debug("BulkChange execution time : {} ms", System.currentTimeMillis() - start); return result; } @@ -118,7 +129,7 @@ public class IssueBulkChangeService { } }, null); if (action == null) { - throw new BadRequestException("The action : '"+ actionKey + "' is unknown"); + throw new BadRequestException("The action : '" + actionKey + "' is unknown"); } return action; } diff --git a/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java b/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java index c14ff25cf1e..33016fbd782 100644 --- a/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java +++ b/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java @@ -32,6 +32,7 @@ import org.sonar.api.rules.RuleFinder; import org.sonar.api.user.User; import org.sonar.api.user.UserFinder; import org.sonar.api.web.UserRole; +import org.sonar.core.dryrun.DryRunCache; import org.sonar.core.issue.IssueNotifications; import org.sonar.core.issue.IssueUpdater; import org.sonar.core.issue.db.IssueStorage; @@ -44,6 +45,7 @@ import org.sonar.core.user.AuthorizationDao; import org.sonar.server.user.UserSession; import javax.annotation.Nullable; + import java.util.Arrays; import java.util.Collections; import java.util.Date; @@ -64,17 +66,19 @@ public class IssueService implements ServerComponent { private final ResourceDao resourceDao; private final AuthorizationDao authorizationDao; private final UserFinder userFinder; + private final DryRunCache dryRunCache; public IssueService(DefaultIssueFinder finder, - IssueWorkflow workflow, - IssueStorage issueStorage, - IssueUpdater issueUpdater, - IssueNotifications issueNotifications, - ActionPlanService actionPlanService, - RuleFinder ruleFinder, - ResourceDao resourceDao, - AuthorizationDao authorizationDao, - UserFinder userFinder) { + IssueWorkflow workflow, + IssueStorage issueStorage, + IssueUpdater issueUpdater, + IssueNotifications issueNotifications, + ActionPlanService actionPlanService, + RuleFinder ruleFinder, + ResourceDao resourceDao, + AuthorizationDao authorizationDao, + UserFinder userFinder, + DryRunCache dryRunCache) { this.finder = finder; this.workflow = workflow; this.issueStorage = issueStorage; @@ -85,6 +89,7 @@ public class IssueService implements ServerComponent { this.resourceDao = resourceDao; this.authorizationDao = authorizationDao; this.userFinder = userFinder; + this.dryRunCache = dryRunCache; } /** @@ -116,6 +121,7 @@ public class IssueService implements ServerComponent { if (workflow.doTransition(issue, transition, context)) { issueStorage.save(issue); issueNotifications.sendChanges(issue, context, queryResult); + dryRunCache.reportResourceModification(issue.componentKey()); } return issue; } @@ -127,7 +133,7 @@ public class IssueService implements ServerComponent { User user = null; if (!Strings.isNullOrEmpty(assignee)) { user = userFinder.findByLogin(assignee); - if(user == null) { + if (user == null) { throw new IllegalArgumentException("Unknown user: " + assignee); } } @@ -135,6 +141,7 @@ public class IssueService implements ServerComponent { if (issueUpdater.assign(issue, user, context)) { issueStorage.save(issue); issueNotifications.sendChanges(issue, context, queryResult); + dryRunCache.reportResourceModification(issue.componentKey()); } return issue; } @@ -144,7 +151,7 @@ public class IssueService implements ServerComponent { ActionPlan actionPlan = null; if (!Strings.isNullOrEmpty(actionPlanKey)) { actionPlan = actionPlanService.findByKey(actionPlanKey, userSession); - if(actionPlan == null) { + if (actionPlan == null) { throw new IllegalArgumentException("Unknown action plan: " + actionPlanKey); } } @@ -155,6 +162,7 @@ public class IssueService implements ServerComponent { if (issueUpdater.plan(issue, actionPlan, context)) { issueStorage.save(issue); issueNotifications.sendChanges(issue, context, queryResult); + dryRunCache.reportResourceModification(issue.componentKey()); } return issue; } @@ -168,6 +176,7 @@ public class IssueService implements ServerComponent { if (issueUpdater.setManualSeverity(issue, severity, context)) { issueStorage.save(issue); issueNotifications.sendChanges(issue, context, queryResult); + dryRunCache.reportResourceModification(issue.componentKey()); } return issue; } @@ -195,6 +204,7 @@ public class IssueService implements ServerComponent { issue.setCreationDate(now); issue.setUpdateDate(now); issueStorage.save(issue); + dryRunCache.reportResourceModification(issue.componentKey()); return issue; } diff --git a/sonar-server/src/test/java/org/sonar/server/issue/IssueBulkChangeServiceTest.java b/sonar-server/src/test/java/org/sonar/server/issue/IssueBulkChangeServiceTest.java index 7bd22ea1711..331a623bc66 100644 --- a/sonar-server/src/test/java/org/sonar/server/issue/IssueBulkChangeServiceTest.java +++ b/sonar-server/src/test/java/org/sonar/server/issue/IssueBulkChangeServiceTest.java @@ -30,6 +30,7 @@ import org.sonar.api.issue.condition.Condition; import org.sonar.api.issue.internal.DefaultIssue; import org.sonar.api.issue.internal.IssueChangeContext; import org.sonar.api.web.UserRole; +import org.sonar.core.dryrun.DryRunCache; import org.sonar.core.issue.IssueNotifications; import org.sonar.core.issue.db.IssueStorage; import org.sonar.server.exceptions.BadRequestException; @@ -45,8 +46,16 @@ import static com.google.common.collect.Maps.newHashMap; import static org.fest.assertions.Assertions.assertThat; import static org.fest.assertions.Fail.fail; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyListOf; +import static org.mockito.Matchers.anyMap; import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; public class IssueBulkChangeServiceTest { @@ -69,7 +78,7 @@ public class IssueBulkChangeServiceTest { actions = newArrayList(); - service = new IssueBulkChangeService(finder, issueStorage, issueNotifications, actions); + service = new IssueBulkChangeService(finder, issueStorage, issueNotifications, actions, mock(DryRunCache.class)); } @Test @@ -300,7 +309,6 @@ public class IssueBulkChangeServiceTest { verifyZeroInteractions(issueNotifications); } - class MockAction extends Action { private boolean verify; diff --git a/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceTest.java b/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceTest.java index 4132c7a63ce..dbb42117b2e 100644 --- a/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceTest.java +++ b/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceTest.java @@ -35,6 +35,7 @@ import org.sonar.api.rules.RuleFinder; import org.sonar.api.user.User; import org.sonar.api.user.UserFinder; import org.sonar.api.web.UserRole; +import org.sonar.core.dryrun.DryRunCache; import org.sonar.core.issue.DefaultActionPlan; import org.sonar.core.issue.IssueNotifications; import org.sonar.core.issue.IssueUpdater; @@ -59,7 +60,11 @@ import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; public class IssueServiceTest { @@ -90,7 +95,8 @@ public class IssueServiceTest { when(issueQueryResult.issues()).thenReturn(newArrayList((Issue) issue)); when(issueQueryResult.first()).thenReturn(issue); - issueService = new IssueService(finder, workflow, issueStorage, issueUpdater, issueNotifications, actionPlanService, ruleFinder, resourceDao, authorizationDao, userFinder); + issueService = new IssueService(finder, workflow, issueStorage, issueUpdater, issueNotifications, actionPlanService, ruleFinder, resourceDao, authorizationDao, userFinder, + mock(DryRunCache.class)); } @Test @@ -101,7 +107,7 @@ public class IssueServiceTest { @Test public void should_fail_to_load_issue() { - when(issueQueryResult.issues()).thenReturn(Collections.emptyList()); + when(issueQueryResult.issues()).thenReturn(Collections. emptyList()); when(finder.find(any(IssueQuery.class))).thenReturn(issueQueryResult); try { @@ -166,7 +172,6 @@ public class IssueServiceTest { verifyZeroInteractions(issueNotifications); } - @Test public void should_fail_do_transition_if_not_logged() { when(userSession.isLoggedIn()).thenReturn(false); @@ -201,7 +206,6 @@ public class IssueServiceTest { verify(issueNotifications).sendChanges(eq(issue), eq(issueChangeContext), eq(issueQueryResult)); } - @Test public void should_unassign() { when(issueUpdater.assign(eq(issue), eq((User) null), any(IssueChangeContext.class))).thenReturn(true); @@ -439,5 +443,4 @@ public class IssueServiceTest { verifyZeroInteractions(issueStorage); } - } -- 2.39.5