Delete trash folders on a regular interval Currently if no schedule is configured, deletion of trash folders only happens at start-up. This means that long running Gerrit instances would not delete projects until Gerrit was restarted. As we've now moved the trash folders to their own separate directory, this operation should no longer take extended period of times and we can therefore run this periodically. This should be considered a breaking change, as we're now deleting projects at a regular interval if no schedule is defined rather than just once at Gerrit startup. Bug: Issue 461332435 Change-Id: Ifaa9d08c72278dd50a75db19f6a1eb1304d3ccc8
diff --git a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/Configuration.java b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/Configuration.java index c93ad77..1c8d62c 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/Configuration.java +++ b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/Configuration.java
@@ -47,6 +47,8 @@ private static final long DEFAULT_ARCHIVE_DURATION_DAYS = 180; protected static final long DEFAULT_TRASH_FOLDER_MAX_ALLOWED_TIME_MINUTES = 10; public static final String DEFAULT_TRASH_FOLDER_NAME = ""; + public static final long DEFAULT_INITIAL_DELAY_MILLIS = 1000; + public static final long DEFAULT_PERIOD_DAYS = 1; private final boolean allowDeletionWithTags; private final boolean archiveDeletedRepos;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/fs/DeleteTrashFolders.java b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/fs/DeleteTrashFolders.java index 550b12f..ac30db24 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/fs/DeleteTrashFolders.java +++ b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/fs/DeleteTrashFolders.java
@@ -14,7 +14,9 @@ package com.googlesource.gerrit.plugins.deleteproject.fs; import static com.google.common.io.RecursiveDeleteOption.ALLOW_INSECURE; -import static java.util.concurrent.Executors.callable; +import static com.googlesource.gerrit.plugins.deleteproject.Configuration.DEFAULT_INITIAL_DELAY_MILLIS; +import static com.googlesource.gerrit.plugins.deleteproject.Configuration.DEFAULT_PERIOD_DAYS; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Stopwatch; @@ -131,18 +133,16 @@ }; ScheduledExecutorService scheduledExecutor = workQueue.getDefaultQueue(); + long initialDelay = DEFAULT_INITIAL_DELAY_MILLIS; + long period = TimeUnit.DAYS.toMillis(DEFAULT_PERIOD_DAYS); if (schedule.isPresent()) { - threadCompleted = - scheduledExecutor.scheduleAtFixedRate( - deleteTrashFoldersRunnable, - schedule.get().initialDelay(), - schedule.get().interval(), - TimeUnit.MILLISECONDS); - } else { - threadCompleted = - scheduledExecutor.schedule( - callable(deleteTrashFoldersRunnable), 0, TimeUnit.MILLISECONDS); + initialDelay = schedule.get().initialDelay(); + period = schedule.get().interval(); } + + threadCompleted = + scheduledExecutor.scheduleAtFixedRate( + deleteTrashFoldersRunnable, initialDelay, period, MILLISECONDS); } private void evaluateIfTrashWithTimeLimit() {
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md index d9b14e8..74c7087 100644 --- a/src/main/resources/Documentation/config.md +++ b/src/main/resources/Documentation/config.md
@@ -137,7 +137,7 @@ ============= Trash folder cleanup can be scheduled to run periodically. -If no schedule is configured, the cleanup runs once at Gerrit startup. +If no schedule is configured, the cleanup runs periodically, once every day. The configuration has to be added to the `@PLUGIN@.config` file.
diff --git a/src/test/java/com/googlesource/gerrit/plugins/deleteproject/fs/DeleteTrashFoldersTest.java b/src/test/java/com/googlesource/gerrit/plugins/deleteproject/fs/DeleteTrashFoldersTest.java index 06300a3..1be602b 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/deleteproject/fs/DeleteTrashFoldersTest.java +++ b/src/test/java/com/googlesource/gerrit/plugins/deleteproject/fs/DeleteTrashFoldersTest.java
@@ -15,6 +15,8 @@ package com.googlesource.gerrit.plugins.deleteproject.fs; import static com.google.common.truth.Truth.assertThat; +import static com.googlesource.gerrit.plugins.deleteproject.Configuration.DEFAULT_INITIAL_DELAY_MILLIS; +import static com.googlesource.gerrit.plugins.deleteproject.Configuration.DEFAULT_PERIOD_DAYS; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.when; @@ -118,6 +120,38 @@ } } + @Test + public void testShouldDeleteRepositoryAfterInitialDelayAndDailyIfNoScheduleIsConfigured() + throws Exception { + trashFolders.start(); + + try (FileRepository repoToDelete = createRepositoryToDelete(REPOSITORY_TO_DELETE); + FileRepository repoToKeep = createRepository("anotherRepo.git")) { + // Repository is not deleted at 1/2 time of the initial delay + fakeScheduledExecutor.advance(DEFAULT_INITIAL_DELAY_MILLIS / 2, TimeUnit.MILLISECONDS); + assertThatRepositoryExists(repoToDelete); + assertThatRepositoryExists(repoToKeep); + + // Repository is deleted 1 second after the initial delay + fakeScheduledExecutor.advance(DEFAULT_INITIAL_DELAY_MILLIS + 1, TimeUnit.MILLISECONDS); + assertThatRepositoryIsDeleted(repoToDelete); + assertThatRepositoryExists(repoToKeep); + } + + try (FileRepository repoToDelete = createRepositoryToDelete(REPOSITORY_TO_DELETE); + FileRepository repoToKeep = createRepository("anotherRepoAgain.git")) { + // Repository recreated + assertThatRepositoryExists(repoToDelete); + assertThatRepositoryExists(repoToKeep); + + // Repository is deleted again after the interval time + fakeScheduledExecutor.advance( + TimeUnit.DAYS.toMillis(DEFAULT_PERIOD_DAYS), TimeUnit.MILLISECONDS); + assertThatRepositoryIsDeleted(repoToDelete); + assertThatRepositoryExists(repoToKeep); + } + } + private static void assertThatRepositoryIsDeleted(FileRepository repoToDelete) { assertFalse( "Repository " + repoToDelete.getDirectory() + " has not been deleted", @@ -131,16 +165,6 @@ } @Test - public void testStart() throws Exception { - FileRepository repoToDelete = createRepositoryToDelete(REPOSITORY_TO_DELETE); - FileRepository repoToKeep = createRepository("anotherRepo.git"); - trashFolders.start(); - trashFolders.getWorkerFuture().get(); - assertThatRepositoryIsDeleted(repoToDelete); - assertThatRepositoryExists(repoToKeep); - } - - @Test public void shouldStopProcessingWhenTimeoutExceeded() throws IOException { when(pluginCfg.getDeleteTrashFoldersMaxAllowedTime()).thenReturn(0L);