private void cleanReleaseHistory(ReleaseHistory cleanRelease) {
    String appId = cleanRelease.getAppId();
    String clusterName = cleanRelease.getClusterName();
    String namespaceName = cleanRelease.getNamespaceName();
    String branchName = cleanRelease.getBranchName();

    int retentionLimit = this.getReleaseHistoryRetentionLimit(cleanRelease);
    //Second check, if retentionLimit is default value, do not clean
    if (retentionLimit == DEFAULT_RELEASE_HISTORY_RETENTION_SIZE) {
      return;
    }

    Optional<Long> maxId = this.releaseHistoryRetentionMaxId(cleanRelease, retentionLimit);
    if (!maxId.isPresent()) {
      return;
    }

    boolean hasMore = true;
    while (hasMore && !Thread.currentThread().isInterrupted()) {
      List<ReleaseHistory> cleanReleaseHistoryList = releaseHistoryRepository.findFirst100ByAppIdAndClusterNameAndNamespaceNameAndBranchNameAndIdLessThanEqualOrderByIdAsc(
          appId, clusterName, namespaceName, branchName, maxId.get());
      Set<Long> releaseIds = cleanReleaseHistoryList.stream()
          .map(ReleaseHistory::getReleaseId)
          .collect(Collectors.toSet());

      transactionManager.execute(new TransactionCallbackWithoutResult() {
        @Override
        protected void doInTransactionWithoutResult(TransactionStatus status) {
          releaseHistoryRepository.deleteAll(cleanReleaseHistoryList);
          releaseRepository.deleteAllById(releaseIds);
        }
      });
      hasMore = cleanReleaseHistoryList.size() == 100;
    }
  }
@Test
  @Sql(scripts = "/sql/release-history-test.sql", executionPhase = ExecutionPhase.BEFORE_TEST_METHOD)
  @Sql(scripts = "/sql/clean.sql", executionPhase = ExecutionPhase.AFTER_TEST_METHOD)
  public void testCleanReleaseHistory() {
    ReleaseHistoryService service = (ReleaseHistoryService) AopProxyUtils.getSingletonTarget(releaseHistoryService);
    assert service != null;
    Method method = ReflectionUtils.findMethod(service.getClass(), "cleanReleaseHistory", ReleaseHistory.class);
    assert method != null;
    ReflectionUtils.makeAccessible(method);

    when(bizConfig.releaseHistoryRetentionSize()).thenReturn(-1);
    when(bizConfig.releaseHistoryRetentionSizeOverride()).thenReturn(Maps.newHashMap());
    ReflectionUtils.invokeMethod(method, service, mockReleaseHistory);
    Assert.assertEquals(6, releaseHistoryRepository.count());
    Assert.assertEquals(6, releaseRepository.count());

    when(bizConfig.releaseHistoryRetentionSize()).thenReturn(2);
    when(bizConfig.releaseHistoryRetentionSizeOverride()).thenReturn(Maps.newHashMap());
    ReflectionUtils.invokeMethod(method, service, mockReleaseHistory);
    Assert.assertEquals(2, releaseHistoryRepository.count());
    Assert.assertEquals(2, releaseRepository.count());

    when(bizConfig.releaseHistoryRetentionSize()).thenReturn(2);
    when(bizConfig.releaseHistoryRetentionSizeOverride()).thenReturn(
        ImmutableMap.of("kl-app+default+application+default", 1));
    ReflectionUtils.invokeMethod(method, service, mockReleaseHistory);
    Assert.assertEquals(1, releaseHistoryRepository.count());
    Assert.assertEquals(1, releaseRepository.count());

    Iterable<ReleaseHistory> historyList = releaseHistoryRepository.findAll();
    historyList.forEach(history -> Assert.assertEquals(6, history.getId()));

    Iterable<Release> releaseList = releaseRepository.findAll();
    releaseList.forEach(release -> Assert.assertEquals(6, release.getId()));
  }