From abda47d52fb188bb704d71762a544cf3bdbff3b8 Mon Sep 17 00:00:00 2001 From: Jacek Date: Mon, 18 Jul 2022 17:05:02 +0200 Subject: [PATCH] SONAR-16374 Simplify purge scheduler --- .../server/pushapi/ServerPushModule.java | 8 +- .../purge/PushEventsPurgeInitializer.java | 41 -------- .../purge/PushEventsPurgeScheduler.java | 82 +++++++++++++++- .../purge/PushEventsPurgeSchedulerImpl.java | 98 ------------------- .../purge/PushEventsPurgeInitializerTest.java | 46 --------- ...java => PushEventsPurgeSchedulerTest.java} | 10 +- 6 files changed, 88 insertions(+), 197 deletions(-) delete mode 100644 server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeInitializer.java delete mode 100644 server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeSchedulerImpl.java delete mode 100644 server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeInitializerTest.java rename server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/scheduler/purge/{PushEventsPurgeSchedulerImplTest.java => PushEventsPurgeSchedulerTest.java} (94%) diff --git a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/ServerPushModule.java b/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/ServerPushModule.java index f8f248abe6a..6c49bd7a6e9 100644 --- a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/ServerPushModule.java +++ b/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/ServerPushModule.java @@ -23,8 +23,7 @@ import org.sonar.core.platform.Module; import org.sonar.server.pushapi.scheduler.polling.PushEventPollExecutorServiceImpl; import org.sonar.server.pushapi.scheduler.polling.PushEventPollScheduler; import org.sonar.server.pushapi.scheduler.purge.PushEventsPurgeExecutorServiceImpl; -import org.sonar.server.pushapi.scheduler.purge.PushEventsPurgeInitializer; -import org.sonar.server.pushapi.scheduler.purge.PushEventsPurgeSchedulerImpl; +import org.sonar.server.pushapi.scheduler.purge.PushEventsPurgeScheduler; import org.sonar.server.pushapi.sonarlint.SonarLintClientPermissionsValidator; import org.sonar.server.pushapi.sonarlint.SonarLintClientsRegistry; import org.sonar.server.pushapi.sonarlint.SonarLintPushAction; @@ -42,8 +41,7 @@ public class ServerPushModule extends Module { PushEventPollExecutorServiceImpl.class, PushEventPollScheduler.class, // Push Events Purge - PushEventsPurgeSchedulerImpl.class, - PushEventsPurgeExecutorServiceImpl.class, - PushEventsPurgeInitializer.class); + PushEventsPurgeScheduler.class, + PushEventsPurgeExecutorServiceImpl.class); } } diff --git a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeInitializer.java b/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeInitializer.java deleted file mode 100644 index 1abea71ea67..00000000000 --- a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeInitializer.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 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.pushapi.scheduler.purge; - -import javax.annotation.Nullable; -import org.sonar.api.platform.Server; -import org.sonar.api.platform.ServerStartHandler; - -public class PushEventsPurgeInitializer implements ServerStartHandler { - - private final PushEventsPurgeScheduler pushEventsPurgeScheduler; - - public PushEventsPurgeInitializer(@Nullable PushEventsPurgeScheduler pushEventsPurgeScheduler) { - this.pushEventsPurgeScheduler = pushEventsPurgeScheduler; - } - - @Override - public void onServerStart(Server server) { - if (pushEventsPurgeScheduler != null) { - pushEventsPurgeScheduler.startScheduling(); - } - } - -} diff --git a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeScheduler.java b/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeScheduler.java index d6ce454f753..1d6f6612ded 100644 --- a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeScheduler.java +++ b/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeScheduler.java @@ -19,9 +19,87 @@ */ package org.sonar.server.pushapi.scheduler.purge; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Set; +import org.sonar.api.Startable; +import org.sonar.api.config.Configuration; import org.sonar.api.server.ServerSide; +import org.sonar.api.utils.System2; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.server.util.GlobalLockManager; + +import static java.util.concurrent.TimeUnit.SECONDS; @ServerSide -public interface PushEventsPurgeScheduler { - void startScheduling(); +public class PushEventsPurgeScheduler implements Startable { + private static final Logger LOG = Loggers.get(PushEventsPurgeScheduler.class); + private static final String LOCK_NAME = "PushEventsPurgeCheck"; + private static final String INITIAL_DELAY_IN_SECONDS = "sonar.push.events.purge.initial.delay"; + private static final String ENQUEUE_DELAY_IN_SECONDS = "sonar.push.events.purge.enqueue.delay"; + private static final int ENQUEUE_LOCK_DELAY_IN_SECONDS = 60; + + private final DbClient dbClient; + private final Configuration config; + private final GlobalLockManager lockManager; + private final PushEventsPurgeExecutorService executorService; + private final System2 system; + + public PushEventsPurgeScheduler(DbClient dbClient, Configuration config, GlobalLockManager lockManager, + PushEventsPurgeExecutorService executorService, System2 system) { + this.dbClient = dbClient; + this.executorService = executorService; + this.config = config; + this.lockManager = lockManager; + this.system = system; + } + + @Override + public void start() { + executorService.scheduleAtFixedRate(this::checks, getInitialDelay(), + getEnqueueDelay(), SECONDS); + } + + private void checks() { + try { + // Avoid enqueueing push events purge task multiple times + if (!lockManager.tryLock(LOCK_NAME, ENQUEUE_LOCK_DELAY_IN_SECONDS)) { + return; + } + purgeExpiredPushEvents(); + } catch (Exception e) { + LOG.error("Error in Push Events Purge scheduler", e); + } + } + + private void purgeExpiredPushEvents() { + try (DbSession dbSession = dbClient.openSession(false)) { + Set uuids = dbClient.pushEventDao().selectUuidsOfExpiredEvents(dbSession, getExpiredTimestamp()); + LOG.debug(String.format("%s push events to be deleted...", uuids.size())); + dbClient.pushEventDao().deleteByUuids(dbSession, uuids); + dbSession.commit(); + } + } + + public long getInitialDelay() { + return config.getLong(INITIAL_DELAY_IN_SECONDS).orElse(60 * 60L); + } + + public long getEnqueueDelay() { + return config.getLong(ENQUEUE_DELAY_IN_SECONDS).orElse(60 * 60L); + } + + private long getExpiredTimestamp() { + return Instant.ofEpochMilli(system.now()) + .minus(1, ChronoUnit.HOURS) + .toEpochMilli(); + } + + @Override + public void stop() { + // nothing to do + } } diff --git a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeSchedulerImpl.java b/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeSchedulerImpl.java deleted file mode 100644 index 3a72765bbcb..00000000000 --- a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeSchedulerImpl.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 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.pushapi.scheduler.purge; - -import java.time.Instant; -import java.time.temporal.ChronoUnit; -import java.util.Set; -import org.sonar.api.config.Configuration; -import org.sonar.api.utils.System2; -import org.sonar.api.utils.log.Logger; -import org.sonar.api.utils.log.Loggers; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; -import org.sonar.server.util.GlobalLockManager; - -import static java.util.concurrent.TimeUnit.SECONDS; - -public class PushEventsPurgeSchedulerImpl implements PushEventsPurgeScheduler { - private static final Logger LOG = Loggers.get(PushEventsPurgeSchedulerImpl.class); - private static final String LOCK_NAME = "PushEventsPurgeCheck"; - private static final String INITIAL_DELAY_IN_SECONDS = "sonar.push.events.purge.initial.delay"; - private static final String ENQUEUE_DELAY_IN_SECONDS = "sonar.push.events.purge.enqueue.delay"; - private static final int ENQUEUE_LOCK_DELAY_IN_SECONDS = 60; - - private final DbClient dbClient; - private final Configuration config; - private final GlobalLockManager lockManager; - private final PushEventsPurgeExecutorService executorService; - private final System2 system; - - - public PushEventsPurgeSchedulerImpl(DbClient dbClient, Configuration config, GlobalLockManager lockManager, - PushEventsPurgeExecutorService executorService, System2 system) { - this.dbClient = dbClient; - this.executorService = executorService; - this.config = config; - this.lockManager = lockManager; - this.system = system; - } - - @Override - public void startScheduling() { - executorService.scheduleAtFixedRate(this::checks, getInitialDelay(), - getEnqueueDelay(), SECONDS); - } - - private void checks() { - try { - // Avoid enqueueing push events purge task multiple times - if (!lockManager.tryLock(LOCK_NAME, ENQUEUE_LOCK_DELAY_IN_SECONDS)) { - return; - } - purgeExpiredPushEvents(); - } catch (Exception e) { - LOG.error("Error in Push Events Purge scheduler", e); - } - } - - private void purgeExpiredPushEvents() { - try (DbSession dbSession = dbClient.openSession(false)) { - Set uuids = dbClient.pushEventDao().selectUuidsOfExpiredEvents(dbSession, getExpiredTimestamp()); - LOG.debug(String.format("%s push events to be deleted...", uuids.size())); - dbClient.pushEventDao().deleteByUuids(dbSession, uuids); - dbSession.commit(); - } - } - - public long getInitialDelay() { - return config.getLong(INITIAL_DELAY_IN_SECONDS).orElse(60 * 60L); - } - - public long getEnqueueDelay() { - return config.getLong(ENQUEUE_DELAY_IN_SECONDS).orElse(60 * 60L); - } - - private long getExpiredTimestamp() { - return Instant.ofEpochMilli(system.now()) - .minus(1, ChronoUnit.HOURS) - .toEpochMilli(); - } -} diff --git a/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeInitializerTest.java b/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeInitializerTest.java deleted file mode 100644 index 7fa2a006091..00000000000 --- a/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeInitializerTest.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 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.pushapi.scheduler.purge; - -import org.junit.Before; -import org.junit.Test; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -public class PushEventsPurgeInitializerTest { - - private PushEventsPurgeScheduler pushEventsPurgeScheduler; - - @Before - public void before() { - pushEventsPurgeScheduler = mock(PushEventsPurgeScheduler.class); - } - - @Test - public void onServerStart_givenProjectReportScheduler_startScheduling() { - PushEventsPurgeInitializer pushEventsPurgeInitializer = new PushEventsPurgeInitializer(pushEventsPurgeScheduler); - - pushEventsPurgeInitializer.onServerStart(null); - - verify(pushEventsPurgeScheduler, times(1)).startScheduling(); - } -} diff --git a/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeSchedulerImplTest.java b/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeSchedulerTest.java similarity index 94% rename from server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeSchedulerImplTest.java rename to server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeSchedulerTest.java index 4e05dd2abf7..38b2fa77b71 100644 --- a/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeSchedulerImplTest.java +++ b/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeSchedulerTest.java @@ -45,7 +45,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; -public class PushEventsPurgeSchedulerImplTest { +public class PushEventsPurgeSchedulerTest { private final DbClient dbClient = mock(DbClient.class); private final DbSession dbSession = mock(DbSession.class); private final GlobalLockManager lockManager = mock(GlobalLockManagerImpl.class); @@ -53,7 +53,7 @@ public class PushEventsPurgeSchedulerImplTest { private final PushEventsPurgeExecutorServiceImpl executorService = new PushEventsPurgeExecutorServiceImpl(); private final Configuration configuration = mock(Configuration.class); private final System2 system2 = mock(System2.class); - private final PushEventsPurgeSchedulerImpl underTest = new PushEventsPurgeSchedulerImpl(dbClient, configuration, + private final PushEventsPurgeScheduler underTest = new PushEventsPurgeScheduler(dbClient, configuration, lockManager, executorService, system2); @Before @@ -65,7 +65,7 @@ public class PushEventsPurgeSchedulerImplTest { public void doNothingIfLocked() { when(lockManager.tryLock(any(), anyInt())).thenReturn(false); - underTest.startScheduling(); + underTest.start(); executorService.runCommand(); @@ -76,7 +76,7 @@ public class PushEventsPurgeSchedulerImplTest { public void doNothingIfExceptionIsThrown() { when(lockManager.tryLock(any(), anyInt())).thenThrow(new IllegalArgumentException("Oops")); - underTest.startScheduling(); + underTest.start(); executorService.runCommand(); @@ -90,7 +90,7 @@ public class PushEventsPurgeSchedulerImplTest { when(dbClient.openSession(false)).thenReturn(dbSession); when(dbClient.pushEventDao().selectUuidsOfExpiredEvents(any(), anyLong())).thenReturn(Set.of("1", "2")); - underTest.startScheduling(); + underTest.start(); executorService.runCommand(); -- 2.39.5