Browse Source

SONAR-13221 replace auto-incremented ID by UUID for notifications

tags/8.4.0.35506
Pierre 4 years ago
parent
commit
4de7a25dc4
29 changed files with 831 additions and 46 deletions
  1. 10
    2
      server/sonar-db-dao/src/main/java/org/sonar/db/notification/NotificationQueueDao.java
  2. 15
    5
      server/sonar-db-dao/src/main/java/org/sonar/db/notification/NotificationQueueDto.java
  3. 1
    1
      server/sonar-db-dao/src/main/java/org/sonar/db/notification/NotificationQueueMapper.java
  4. 10
    10
      server/sonar-db-dao/src/main/resources/org/sonar/db/notification/NotificationQueueMapper.xml
  5. 4
    3
      server/sonar-db-dao/src/schema/schema-sq.ddl
  6. 27
    18
      server/sonar-db-dao/src/test/java/org/sonar/db/notification/NotificationQueueDaoTest.java
  7. 15
    1
      server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/DbVersion83.java
  8. 38
    0
      server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/notifications/AddPrimaryKeyOnUuidColumnOfNotificationTable.java
  9. 58
    0
      server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/notifications/AddUuidAndCreatedAtColumnsToNotification.java
  10. 37
    0
      server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/notifications/DropIdColumnOfNotificationTable.java
  11. 41
    0
      server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/notifications/DropPrimaryKeyOnIdColumnOfNotificationTable.java
  12. 59
    0
      server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/notifications/MakeNotificationUuidAndCreatedAtColumnsNotNullable.java
  13. 60
    0
      server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/notifications/PopulateNotificationUuidAndCreatedAt.java
  14. 6
    0
      server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/DbVersionTestUtils.java
  15. 2
    2
      server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/DbVersion83Test.java
  16. 51
    0
      server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/notifications/AddPrimaryKeyOnUuidColumnOfNotificationTableTest.java
  17. 83
    0
      server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/notifications/AddUuidAndCreatedAtColumnsToNotificationTest.java
  18. 51
    0
      server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/notifications/DropIdColumnOfNotificationTableTest.java
  19. 56
    0
      server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/notifications/DropPrimaryKeyOnIdColumnOfNotificationTableTest.java
  20. 45
    0
      server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/notifications/MakeNotificationUuidAndCreatedAtColumnsNotNullableTest.java
  21. 110
    0
      server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/notifications/PopulateNotificationUuidAndCreatedAtTest.java
  22. 6
    0
      server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/notifications/AddPrimaryKeyOnUuidColumnOfNotificationTableTest/schema.sql
  23. 5
    0
      server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/notifications/AddUuidAndCreatedAtColumnsToNotificationTest/schema.sql
  24. 7
    0
      server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/notifications/DropIdColumnOfNotificationTableTest/schema.sql
  25. 7
    0
      server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/notifications/DropPrimaryKeyOnIdColumnOfNotificationTableTest/schema.sql
  26. 7
    0
      server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/notifications/MakeNotificationUuidAndCreatedAtColumnsNotNullableTest/schema.sql
  27. 7
    0
      server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/notifications/PopulateNotificationUuidAndCreatedAtTest/schema.sql
  28. 4
    2
      server/sonar-server-common/src/main/java/org/sonar/server/notification/DefaultNotificationManager.java
  29. 9
    2
      server/sonar-server-common/src/test/java/org/sonar/server/notification/DefaultNotificationManagerTest.java

+ 10
- 2
server/sonar-db-dao/src/main/java/org/sonar/db/notification/NotificationQueueDao.java View File

@@ -21,6 +21,8 @@ package org.sonar.db.notification;

