diff options
author | Sébastien Lesaint <sebastien.lesaint@sonarsource.com> | 2019-04-02 10:53:34 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2019-04-23 10:37:54 +0200 |
commit | 8420e1087f18f08d54d94e4f1a46770ca684ff9b (patch) | |
tree | 1c7c6fad4bd7389aad009f28f35fdb28974ab3f5 /server/sonar-db-dao | |
parent | dfae66e01938fda55760991e65397f0d318c38c8 (diff) | |
download | sonarqube-8420e1087f18f08d54d94e4f1a46770ca684ff9b.tar.gz sonarqube-8420e1087f18f08d54d94e4f1a46770ca684ff9b.zip |
SONAR-11753 dont retrieve all subscribers if only interested in subset
Diffstat (limited to 'server/sonar-db-dao')
4 files changed, 162 insertions, 3 deletions
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/property/PropertiesDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/property/PropertiesDao.java index 465c8e4d9e2..bad536ddf3e 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/property/PropertiesDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/property/PropertiesDao.java @@ -25,6 +25,7 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; @@ -40,6 +41,7 @@ import org.sonar.db.MyBatis; import static com.google.common.base.Preconditions.checkArgument; import static org.apache.commons.lang.StringUtils.repeat; import static org.sonar.db.DatabaseUtils.executeLargeInputs; +import static org.sonar.db.DatabaseUtils.executeLargeInputsIntoSet; import static org.sonar.db.DatabaseUtils.executeLargeInputsWithoutOutput; public class PropertiesDao implements Dao { @@ -72,7 +74,22 @@ public class PropertiesDao implements Dao { public Set<EmailSubscriberDto> findEmailSubscribersForNotification(DbSession dbSession, String notificationDispatcherKey, String notificationChannelKey, @Nullable String projectKey) { - return getMapper(dbSession).findEmailRecipientsForNotification(NOTIFICATION_PREFIX + notificationDispatcherKey + "." + notificationChannelKey, projectKey); + return getMapper(dbSession).findEmailRecipientsForNotification(NOTIFICATION_PREFIX + notificationDispatcherKey + "." + notificationChannelKey, projectKey, null); + } + + public Set<EmailSubscriberDto> findEmailSubscribersForNotification(DbSession dbSession, String notificationDispatcherKey, String notificationChannelKey, + @Nullable String projectKey, Set<String> logins) { + if (logins.isEmpty()) { + return Collections.emptySet(); + } + + return executeLargeInputsIntoSet( + logins, + loginsPartition -> { + String notificationKey = NOTIFICATION_PREFIX + notificationDispatcherKey + "." + notificationChannelKey; + return getMapper(dbSession).findEmailRecipientsForNotification(notificationKey, projectKey, loginsPartition); + }, + partitionSize -> projectKey == null ? partitionSize : (partitionSize / 2)); } public boolean hasProjectNotificationSubscribersForDispatchers(String projectUuid, Collection<String> dispatcherKeys) { diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/property/PropertiesMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/property/PropertiesMapper.java index 5009b2e25ee..ccd2bb5f2e0 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/property/PropertiesMapper.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/property/PropertiesMapper.java @@ -29,7 +29,8 @@ public interface PropertiesMapper { Set<Subscriber> findUsersForNotification(@Param("notifKey") String notificationKey, @Nullable @Param("projectKey") String projectKey); - Set<EmailSubscriberDto> findEmailRecipientsForNotification(@Param("notifKey") String notificationKey, @Nullable @Param("projectKey") String projectKey); + Set<EmailSubscriberDto> findEmailRecipientsForNotification(@Param("notifKey") String notificationKey, @Nullable @Param("projectKey") String projectKey, + @Nullable @Param("logins") List<String> logins); List<PropertyDto> selectGlobalProperties(); @@ -52,7 +53,7 @@ public interface PropertiesMapper { List<Long> selectIdsByOrganizationAndUser(@Param("organizationUuid") String organizationUuid, @Param("userId") int userId); List<Long> selectIdsByOrganizationAndMatchingLogin(@Param("organizationUuid") String organizationUuid, @Param("login") String login, - @Param("propertyKeys") List<String> propertyKeys); + @Param("propertyKeys") List<String> propertyKeys); void insertAsEmpty(@Param("key") String key, @Nullable @Param("userId") Integer userId, @Nullable @Param("componentId") Long componentId, @Param("now") long now); diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/property/PropertiesMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/property/PropertiesMapper.xml index bd1f93556d3..4360431ea57 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/property/PropertiesMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/property/PropertiesMapper.xml @@ -46,6 +46,9 @@ and p.resource_id IS NULL WHERE u.email is not null + <if test="logins != null"> + and u.login in <foreach collection="logins" open="(" close=")" item="login" separator=",">#{login,jdbcType=VARCHAR}</foreach> + </if> <if test="projectKey != null"> UNION @@ -65,6 +68,9 @@ and p.resource_id = c.id WHERE u.email is not null + <if test="logins != null"> + and u.login in <foreach collection="logins" open="(" close=")" item="login" separator=",">#{login,jdbcType=VARCHAR}</foreach> + </if> </if> </select> diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/property/PropertiesDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/property/PropertiesDaoTest.java index 4c7d01ac062..b93f129625d 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/property/PropertiesDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/property/PropertiesDaoTest.java @@ -47,6 +47,7 @@ import org.sonar.db.component.ComponentTesting; import org.sonar.db.organization.OrganizationDto; import org.sonar.db.user.UserDto; +import static com.google.common.collect.ImmutableSet.of; import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Sets.newHashSet; import static java.util.Collections.singletonList; @@ -172,6 +173,19 @@ public class PropertiesDaoTest { } @Test + public void findEmailRecipientsForNotification_with_logins_returns_empty_on_empty_properties_table() { + db.users().insertUser(); + String dispatcherKey = randomAlphabetic(5); + String channelKey = randomAlphabetic(6); + String projectKey = randomAlphabetic(7); + Set<String> logins = of("user1", "user2"); + + Set<EmailSubscriberDto> subscribers = underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, projectKey, logins); + + assertThat(subscribers).isEmpty(); + } + + @Test public void findEmailRecipientsForNotification_finds_only_globally_subscribed_users_if_projectKey_is_null() { int userId1 = db.users().insertUser(withEmail("user1")).getId(); int userId2 = db.users().insertUser(withEmail("user2")).getId(); @@ -204,6 +218,47 @@ public class PropertiesDaoTest { } @Test + public void findEmailRecipientsForNotification_with_logins_finds_only_globally_subscribed_specified_users_if_projectKey_is_null() { + int userId1 = db.users().insertUser(withEmail("user1")).getId(); + int userId2 = db.users().insertUser(withEmail("user2")).getId(); + int userId3 = db.users().insertUser(withEmail("user3")).getId(); + int userId4 = db.users().insertUser(withEmail("user4")).getId(); + long projectId = insertPrivateProject("PROJECT_A").getId(); + String dispatcherKey = randomAlphabetic(5); + String otherDispatcherKey = randomAlphabetic(6); + String channelKey = randomAlphabetic(7); + String otherChannelKey = randomAlphabetic(8); + // user1 subscribed only globally + insertProperty(propertyKeyOf(dispatcherKey, channelKey), "true", null, userId1); + // user2 subscribed on project and globally + insertProperty(propertyKeyOf(dispatcherKey, channelKey), "true", null, userId2); + insertProperty(propertyKeyOf(dispatcherKey, channelKey), "true", projectId, userId2); + // user3 subscribed on project only + insertProperty(propertyKeyOf(dispatcherKey, channelKey), "true", projectId, userId3); + // user4 did not subscribe + insertProperty(propertyKeyOf(dispatcherKey, channelKey), "false", projectId, userId4); + Set<String> allLogins = of("user1", "user2", "user3", "user4"); + + assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, null, allLogins)) + .containsOnly(new EmailSubscriberDto("user1", true, emailOf("user1")), new EmailSubscriberDto("user2", true, emailOf("user2"))); + assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, null, of("user1", "user2"))) + .containsOnly(new EmailSubscriberDto("user1", true, emailOf("user1")), new EmailSubscriberDto("user2", true, emailOf("user2"))); + assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, null, of("user2"))) + .containsOnly(new EmailSubscriberDto("user2", true, emailOf("user2"))); + assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, null, of("user1"))) + .containsOnly(new EmailSubscriberDto("user1", true, emailOf("user1"))); + assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, null, of())) + .isEmpty(); + + assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, otherChannelKey, null, allLogins)) + .isEmpty(); + assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), otherDispatcherKey, channelKey, null, allLogins)) + .isEmpty(); + assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), channelKey, dispatcherKey, null, allLogins)) + .isEmpty(); + } + + @Test public void findEmailRecipientsForNotification_finds_global_and_project_subscribed_users_when_projectKey_is_non_null() { int userId1 = db.users().insertUser(withEmail("user1")).getId(); int userId2 = db.users().insertUser(withEmail("user2")).getId(); @@ -243,6 +298,56 @@ public class PropertiesDaoTest { } @Test + public void findEmailRecipientsForNotification_with_logins_finds_global_and_project_subscribed_specified_users_when_projectKey_is_non_null() { + int userId1 = db.users().insertUser(withEmail("user1")).getId(); + int userId2 = db.users().insertUser(withEmail("user2")).getId(); + int userId3 = db.users().insertUser(withEmail("user3")).getId(); + int userId4 = db.users().insertUser(withEmail("user4")).getId(); + String projectKey = randomAlphabetic(3); + String otherProjectKey = randomAlphabetic(4); + long projectId = insertPrivateProject(projectKey).getId(); + String dispatcherKey = randomAlphabetic(5); + String otherDispatcherKey = randomAlphabetic(6); + String channelKey = randomAlphabetic(7); + String otherChannelKey = randomAlphabetic(8); + // user1 subscribed only globally + insertProperty(propertyKeyOf(dispatcherKey, channelKey), "true", null, userId1); + // user2 subscribed on project and globally + insertProperty(propertyKeyOf(dispatcherKey, channelKey), "true", null, userId2); + insertProperty(propertyKeyOf(dispatcherKey, channelKey), "true", projectId, userId2); + // user3 subscribed on project only + insertProperty(propertyKeyOf(dispatcherKey, channelKey), "true", projectId, userId3); + // user4 did not subscribe + insertProperty(propertyKeyOf(dispatcherKey, channelKey), "false", projectId, userId4); + Set<String> allLogins = of("user1", "user2", "user3", "user4"); + + assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, projectKey, allLogins)) + .containsOnly( + new EmailSubscriberDto("user1", true, emailOf("user1")), + new EmailSubscriberDto("user2", true, emailOf("user2")), new EmailSubscriberDto("user2", false, "user2@foo"), + new EmailSubscriberDto("user3", false, emailOf("user3"))); + assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, projectKey, of("user1"))) + .containsOnly( + new EmailSubscriberDto("user1", true, emailOf("user1"))); + assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, projectKey, of("user2"))) + .containsOnly( + new EmailSubscriberDto("user2", true, emailOf("user2")), new EmailSubscriberDto("user2", false, "user2@foo")); + assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, projectKey, of("user3"))) + .containsOnly(new EmailSubscriberDto("user3", false, emailOf("user3"))); + assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, projectKey, of())) + .isEmpty(); + + assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, otherProjectKey, allLogins)) + .containsOnly( + new EmailSubscriberDto("user1", true, emailOf("user1")), + new EmailSubscriberDto("user2", true, emailOf("user2"))); + assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, otherChannelKey, otherProjectKey, allLogins)) + .isEmpty(); + assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), otherDispatcherKey, channelKey, otherProjectKey, allLogins)) + .isEmpty(); + } + + @Test public void findEmailRecipientsForNotification_ignores_subscribed_users_without_email() { int userId1 = db.users().insertUser(withEmail("user1")).getId(); int userId2 = db.users().insertUser(noEmail("user2")).getId(); @@ -272,6 +377,36 @@ public class PropertiesDaoTest { } @Test + public void findEmailRecipientsForNotification_with_logins_ignores_subscribed_users_without_email() { + int userId1 = db.users().insertUser(withEmail("user1")).getId(); + int userId2 = db.users().insertUser(noEmail("user2")).getId(); + int userId3 = db.users().insertUser(withEmail("user3")).getId(); + int userId4 = db.users().insertUser(noEmail("user4")).getId(); + Set<String> allLogins = of("user1", "user2", "user3"); + String projectKey = randomAlphabetic(3); + long projectId = insertPrivateProject(projectKey).getId(); + String dispatcherKey = randomAlphabetic(4); + String channelKey = randomAlphabetic(5); + // user1 and user2 subscribed on project and globally + insertProperty(propertyKeyOf(dispatcherKey, channelKey), "true", null, userId1); + insertProperty(propertyKeyOf(dispatcherKey, channelKey), "true", projectId, userId1); + insertProperty(propertyKeyOf(dispatcherKey, channelKey), "true", null, userId2); + insertProperty(propertyKeyOf(dispatcherKey, channelKey), "true", projectId, userId2); + // user3 and user4 subscribed only globally + insertProperty(propertyKeyOf(dispatcherKey, channelKey), "true", null, userId3); + insertProperty(propertyKeyOf(dispatcherKey, channelKey), "true", null, userId4); + + assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, projectKey, allLogins)) + .containsOnly( + new EmailSubscriberDto("user1", true, emailOf("user1")), new EmailSubscriberDto("user1", false, emailOf("user1")), + new EmailSubscriberDto("user3", true, emailOf("user3"))); + assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, null, allLogins)) + .containsOnly( + new EmailSubscriberDto("user1", true, emailOf("user1")), + new EmailSubscriberDto("user3", true, emailOf("user3"))); + } + + @Test public void selectGlobalProperties() { // global long id1 = insertProperty("global.one", "one", null, null); |