import java.util.Collections;
import java.util.List;
import org.sonar.api.utils.System2;
import org.sonar.core.util.UuidFactory;
import org.sonar.db.Dao;
import org.sonar.db.DbSession;
import org.sonar.db.MyBatis;
@@ -28,15 +30,21 @@ import org.sonar.db.MyBatis;
public class NotificationQueueDao implements Dao {

private final MyBatis mybatis;
private System2 system2;
private UuidFactory uuidFactory;

public NotificationQueueDao(MyBatis mybatis) {
public NotificationQueueDao(MyBatis mybatis, System2 system2, UuidFactory uuidFactory) {
this.mybatis = mybatis;
this.system2 = system2;
this.uuidFactory = uuidFactory;
}

public void insert(List<NotificationQueueDto> dtos) {
try (DbSession session = mybatis.openSession(true)) {
NotificationQueueMapper mapper = session.getMapper(NotificationQueueMapper.class);
for (NotificationQueueDto dto : dtos) {
dto.setUuid(uuidFactory.create());
dto.setCreatedAt(system2.now());
mapper.insert(dto);
}
session.commit();
@@ -47,7 +55,7 @@ public class NotificationQueueDao implements Dao {
try (DbSession session = mybatis.openSession(true)) {
NotificationQueueMapper mapper = session.getMapper(NotificationQueueMapper.class);
for (NotificationQueueDto dto : dtos) {
mapper.delete(dto.getId());
mapper.delete(dto.getUuid());
}
session.commit();
}

+ 15
- 5
server/sonar-db-dao/src/main/java/org/sonar/db/notification/NotificationQueueDto.java View File

@@ -35,15 +35,16 @@ import org.sonar.api.utils.SonarException;
*/
public class NotificationQueueDto {

private Long id;
private String uuid;
private byte[] data;
private long createdAt;

public Long getId() {
return id;
public String getUuid() {
return uuid;
}

public NotificationQueueDto setId(Long id) {
this.id = id;
NotificationQueueDto setUuid(String uuid) {
this.uuid = uuid;
return this;
}

@@ -56,6 +57,15 @@ public class NotificationQueueDto {
return this;
}

public long getCreatedAt() {
return createdAt;
}

NotificationQueueDto setCreatedAt(long createdAt) {
this.createdAt = createdAt;
return this;
}

@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);

+ 1
- 1
server/sonar-db-dao/src/main/java/org/sonar/db/notification/NotificationQueueMapper.java View File

@@ -28,7 +28,7 @@ public interface NotificationQueueMapper {

void insert(NotificationQueueDto actionPlanDto);

void delete(long id);
void delete(String uuid);

List<NotificationQueueDto> findOldest(int count);


+ 10
- 10
server/sonar-db-dao/src/main/resources/org/sonar/db/notification/NotificationQueueMapper.xml View File

@@ -5,12 +5,12 @@
<mapper namespace="org.sonar.db.notification.NotificationQueueMapper">

<insert id="insert" parameterType="NotificationQueue" useGeneratedKeys="false">
INSERT INTO notifications (data)
VALUES (#{data})
INSERT INTO notifications (uuid,data,created_at)
VALUES (#{uuid},#{data},#{createdAt})
</insert>

<delete id="delete" parameterType="long">
delete from notifications where id=#{id}
<delete id="delete" parameterType="String">
delete from notifications where uuid=#{uuid}
</delete>

<select id="count" resultType="long">
@@ -18,25 +18,25 @@
</select>

<select id="findOldest" parameterType="int" resultType="NotificationQueue">
select id, data
select uuid, data, created_at
from notifications
order by id asc
order by created_at asc
limit #{count}
</select>

<!-- SQL Server -->
<select id="findOldest" parameterType="int" resultType="NotificationQueue" databaseId="mssql">
select top (#{count}) id, data
select top (#{count}) uuid, data, created_at
from notifications
order by id asc
order by created_at asc
</select>

<!-- Oracle -->
<select id="findOldest" parameterType="int" resultType="NotificationQueue" databaseId="oracle">
select * from (select
id, data
uuid, data, created_at
from notifications
order by id asc
order by created_at asc
)
where rownum &lt;= #{count}
</select>

+ 4
- 3
server/sonar-db-dao/src/schema/schema-sq.ddl View File

@@ -483,10 +483,11 @@ ALTER TABLE "NEW_CODE_PERIODS" ADD CONSTRAINT "PK_NEW_CODE_PERIODS" PRIMARY KEY(
CREATE UNIQUE INDEX "UNIQ_NEW_CODE_PERIODS" ON "NEW_CODE_PERIODS"("PROJECT_UUID", "BRANCH_UUID");

CREATE TABLE "NOTIFICATIONS"(
"ID" INTEGER NOT NULL AUTO_INCREMENT (1,1),
"DATA" BLOB
"DATA" BLOB,
"UUID" VARCHAR(40) NOT NULL,
"CREATED_AT" BIGINT NOT NULL
);
ALTER TABLE "NOTIFICATIONS" ADD CONSTRAINT "PK_NOTIFICATIONS" PRIMARY KEY("ID");
ALTER TABLE "NOTIFICATIONS" ADD CONSTRAINT "PK_NOTIFICATIONS" PRIMARY KEY("UUID");

CREATE TABLE "ORG_QPROFILES"(
"UUID" VARCHAR(255) NOT NULL,

+ 27
- 18
server/sonar-db-dao/src/test/java/org/sonar/db/notification/NotificationQueueDaoTest.java View File

@@ -21,22 +21,27 @@ package org.sonar.db.notification;

import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.stream.IntStream;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.sonar.api.notifications.Notification;
import org.sonar.api.utils.System2;
import org.sonar.db.DbTester;

import static java.util.stream.Collectors.toList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.sonar.db.notification.NotificationQueueDto.toNotificationQueueDto;

public class NotificationQueueDaoTest {

private final System2 system2 = mock(System2.class);

@Rule
public DbTester db = DbTester.create(System2.INSTANCE);
public DbTester db = DbTester.create(system2);

private NotificationQueueDao dao = db.getDbClient().notificationQueueDao();

@@ -63,41 +68,45 @@ public class NotificationQueueDaoTest {

@Test
public void should_delete_notification() {
List<NotificationQueueDto> notifs = IntStream.range(0, 30 + new Random().nextInt(20))
List<NotificationQueueDto> notifs = IntStream.range(0, 30)
.mapToObj(i -> toNotificationQueueDto(new Notification("foo_" + i)))
.collect(toList());
dao.insert(notifs);
db.commit();

List<Long> ids = selectAllIds();
List<String> uuids = selectAllUuid();

dao.delete(ids.stream().limit(10).map(id -> new NotificationQueueDto().setId(id)).collect(toList()));
dao.delete(uuids.stream().limit(10).map(uuid -> new NotificationQueueDto().setUuid(uuid)).collect(toList()));

assertThat(selectAllIds()).containsOnly(ids.stream().skip(10).toArray(Long[]::new));
assertThat(selectAllUuid()).containsOnly(uuids.stream().skip(10).toArray(String[]::new));
}

@Test
public void should_findOldest() {
List<NotificationQueueDto> notifs = IntStream.range(0, 20)
when(system2.now()).thenAnswer(new Answer<Long>() {
private long counter;

@Override
public Long answer(InvocationOnMock invocationOnMock) {
counter++;
return counter;
}
});

List<NotificationQueueDto> notifs = IntStream.range(0, 5)
.mapToObj(i -> toNotificationQueueDto(new Notification("foo_" + i)))
.collect(toList());
dao.insert(notifs);
db.commit();

List<Long> ids = selectAllIds();

assertThat(dao.selectOldest(3))
.extracting(NotificationQueueDto::getId)
.containsOnly(ids.stream().limit(3).toArray(Long[]::new));

assertThat(dao.selectOldest(22))
.extracting(NotificationQueueDto::getId)
.containsOnly(ids.toArray(new Long[0]));
.extracting(NotificationQueueDto::getUuid)
.containsExactlyElementsOf(Arrays.asList("1", "2", "3"));
}

private List<Long> selectAllIds() {
return db.select("select id as \"ID\" from notifications").stream()
.map(t -> (Long) t.get("ID"))
private List<String> selectAllUuid() {
return db.select("select uuid as \"UUID\" from notifications order by created_at asc").stream()
.map(t -> (String) t.get("UUID"))
.collect(toList());
}
}

+ 15
- 1
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/DbVersion83.java View File

@@ -21,6 +21,12 @@ package org.sonar.server.platform.db.migration.version.v83;

import org.sonar.server.platform.db.migration.step.MigrationStepRegistry;
import org.sonar.server.platform.db.migration.version.DbVersion;
import org.sonar.server.platform.db.migration.version.v83.notifications.AddPrimaryKeyOnUuidColumnOfNotificationTable;
import org.sonar.server.platform.db.migration.version.v83.notifications.AddUuidAndCreatedAtColumnsToNotification;
import org.sonar.server.platform.db.migration.version.v83.notifications.DropIdColumnOfNotificationTable;
import org.sonar.server.platform.db.migration.version.v83.notifications.DropPrimaryKeyOnIdColumnOfNotificationTable;
import org.sonar.server.platform.db.migration.version.v83.notifications.MakeNotificationUuidAndCreatedAtColumnsNotNullable;
import org.sonar.server.platform.db.migration.version.v83.notifications.PopulateNotificationUuidAndCreatedAt;

public class DbVersion83 implements DbVersion {
@Override
@@ -42,7 +48,15 @@ public class DbVersion83 implements DbVersion {
// Migration on EVENTS table
.add(3400, "Drop primary key on 'ID' column of 'EVENTS' table", DropPrimaryKeyOnIdColumnOfEventsTable.class)
.add(3401, "Add primary key on 'UUID' column of 'EVENTS' table", AddPrimaryKeyOnUuidColumnOfEventsTable.class)
.add(3402, "Drop column 'ID' of 'EVENTS' table", DropIdColumnOfEventsTable.class);
.add(3402, "Drop column 'ID' of 'EVENTS' table", DropIdColumnOfEventsTable.class)

// Migrations of NOTIFICATIONS table
.add(3403, "Add 'uuid' and 'createdAt' columns for notifications", AddUuidAndCreatedAtColumnsToNotification.class)
.add(3404, "Populate 'uuid' and 'createdAt columns for notifications", PopulateNotificationUuidAndCreatedAt.class)
.add(3405, "Make 'uuid' and 'createdAt' column not nullable for notifications", MakeNotificationUuidAndCreatedAtColumnsNotNullable.class)
.add(3406, "Drop primary key on 'ID' column of 'NOTIFICATIONS' table", DropPrimaryKeyOnIdColumnOfNotificationTable.class)
.add(3407, "Add primary key on 'UUID' column of 'NOTIFICATIONS' table", AddPrimaryKeyOnUuidColumnOfNotificationTable.class)
.add(3408, "Drop column 'ID' of 'NOTIFICATIONS' table", DropIdColumnOfNotificationTable.class)

;
}

+ 38
- 0
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/notifications/AddPrimaryKeyOnUuidColumnOfNotificationTable.java View File

@@ -0,0 +1,38 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.platform.db.migration.version.v83.notifications;

import java.sql.SQLException;
import org.sonar.db.Database;
import org.sonar.server.platform.db.migration.step.DdlChange;
import org.sonar.server.platform.db.migration.version.v83.util.AddPrimaryKeyBuilder;

public class AddPrimaryKeyOnUuidColumnOfNotificationTable extends DdlChange {

public AddPrimaryKeyOnUuidColumnOfNotificationTable(Database db) {
super(db);
}

@Override
public void execute(Context context) throws SQLException {
context.execute(new AddPrimaryKeyBuilder("notifications", "uuid").build());
}

}

+ 58
- 0
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/notifications/AddUuidAndCreatedAtColumnsToNotification.java View File

@@ -0,0 +1,58 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.platform.db.migration.version.v83.notifications;

import java.sql.SQLException;
import org.sonar.db.Database;
import org.sonar.server.platform.db.migration.def.BigIntegerColumnDef;
import org.sonar.server.platform.db.migration.def.VarcharColumnDef;
import org.sonar.server.platform.db.migration.sql.AddColumnsBuilder;
import org.sonar.server.platform.db.migration.step.DdlChange;

import static org.sonar.server.platform.db.migration.def.BigIntegerColumnDef.newBigIntegerColumnDefBuilder;
import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder;

public class AddUuidAndCreatedAtColumnsToNotification extends DdlChange {
private static final String TABLE = "notifications";

private static final VarcharColumnDef uuidColumnDefinition = newVarcharColumnDefBuilder()
.setColumnName("uuid")
.setIsNullable(true)
.setDefaultValue(null)
.setLimit(VarcharColumnDef.UUID_SIZE)
.build();

private static final BigIntegerColumnDef createdAtColumnDefinition = newBigIntegerColumnDefBuilder()
.setColumnName("created_at")
.setIsNullable(true)
.build();

public AddUuidAndCreatedAtColumnsToNotification(Database db) {
super(db);
}

@Override
public void execute(Context context) throws SQLException {
context.execute(new AddColumnsBuilder(getDialect(), TABLE)
.addColumn(uuidColumnDefinition)
.addColumn(createdAtColumnDefinition)
.build());
}
}

+ 37
- 0
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/notifications/DropIdColumnOfNotificationTable.java View File

@@ -0,0 +1,37 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.platform.db.migration.version.v83.notifications;

import java.sql.SQLException;
import org.sonar.db.Database;
import org.sonar.server.platform.db.migration.sql.DropColumnsBuilder;
import org.sonar.server.platform.db.migration.step.DdlChange;

public class DropIdColumnOfNotificationTable extends DdlChange {

public DropIdColumnOfNotificationTable(Database db) {
super(db);
}

@Override
public void execute(Context context) throws SQLException {
context.execute(new DropColumnsBuilder(getDialect(), "notifications", "id").build());
}
}

+ 41
- 0
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/notifications/DropPrimaryKeyOnIdColumnOfNotificationTable.java View File

@@ -0,0 +1,41 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.platform.db.migration.version.v83.notifications;

import java.sql.SQLException;
import org.sonar.db.Database;
import org.sonar.server.platform.db.migration.step.DdlChange;
import org.sonar.server.platform.db.migration.version.v83.util.DropPrimaryKeySqlGenerator;

public class DropPrimaryKeyOnIdColumnOfNotificationTable extends DdlChange {

private final DropPrimaryKeySqlGenerator dropPrimaryKeySqlGenerator;

public DropPrimaryKeyOnIdColumnOfNotificationTable(Database db, DropPrimaryKeySqlGenerator dropPrimaryKeySqlGenerator) {
super(db);
this.dropPrimaryKeySqlGenerator = dropPrimaryKeySqlGenerator;
}

@Override
public void execute(Context context) throws SQLException {
context.execute(dropPrimaryKeySqlGenerator.generate("notifications", "notifications","id"));
}

}

+ 59
- 0
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/notifications/MakeNotificationUuidAndCreatedAtColumnsNotNullable.java View File

@@ -0,0 +1,59 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.platform.db.migration.version.v83.notifications;

import java.sql.SQLException;
import org.sonar.db.Database;
import org.sonar.server.platform.db.migration.def.BigIntegerColumnDef;
import org.sonar.server.platform.db.migration.def.VarcharColumnDef;
import org.sonar.server.platform.db.migration.sql.AlterColumnsBuilder;
import org.sonar.server.platform.db.migration.step.DdlChange;

import static org.sonar.server.platform.db.migration.def.BigIntegerColumnDef.newBigIntegerColumnDefBuilder;
import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder;

public class MakeNotificationUuidAndCreatedAtColumnsNotNullable extends DdlChange {
private static final String TABLE = "notifications";

private static final VarcharColumnDef uuidColumnDefinition = newVarcharColumnDefBuilder()
.setColumnName("uuid")
.setIsNullable(false)
.setDefaultValue(null)
.setLimit(VarcharColumnDef.UUID_SIZE)
.build();

private static final BigIntegerColumnDef createdAtColumnDefinition = newBigIntegerColumnDefBuilder()
.setColumnName("created_at")
.setIsNullable(false)
.build();


public MakeNotificationUuidAndCreatedAtColumnsNotNullable(Database db) {
super(db);
}

@Override
public void execute(Context context) throws SQLException {
context.execute(new AlterColumnsBuilder(getDialect(), TABLE)
.updateColumn(uuidColumnDefinition)
.updateColumn(createdAtColumnDefinition)
.build());
}
}

+ 60
- 0
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/notifications/PopulateNotificationUuidAndCreatedAt.java View File

@@ -0,0 +1,60 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.platform.db.migration.version.v83.notifications;

import java.sql.SQLException;
import java.util.concurrent.atomic.AtomicLong;
import org.sonar.api.utils.System2;
import org.sonar.core.util.UuidFactory;
import org.sonar.db.Database;
import org.sonar.server.platform.db.migration.step.DataChange;
import org.sonar.server.platform.db.migration.step.MassUpdate;

public class PopulateNotificationUuidAndCreatedAt extends DataChange {

private final UuidFactory uuidFactory;
private final System2 system2;

public PopulateNotificationUuidAndCreatedAt(Database db, UuidFactory uuidFactory, System2 system2) {
super(db);
this.uuidFactory = uuidFactory;
this.system2 = system2;
}

@Override
protected void execute(Context context) throws SQLException {
MassUpdate massUpdate = context.prepareMassUpdate();

massUpdate.select("select id from notifications order by id asc");
massUpdate.update("update notifications set uuid = ?, created_at = ? where id = ?");

// now - 7 days, to have previous notification in the past
long lastWeek = system2.now() - (1000 * 60 * 60 * 24 * 7);

AtomicLong cpt = new AtomicLong(0);
massUpdate.execute((row, update) -> {
update.setString(1, uuidFactory.create());
update.setLong(2, lastWeek + cpt.longValue());
update.setLong(3, row.getLong(1));
cpt.addAndGet(1);
return true;
});
}
}

+ 6
- 0
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/DbVersionTestUtils.java View File

@@ -52,6 +52,12 @@ public class DbVersionTestUtils {
assertThat(registry.migrationNumbers).hasSize(migrationCount);
}

public static void verifyMigrationNotEmpty(DbVersion underTest) {
TestMigrationStepRegistry registry = new TestMigrationStepRegistry();
underTest.addSteps(registry);
assertThat(registry.migrationNumbers).isNotEmpty();
}

private static class TestMigrationStepRegistry implements MigrationStepRegistry {
private Set<Long> migrationNumbers = new HashSet<>();


+ 2
- 2
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/DbVersion83Test.java View File

@@ -22,7 +22,7 @@ package org.sonar.server.platform.db.migration.version.v83;
import org.junit.Test;
import org.sonar.server.platform.db.migration.version.DbVersion;

import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMigrationCount;
import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMigrationNotEmpty;
import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMinimumMigrationNumber;

public class DbVersion83Test {
@@ -36,7 +36,7 @@ public class DbVersion83Test {

@Test
public void verify_migration_count() {
verifyMigrationCount(underTest, 15);
verifyMigrationNotEmpty(underTest);
}

}

+ 51
- 0
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/notifications/AddPrimaryKeyOnUuidColumnOfNotificationTableTest.java View File

@@ -0,0 +1,51 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.platform.db.migration.version.v83.notifications;

import java.sql.SQLException;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.db.CoreDbTester;
import org.sonar.server.platform.db.migration.step.MigrationStep;

import static org.assertj.core.api.Assertions.assertThatThrownBy;

public class AddPrimaryKeyOnUuidColumnOfNotificationTableTest {

@Rule
public CoreDbTester db = CoreDbTester.createForSchema(AddPrimaryKeyOnUuidColumnOfNotificationTableTest.class, "schema.sql");

private MigrationStep underTest = new AddPrimaryKeyOnUuidColumnOfNotificationTable(db.database());

@Test
public void execute() throws SQLException {
underTest.execute();

db.assertPrimaryKey("notifications", "pk_notifications", "uuid");
}

@Test
public void migration_is_not_re_entrant() throws SQLException {
underTest.execute();

assertThatThrownBy(() -> underTest.execute()).isInstanceOf(IllegalStateException.class);
}

}

+ 83
- 0
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/notifications/AddUuidAndCreatedAtColumnsToNotificationTest.java View File

@@ -0,0 +1,83 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.platform.db.migration.version.v83.notifications;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.sql.SQLException;
import java.sql.Types;
import org.apache.commons.io.IOUtils;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.utils.SonarException;
import org.sonar.db.CoreDbTester;
import org.sonar.server.platform.db.migration.step.DdlChange;

import static java.sql.Types.BIGINT;
import static org.assertj.core.api.Assertions.assertThat;

public class AddUuidAndCreatedAtColumnsToNotificationTest {

@Rule
public CoreDbTester db = CoreDbTester.createForSchema(AddUuidAndCreatedAtColumnsToNotificationTest.class, "schema.sql");

private DdlChange underTest = new AddUuidAndCreatedAtColumnsToNotification(db.database());

@Before
public void setup() {
insertNotification(1L, "data1");
insertNotification(2L, "data2");
insertNotification(3L, "data3");
}

@Test
public void add_uuid_and_created_at_columns_to_notification() throws SQLException {
underTest.execute();

db.assertColumnDefinition("notifications", "uuid", Types.VARCHAR, 40, true);
db.assertColumnDefinition("notifications", "created_at", BIGINT, null, true);

assertThat(db.countSql("select count(id) from notifications"))
.isEqualTo(3);
}

private void insertNotification(Long id, String data) {

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(data);
objectOutputStream.close();
byte[] byteArray = byteArrayOutputStream.toByteArray();

db.executeInsert("notifications",
"id", id,
"data", byteArray);

} catch (IOException e) {
throw new SonarException("Unable to write notification", e);

} finally {
IOUtils.closeQuietly(byteArrayOutputStream);
}
}
}

+ 51
- 0
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/notifications/DropIdColumnOfNotificationTableTest.java View File

@@ -0,0 +1,51 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.platform.db.migration.version.v83.notifications;

import java.sql.SQLException;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.db.CoreDbTester;
import org.sonar.server.platform.db.migration.step.MigrationStep;

import static org.assertj.core.api.Assertions.assertThatThrownBy;

public class DropIdColumnOfNotificationTableTest {

@Rule
public CoreDbTester db = CoreDbTester.createForSchema(DropIdColumnOfNotificationTableTest.class, "schema.sql");

private MigrationStep underTest = new DropIdColumnOfNotificationTable(db.database());

@Test
public void execute() throws SQLException {
underTest.execute();

db.assertColumnDoesNotExist("notifications", "id");
}

@Test
public void migration_is_not_re_entrant() throws SQLException {
underTest.execute();

assertThatThrownBy(() -> underTest.execute()).isInstanceOf(IllegalStateException.class);
}

}

+ 56
- 0
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/notifications/DropPrimaryKeyOnIdColumnOfNotificationTableTest.java View File

@@ -0,0 +1,56 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.platform.db.migration.version.v83.notifications;

import java.sql.SQLException;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.db.CoreDbTester;
import org.sonar.server.platform.db.migration.step.MigrationStep;
import org.sonar.server.platform.db.migration.version.v83.util.DropPrimaryKeySqlGenerator;
import org.sonar.server.platform.db.migration.version.v83.util.GetConstraintHelper;

import static org.assertj.core.api.Assertions.assertThatThrownBy;

public class DropPrimaryKeyOnIdColumnOfNotificationTableTest {

private static final String TABLE_NAME = "notifications";
@Rule
public CoreDbTester db = CoreDbTester.createForSchema(DropPrimaryKeyOnIdColumnOfNotificationTableTest.class, "schema.sql");

private DropPrimaryKeySqlGenerator dropPrimaryKeySqlGenerator = new DropPrimaryKeySqlGenerator(db.database(), new GetConstraintHelper(db.database()));

private MigrationStep underTest = new DropPrimaryKeyOnIdColumnOfNotificationTable(db.database(), dropPrimaryKeySqlGenerator);

@Test
public void execute() throws SQLException {
underTest.execute();

db.assertNoPrimaryKey(TABLE_NAME);
}

@Test
public void migration_is_not_re_entrant() throws SQLException {
underTest.execute();

assertThatThrownBy(() -> underTest.execute()).isInstanceOf(IllegalStateException.class);
}

}

+ 45
- 0
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/notifications/MakeNotificationUuidAndCreatedAtColumnsNotNullableTest.java View File

@@ -0,0 +1,45 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.platform.db.migration.version.v83.notifications;

import java.sql.SQLException;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.db.CoreDbTester;
import org.sonar.server.platform.db.migration.step.MigrationStep;

import static java.sql.Types.BIGINT;
import static java.sql.Types.VARCHAR;

public class MakeNotificationUuidAndCreatedAtColumnsNotNullableTest {

@Rule
public CoreDbTester db = CoreDbTester.createForSchema(MakeNotificationUuidAndCreatedAtColumnsNotNullableTest.class, "schema.sql");

private MigrationStep underTest = new MakeNotificationUuidAndCreatedAtColumnsNotNullable(db.database());

@Test
public void created_at_and_uuid_columns_are_not_null() throws SQLException {
underTest.execute();

db.assertColumnDefinition("notifications", "uuid", VARCHAR, null, false);
db.assertColumnDefinition("notifications", "created_at", BIGINT, null, false);
}
}

+ 110
- 0
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/notifications/PopulateNotificationUuidAndCreatedAtTest.java View File

@@ -0,0 +1,110 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.platform.db.migration.version.v83.notifications;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.sql.SQLException;
import java.util.Objects;
import java.util.stream.Collectors;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.utils.System2;
import org.sonar.core.util.UuidFactory;
import org.sonar.core.util.UuidFactoryFast;
import org.sonar.db.CoreDbTester;
import org.sonar.server.platform.db.migration.step.DataChange;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class PopulateNotificationUuidAndCreatedAtTest {

@Rule
public CoreDbTester db = CoreDbTester.createForSchema(PopulateNotificationUuidAndCreatedAtTest.class, "schema.sql");

private UuidFactory uuidFactory = UuidFactoryFast.getInstance();
private System2 system2 = mock(System2.class);
private DataChange underTest = new PopulateNotificationUuidAndCreatedAt(db.database(), uuidFactory, system2);

@Before
public void before() {
// exactly one week before now + 1ms, so that ID are exactly equals to timestamp in the tests
when(system2.now()).thenReturn((1000 * 60 * 60 * 24 * 7) + 1L);
}

@Test
public void populate_uuids_and_created_at() throws IOException, SQLException {
insertNotification(1L, "data1");
insertNotification(2L, "data2");
insertNotification(3L, "data3");

underTest.execute();

verifyUuidsAreNotNull();
verifyCreatedAt();
}

@Test
public void migration_is_reentrant() throws IOException, SQLException {
insertNotification(1L, "data1");
insertNotification(2L, "data2");
insertNotification(3L, "data3");

underTest.execute();
// re-entrant
underTest.execute();

verifyUuidsAreNotNull();
verifyCreatedAt();
}

private void verifyUuidsAreNotNull() {
assertThat(db.select("select uuid from notifications")
.stream()
.map(row -> row.get("UUID"))
.filter(Objects::isNull)
.collect(Collectors.toList())).isEmpty();
}

private void verifyCreatedAt() {
assertThat(db.select("select id, created_at from notifications")
.stream()
.filter(row -> !row.get("CREATED_AT").equals(row.get("ID")))
.collect(Collectors.toList())).isEmpty();

}

private void insertNotification(Long id, String data) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(data);
objectOutputStream.close();
byte[] byteArray = byteArrayOutputStream.toByteArray();

db.executeInsert("notifications",
"id", id,
"data", byteArray);
}

}

+ 6
- 0
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/notifications/AddPrimaryKeyOnUuidColumnOfNotificationTableTest/schema.sql View File

@@ -0,0 +1,6 @@
CREATE TABLE "NOTIFICATIONS"(
"ID" INTEGER NOT NULL,
"DATA" BLOB,
"UUID" VARCHAR(40) NOT NULL,
"CREATED_AT" BIGINT NOT NULL
);

+ 5
- 0
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/notifications/AddUuidAndCreatedAtColumnsToNotificationTest/schema.sql View File

@@ -0,0 +1,5 @@
CREATE TABLE "NOTIFICATIONS"(
"ID" INTEGER NOT NULL AUTO_INCREMENT (1,1),
"DATA" BLOB
);
ALTER TABLE "NOTIFICATIONS" ADD CONSTRAINT "PK_NOTIFICATIONS" PRIMARY KEY("ID");

+ 7
- 0
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/notifications/DropIdColumnOfNotificationTableTest/schema.sql View File

@@ -0,0 +1,7 @@
CREATE TABLE "NOTIFICATIONS"(
"ID" INTEGER NOT NULL,
"DATA" BLOB,
"UUID" VARCHAR(40) NOT NULL,
"CREATED_AT" BIGINT NOT NULL
);
ALTER TABLE "NOTIFICATIONS" ADD CONSTRAINT "PK_NOTIFICATIONS" PRIMARY KEY("UUID");

+ 7
- 0
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/notifications/DropPrimaryKeyOnIdColumnOfNotificationTableTest/schema.sql View File

@@ -0,0 +1,7 @@
CREATE TABLE "NOTIFICATIONS"(
"ID" INTEGER NOT NULL AUTO_INCREMENT (1,1),
"UUID" VARCHAR(40) NOT NULL,
"CREATED_AT" BIGINT NOT NULL,
"DATA" BLOB
);
ALTER TABLE "NOTIFICATIONS" ADD CONSTRAINT "PK_NOTIFICATIONS" PRIMARY KEY("ID");

+ 7
- 0
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/notifications/MakeNotificationUuidAndCreatedAtColumnsNotNullableTest/schema.sql View File

@@ -0,0 +1,7 @@
CREATE TABLE "NOTIFICATIONS"(
"ID" INTEGER NOT NULL AUTO_INCREMENT (1,1),
"UUID" VARCHAR(40),
"CREATED_AT" BIGINT,
"DATA" BLOB
);
ALTER TABLE "NOTIFICATIONS" ADD CONSTRAINT "PK_NOTIFICATIONS" PRIMARY KEY("ID");

+ 7
- 0
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/notifications/PopulateNotificationUuidAndCreatedAtTest/schema.sql View File

@@ -0,0 +1,7 @@
CREATE TABLE "NOTIFICATIONS"(
"ID" INTEGER NOT NULL AUTO_INCREMENT (1,1),
"UUID" VARCHAR(40),
"CREATED_AT" BIGINT NULL,
"DATA" BLOB
);
ALTER TABLE "NOTIFICATIONS" ADD CONSTRAINT "PK_NOTIFICATIONS" PRIMARY KEY("ID");

+ 4
- 2
server/sonar-server-common/src/main/java/org/sonar/server/notification/DefaultNotificationManager.java View File

@@ -36,8 +36,10 @@ import javax.annotation.Nullable;
import org.sonar.api.notifications.Notification;
import org.sonar.api.notifications.NotificationChannel;
import org.sonar.api.utils.SonarException;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.core.util.UuidFactory;
import org.sonar.core.util.stream.MoreCollectors;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
@@ -59,13 +61,13 @@ public class DefaultNotificationManager implements NotificationManager {
private NotificationChannel[] notificationChannels;
private final DbClient dbClient;


private boolean alreadyLoggedDeserializationIssue = false;

/**
* Default constructor used by Pico
*/
public DefaultNotificationManager(NotificationChannel[] channels,
DbClient dbClient) {
public DefaultNotificationManager(NotificationChannel[] channels, DbClient dbClient) {
this.notificationChannels = channels;
this.dbClient = dbClient;
}

+ 9
- 2
server/sonar-server-common/src/test/java/org/sonar/server/notification/DefaultNotificationManagerTest.java View File

@@ -38,7 +38,10 @@ import org.junit.rules.ExpectedException;
import org.mockito.InOrder;
import org.sonar.api.notifications.Notification;
import org.sonar.api.notifications.NotificationChannel;
import org.sonar.api.utils.System2;
import org.sonar.api.web.UserRole;
import org.sonar.core.util.UuidFactory;
import org.sonar.core.util.UuidFactoryFast;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.EmailSubscriberDto;
@@ -83,6 +86,7 @@ public class DefaultNotificationManagerTest {
private AuthorizationDao authorizationDao = mock(AuthorizationDao.class);
private DbClient dbClient = mock(DbClient.class);
private DbSession dbSession = mock(DbSession.class);
private System2 system2 = mock(System2.class);

@Before
public void setUp() {
@@ -93,6 +97,7 @@ public class DefaultNotificationManagerTest {
when(dbClient.propertiesDao()).thenReturn(propertiesDao);
when(dbClient.notificationQueueDao()).thenReturn(notificationQueueDao);
when(dbClient.authorizationDao()).thenReturn(authorizationDao);
when(system2.now()).thenReturn(0L);

underTest = new DefaultNotificationManager(new NotificationChannel[] {emailChannel, twitterChannel}, dbClient);
}
@@ -345,7 +350,8 @@ public class DefaultNotificationManagerTest {
String projectKey = randomAlphabetic(6);
when(propertiesDao.findEmailSubscribersForNotification(dbSession, dispatcherKey, "EmailNotificationChannel", projectKey))
.thenReturn(
newHashSet(EmailSubscriberDto.create("user1", false, "user1@foo"), EmailSubscriberDto.create("user3", false, "user3@foo"), EmailSubscriberDto.create("user3", true, "user3@foo")));
newHashSet(EmailSubscriberDto.create("user1", false, "user1@foo"), EmailSubscriberDto.create("user3", false, "user3@foo"),
EmailSubscriberDto.create("user3", true, "user3@foo")));
when(authorizationDao.keepAuthorizedLoginsOnProject(dbSession, newHashSet("user3", "user4"), projectKey, globalPermission))
.thenReturn(newHashSet("user3"));
when(authorizationDao.keepAuthorizedLoginsOnProject(dbSession, newHashSet("user1", "user3"), projectKey, projectPermission))
@@ -370,7 +376,8 @@ public class DefaultNotificationManagerTest {
Set<String> logins = ImmutableSet.of("user1", "user2", "user3");
when(propertiesDao.findEmailSubscribersForNotification(dbSession, dispatcherKey, "EmailNotificationChannel", projectKey, logins))
.thenReturn(
newHashSet(EmailSubscriberDto.create("user1", false, "user1@foo"), EmailSubscriberDto.create("user3", false, "user3@foo"), EmailSubscriberDto.create("user3", true, "user3@foo")));
newHashSet(EmailSubscriberDto.create("user1", false, "user1@foo"), EmailSubscriberDto.create("user3", false, "user3@foo"),
EmailSubscriberDto.create("user3", true, "user3@foo")));
when(authorizationDao.keepAuthorizedLoginsOnProject(dbSession, newHashSet("user3", "user4"), projectKey, globalPermission))
.thenReturn(newHashSet("user3"));
when(authorizationDao.keepAuthorizedLoginsOnProject(dbSession, newHashSet("user1", "user3"), projectKey, projectPermission))

Loading…
Cancel
Save