You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sk...@apache.org on 2020/12/09 09:16:07 UTC

[ignite-teamcity-bot] branch master updated: Cleaning improvement. Added new time period for deleting old log files.

This is an automated email from the ASF dual-hosted git repository.

sk0x50 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite-teamcity-bot.git


The following commit(s) were added to refs/heads/master by this push:
     new 708978d  Cleaning improvement. Added new time period for deleting old log files.
708978d is described below

commit 708978d8d6273d67d281a46c9ccc47f3d65265da
Author: sergeyuttsel <ut...@gmail.com>
AuthorDate: Wed Dec 9 12:15:36 2020 +0300

    Cleaning improvement. Added new time period for deleting old log files.
    
    Signed-off-by: Slava Koptilin <sl...@gmail.com>
---
 .../org/apache/ignite/ci/db/Ignite2Configurer.java |   3 +
 .../ignite/tcbot/engine/cleaner/CleanerTest.java   | 297 +++++++++++++++++++++
 .../engine/cleaner/TeamcityIgnitedModule.java      |  79 ++++++
 .../java/org/apache/ignite/ci/issue/Issue.java     |   1 +
 .../ignite/tcbot/engine/board/BoardService.java    |   4 +
 .../ignite/tcbot/engine/cleaner/Cleaner.java       | 105 ++++----
 .../ignite/tcbot/engine/conf/CleanerConfig.java    |  33 ++-
 .../ignite/tcbot/engine/conf/ICleanerConfig.java   |   9 +-
 .../tcbot/engine/defect/DefectCompacted.java       |   3 +-
 .../ignite/tcbot/engine/defect/DefectsStorage.java |  34 ++-
 .../ignite/tcbot/engine/issue/IIssuesStorage.java  |   6 +
 .../ignite/tcbot/engine/issue/IssuesStorage.java   |  21 ++
 .../ignited/buildcondition/BuildConditionDao.java  |   5 +
 .../apache/ignite/tcignited/build/FatBuildDao.java |   8 +-
 .../tcignited/buildlog/BuildLogCheckResultDao.java |   5 +
 .../ignite/tcignited/buildref/BuildRefDao.java     |   4 +
 .../tcignited/history/BuildStartTimeStorage.java   |   4 +
 .../history/SuiteInvocationHistoryDao.java         |   5 +
 18 files changed, 570 insertions(+), 56 deletions(-)

diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/Ignite2Configurer.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/Ignite2Configurer.java
index 69ddad8..26522d2 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/Ignite2Configurer.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/Ignite2Configurer.java
@@ -117,6 +117,9 @@ public class Ignite2Configurer {
             LoggerFactory.getLogger(Ignite2Configurer.class).info(msg);
             System.out.println(msg);
         }
+
+        regConf.setMetricsEnabled(true);
+
         return regConf;
     }
 
diff --git a/ignite-tc-helper-web/src/test/java/org/apache/ignite/tcbot/engine/cleaner/CleanerTest.java b/ignite-tc-helper-web/src/test/java/org/apache/ignite/tcbot/engine/cleaner/CleanerTest.java
new file mode 100644
index 0000000..ce47c61
--- /dev/null
+++ b/ignite-tc-helper-web/src/test/java/org/apache/ignite/tcbot/engine/cleaner/CleanerTest.java
@@ -0,0 +1,297 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.tcbot.engine.cleaner;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.internal.SingletonScope;
+import java.lang.reflect.Field;
+import java.util.Random;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.Ignition;
+import org.apache.ignite.ci.db.TcHelperDb;
+import org.apache.ignite.ci.issue.Issue;
+import org.apache.ignite.ci.issue.IssueKey;
+import org.apache.ignite.ci.teamcity.ignited.BuildRefCompacted;
+import org.apache.ignite.ci.teamcity.ignited.buildcondition.BuildConditionDao;
+import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.jiraservice.IJiraIntegrationProvider;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.tcbot.common.conf.IDataSourcesConfigSupplier;
+import org.apache.ignite.tcbot.engine.chain.TestCompactedMult;
+import org.apache.ignite.tcbot.engine.conf.CleanerConfig;
+import org.apache.ignite.tcbot.engine.conf.ICleanerConfig;
+import org.apache.ignite.tcbot.engine.conf.ITcBotConfig;
+import org.apache.ignite.tcbot.engine.defect.DefectCompacted;
+import org.apache.ignite.tcbot.engine.defect.DefectsStorage;
+import org.apache.ignite.tcbot.engine.issue.IssuesStorage;
+import org.apache.ignite.tcbot.persistence.TcBotPersistenceModule;
+import org.apache.ignite.tcbot.persistence.scheduler.DirectExecNoWaitScheduler;
+import org.apache.ignite.tcbot.persistence.scheduler.IScheduler;
+import org.apache.ignite.tcignited.build.FatBuildDao;
+import org.apache.ignite.tcignited.build.TestCompactedV2;
+import org.apache.ignite.tcignited.buildlog.BuildLogCheckResultDao;
+import org.apache.ignite.tcignited.buildref.BuildRefDao;
+import org.apache.ignite.tcignited.history.BuildStartTimeStorage;
+import org.apache.ignite.tcignited.history.SuiteInvocationHistoryDao;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import static java.time.ZonedDateTime.now;
+import static org.apache.ignite.tcbot.engine.issue.IssueType.newFailure;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class CleanerTest {
+
+    /** Server Name for test. */
+    public static final String APACHE = "apachetest";
+
+    /** Test ignite port. */
+    public static final int TEST_IGNITE_PORT = 64124;
+
+    /** Ignite. */
+    private static Ignite ignite;
+
+    /**
+     *
+     */
+    @BeforeClass
+    public static void startIgnite() {
+        IgniteConfiguration cfg = new IgniteConfiguration();
+        final TcpDiscoverySpi spi = new TcpDiscoverySpi();
+        int locPort = TEST_IGNITE_PORT;
+
+        spi.setLocalPort(locPort);
+        spi.setLocalPortRange(1);
+        spi.setIpFinder(new TcHelperDb.LocalOnlyTcpDiscoveryIpFinder(locPort));
+
+        cfg.setDiscoverySpi(spi);
+
+        ignite = Ignition.start(cfg);
+    }
+
+    /**
+     *
+     */
+    @AfterClass
+    public static void stopIgnite() {
+        if (ignite != null)
+            ignite.close();
+    }
+
+    @Test
+    public void testCleaner() throws Exception {
+        TeamcityIgnitedModule module = new TeamcityIgnitedModule();
+
+        Injector injector = Guice.createInjector(module, new IgniteAndSchedulerTestModule());
+
+        FatBuildDao fatBuildDao = injector.getInstance(FatBuildDao.class);
+        DefectsStorage defectsStorage = injector.getInstance(DefectsStorage.class);
+        IssuesStorage issuesStorage = injector.getInstance(IssuesStorage.class);
+        Cleaner cleaner = injector.getInstance(Cleaner.class);
+
+        fatBuildDao.init();
+        injector.getInstance(SuiteInvocationHistoryDao.class).init();
+        injector.getInstance(BuildLogCheckResultDao.class).init();
+        injector.getInstance(BuildRefDao.class).init();
+        injector.getInstance(BuildStartTimeStorage.class).init();
+        injector.getInstance(BuildConditionDao.class).init();
+
+        FatBuildEntry.fatBuildDao = fatBuildDao;
+        DefectEntry.defectsStorage = defectsStorage;
+        IssueEntry.issuesStorage = issuesStorage;
+
+        Random rnd = new Random();
+
+        final String tc1 = "apache";
+        final String tc2 = "private";
+        final int tcId1 = Math.abs(tc1.hashCode());
+        final int tcId2 = Math.abs(tc2.hashCode());
+        final int safeDays = 5;
+        final long nowTime = now().toInstant().toEpochMilli();
+
+        FatBuildEntry oldBuildToRemove1 = FatBuildEntry.createFatBuildEntry(tcId1, 1, now().minusDays(safeDays + 5).toInstant().toEpochMilli(), true);
+        FatBuildEntry oldBuildToSave1 = FatBuildEntry.createFatBuildEntry(tcId1, 2, now().minusDays(safeDays + 5).toInstant().toEpochMilli(), true);
+        FatBuildEntry buildToSave1 = FatBuildEntry.createFatBuildEntry(tcId1, 3, now().minusDays(safeDays - 2).toInstant().toEpochMilli(), true);
+        FatBuildEntry notSavedBuild = FatBuildEntry.createFatBuildEntry(tcId1, 4, now().minusDays(safeDays - 2).toInstant().toEpochMilli(), false);
+
+        DefectEntry oldOpenedDefectToSave1 = DefectEntry.createDefectEntry(11, tcId1, oldBuildToSave1.build, -1);
+        DefectEntry oldOpenedDefectToSave2 = DefectEntry.createDefectEntry(15, tcId2, oldBuildToRemove1.build, now().minusDays(safeDays + 5).toInstant().toEpochMilli());
+        DefectEntry oldClosedWithBrokenConsistencyDefectToSave3 = DefectEntry.createDefectEntry(12, tcId1, notSavedBuild.build, now().minusDays(safeDays + 5).toInstant().toEpochMilli());
+        DefectEntry oldClosedDefectToRemove1 = DefectEntry.createDefectEntry(13, tcId1, oldBuildToRemove1.build, now().minusDays(safeDays + 5).toInstant().toEpochMilli());
+        DefectEntry oldClosedWithBrokenConsistencyDefectToRemove2 = DefectEntry.createDefectEntry(14, tcId1, notSavedBuild.build, now().minusDays(safeDays + 1000).toInstant().toEpochMilli());
+
+        IssueEntry issueToRemove1 = IssueEntry.createIssueEntry(tc1, oldBuildToRemove1.buildId, nowTime);
+        IssueEntry issueWithBrokenConsistencyToRemove2 = IssueEntry.createIssueEntry(tc1, Math.abs(rnd.nextInt()), now().minusDays(safeDays + 1000).toInstant().toEpochMilli());
+        IssueEntry issueToSave1 = IssueEntry.createIssueEntry(tc2, oldBuildToRemove1.buildId, nowTime);
+        IssueEntry issueWithBrokenConsistencyToSave2 = IssueEntry.createIssueEntry(tc1, Math.abs(rnd.nextInt()), nowTime);
+
+        cleaner.clean();
+
+        Assert.assertNull(fatBuildDao.getFatBuild(oldBuildToRemove1.tcId, oldBuildToRemove1.buildId));
+        Assert.assertNotNull(fatBuildDao.getFatBuild(oldBuildToSave1.tcId, oldBuildToSave1.buildId));
+        Assert.assertNotNull(fatBuildDao.getFatBuild(buildToSave1.tcId, buildToSave1.buildId));
+
+        Assert.assertNull(defectsStorage.load(oldClosedDefectToRemove1.id));
+        Assert.assertNull(defectsStorage.load(oldClosedWithBrokenConsistencyDefectToRemove2.id));
+        Assert.assertNotNull(defectsStorage.load(oldOpenedDefectToSave1.id));
+        Assert.assertNotNull(defectsStorage.load(oldOpenedDefectToSave2.id));
+        Assert.assertNotNull(defectsStorage.load(oldClosedWithBrokenConsistencyDefectToSave3.id));
+
+        Assert.assertNull(issuesStorage.getIssue(issueToRemove1.issueKey));
+        Assert.assertNull(issuesStorage.getIssue(issueWithBrokenConsistencyToRemove2.issueKey));
+        Assert.assertNotNull(issuesStorage.getIssue(issueToSave1.issueKey));
+        Assert.assertNotNull(issuesStorage.getIssue(issueWithBrokenConsistencyToSave2.issueKey));
+    }
+
+    private static class FatBuildEntry {
+        int tcId;
+        int buildId;
+        FatBuildCompacted build;
+
+        static FatBuildDao fatBuildDao;
+        static Field setterBuildStartDate;
+
+        static {
+            try {
+                setterBuildStartDate = FatBuildCompacted.class.getDeclaredField("startDate");
+            }
+            catch (NoSuchFieldException e) {
+                e.printStackTrace();
+            }
+
+            setterBuildStartDate.setAccessible(true);
+        }
+
+        private FatBuildEntry(int tcId, int buildId, FatBuildCompacted build) {
+            this.tcId = tcId;
+            this.buildId = buildId;
+            this.build = build;
+        }
+
+        static FatBuildEntry createFatBuildEntry(int srvId, int buildId, long startDate, boolean save) throws Exception{
+            FatBuildCompacted fatBuildCompacted = new FatBuildCompacted();
+            fatBuildCompacted.withId(buildId);
+
+            setterBuildStartDate.setLong(fatBuildCompacted, startDate);
+
+            FatBuildEntry fatBuildEntry = new FatBuildEntry(srvId, buildId, fatBuildCompacted);
+
+            if (save)
+                fatBuildDao.putFatBuild(fatBuildEntry.tcId, fatBuildEntry.buildId, fatBuildEntry.build);
+
+            return fatBuildEntry;
+        }
+    }
+
+    private static class DefectEntry {
+        int id;
+        int tcId;
+        DefectCompacted defect;
+        FatBuildCompacted build;
+
+        static DefectsStorage defectsStorage;
+        static Field setterResolvedTs;
+
+        static {
+            try {
+                setterResolvedTs = DefectCompacted.class.getDeclaredField("resolvedTs");
+            }
+            catch (NoSuchFieldException e) {
+                e.printStackTrace();
+            }
+
+            setterResolvedTs.setAccessible(true);
+        }
+
+        public DefectEntry(int id, int tcId, DefectCompacted defect,
+            FatBuildCompacted build) {
+            this.id = id;
+            this.tcId = tcId;
+            this.defect = defect;
+            this.build = build;
+        }
+
+        static DefectEntry createDefectEntry(int id, int tcId, FatBuildCompacted build, long resolvedTs) throws IllegalAccessException {
+            DefectCompacted defect = new DefectCompacted(id);
+            defect.tcSrvId(tcId);
+            defect.computeIfAbsent(build);
+            setterResolvedTs.setLong(defect, resolvedTs);
+
+            defectsStorage.save(defect);
+
+            return new DefectEntry(id, tcId, defect, build);
+        }
+    }
+
+    private static class IssueEntry {
+        IssueKey issueKey;
+        Issue issue;
+
+        static IssuesStorage issuesStorage;
+
+        public IssueEntry(IssueKey issueKey, Issue issue) {
+            this.issueKey = issueKey;
+            this.issue = issue;
+        }
+
+        static IssueEntry createIssueEntry(String tc, Integer buildId, Long detectedTs) {
+            IssueKey issueKey = new IssueKey(tc, buildId, "issue" + new Random().nextLong());
+            Issue issue = new Issue(issueKey, newFailure, 888888L);
+            issue.detectedTs = detectedTs;
+
+            issuesStorage.saveIssue(issue);
+
+            return new IssueEntry(issueKey, issue);
+        }
+    }
+
+    private static class IgniteAndSchedulerTestModule extends AbstractModule {
+        /** {@inheritDoc} */
+        @Override protected void configure() {
+            bind(Ignite.class).toInstance(ignite);
+            bind(IScheduler.class).to(DirectExecNoWaitScheduler.class).in(new SingletonScope());
+
+            final IJiraIntegrationProvider jiraProv = Mockito.mock(IJiraIntegrationProvider.class);
+            bind(IJiraIntegrationProvider.class).toInstance(jiraProv);
+
+            ITcBotConfig cfg = Mockito.mock(ITcBotConfig.class);
+
+            ICleanerConfig cCfg = mock(CleanerConfig.class);
+
+            when(cCfg.enabled()).thenReturn(true);
+            when(cCfg.numOfItemsToDel()).thenReturn(100);
+            when(cCfg.safeDaysForCaches()).thenReturn(5);
+
+            when(cfg.getCleanerConfig()).thenReturn(cCfg);
+
+            bind(ITcBotConfig.class).toInstance(cfg);
+            bind(IDataSourcesConfigSupplier.class).toInstance(cfg);
+
+            install(new TcBotPersistenceModule());
+        }
+    }
+}
diff --git a/ignite-tc-helper-web/src/test/java/org/apache/ignite/tcbot/engine/cleaner/TeamcityIgnitedModule.java b/ignite-tc-helper-web/src/test/java/org/apache/ignite/tcbot/engine/cleaner/TeamcityIgnitedModule.java
new file mode 100644
index 0000000..388b43a
--- /dev/null
+++ b/ignite-tc-helper-web/src/test/java/org/apache/ignite/tcbot/engine/cleaner/TeamcityIgnitedModule.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.tcbot.engine.cleaner;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.internal.SingletonScope;
+import javax.annotation.Nullable;
+import org.apache.ignite.ci.teamcity.ignited.buildcondition.BuildConditionDao;
+import org.apache.ignite.ci.teamcity.ignited.buildtype.BuildTypeDao;
+import org.apache.ignite.ci.teamcity.ignited.buildtype.BuildTypeRefDao;
+import org.apache.ignite.ci.teamcity.ignited.buildtype.BuildTypeSync;
+import org.apache.ignite.ci.teamcity.ignited.change.ChangeDao;
+import org.apache.ignite.ci.teamcity.ignited.change.ChangeSync;
+import org.apache.ignite.tcbot.engine.defect.DefectsStorage;
+import org.apache.ignite.tcbot.engine.issue.IIssuesStorage;
+import org.apache.ignite.tcbot.engine.issue.IssuesStorage;
+import org.apache.ignite.tcignited.build.FatBuildDao;
+import org.apache.ignite.tcignited.build.ProactiveFatBuildSync;
+import org.apache.ignite.tcignited.build.UpdateCountersStorage;
+import org.apache.ignite.tcignited.buildlog.BuildLogCheckResultDao;
+import org.apache.ignite.tcignited.buildlog.BuildLogProcessorModule;
+import org.apache.ignite.tcignited.buildlog.ILogProductSpecific;
+import org.apache.ignite.tcignited.buildlog.LogIgniteSpecific;
+import org.apache.ignite.tcignited.buildref.BuildRefDao;
+import org.apache.ignite.tcignited.buildref.BuildRefSync;
+import org.apache.ignite.tcignited.history.BuildStartTimeStorage;
+import org.apache.ignite.tcignited.history.HistoryCollector;
+import org.apache.ignite.tcignited.history.SuiteInvocationHistoryDao;
+import org.apache.ignite.tcignited.mute.MuteDao;
+import org.apache.ignite.tcignited.mute.MuteSync;
+import org.apache.ignite.tcservice.TcRealConnectionModule;
+
+public class TeamcityIgnitedModule extends AbstractModule {
+    /** {@inheritDoc} */
+    @Override protected void configure() {
+        bind(BuildRefDao.class).in(new SingletonScope());
+        bind(BuildRefSync.class).in(new SingletonScope());
+        bind(BuildConditionDao.class).in(new SingletonScope());
+        bind(FatBuildDao.class).in(new SingletonScope());
+        bind(ProactiveFatBuildSync.class).in(new SingletonScope());
+        bind(ChangeSync.class).in(new SingletonScope());
+        bind(ChangeDao.class).in(new SingletonScope());
+        bind(BuildTypeRefDao.class).in(new SingletonScope());
+        bind(BuildTypeDao.class).in(new SingletonScope());
+        bind(BuildTypeSync.class).in(new SingletonScope());
+        bind(BuildStartTimeStorage.class).in(new SingletonScope());
+        bind(MuteDao.class).in(new SingletonScope());
+        bind(MuteSync.class).in(new SingletonScope());
+        bind(BuildLogCheckResultDao.class).in(new SingletonScope());
+        bind(SuiteInvocationHistoryDao.class).in(new SingletonScope());
+        bind(HistoryCollector.class).in(new SingletonScope());
+        bind(ILogProductSpecific.class).to(LogIgniteSpecific.class).in(new SingletonScope());
+        bind(UpdateCountersStorage.class).in(new SingletonScope());
+        bind(Cleaner.class).in(new SingletonScope());
+        bind(DefectsStorage.class).in(new SingletonScope());
+        bind(IIssuesStorage.class).to(IssuesStorage.class).in(new SingletonScope());
+
+        TcRealConnectionModule module = new TcRealConnectionModule();
+
+        install(module);
+
+        install(new BuildLogProcessorModule());
+    }
+}
diff --git a/tcbot-engine/src/main/java/org/apache/ignite/ci/issue/Issue.java b/tcbot-engine/src/main/java/org/apache/ignite/ci/issue/Issue.java
index d765130..fe923e6 100644
--- a/tcbot-engine/src/main/java/org/apache/ignite/ci/issue/Issue.java
+++ b/tcbot-engine/src/main/java/org/apache/ignite/ci/issue/Issue.java
@@ -49,6 +49,7 @@ public class Issue {
 
     public double flakyRate;
 
+    /** Branch alias */
     @Nullable
     public String trackedBranchName;
 
diff --git a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/board/BoardService.java b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/board/BoardService.java
index 5d5e2f8..4e8001e 100644
--- a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/board/BoardService.java
+++ b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/board/BoardService.java
@@ -119,6 +119,10 @@ public class BoardService {
                 FatBuildCompacted firstBuild = cause.build();
                 FatBuildCompacted fatBuild = fatBuildDao.getFatBuild(next.tcSrvId(), firstBuild.id());
 
+                // In case the build was removed from the cache, but the defect was not yet
+                if (fatBuild == null)
+                    continue;
+
                 List<Future<FatBuildCompacted>> futures = buildChainProcessor.replaceWithRecent(fatBuild, allBuildsMap, tcIgn);
 
                 Stream<FatBuildCompacted> results = FutureUtil.getResults(futures);
diff --git a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/cleaner/Cleaner.java b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/cleaner/Cleaner.java
index 97791ce..dbe5499 100644
--- a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/cleaner/Cleaner.java
+++ b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/cleaner/Cleaner.java
@@ -20,6 +20,8 @@ import java.io.File;
 import java.time.ZonedDateTime;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
@@ -42,18 +44,24 @@ import org.apache.ignite.tcignited.history.SuiteInvocationHistoryDao;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static java.util.stream.Collectors.groupingBy;
+import static java.util.stream.Collectors.mapping;
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toSet;
+import static org.apache.ignite.tcignited.build.FatBuildDao.cacheKeyToSrvIdAndBuildId;
+
 public class Cleaner {
     private final AtomicBoolean init = new AtomicBoolean();
 
-    @Inject IIssuesStorage issuesStorage;
-    @Inject FatBuildDao fatBuildDao;
-    @Inject SuiteInvocationHistoryDao suiteInvocationHistoryDao;
-    @Inject BuildLogCheckResultDao buildLogCheckResultDao;
-    @Inject BuildRefDao buildRefDao;
-    @Inject BuildStartTimeStorage buildStartTimeStorage;
-    @Inject BuildConditionDao buildConditionDao;
-    @Inject DefectsStorage defectsStorage;
-    @Inject ITcBotConfig cfg;
+    @Inject private IIssuesStorage issuesStorage;
+    @Inject private FatBuildDao fatBuildDao;
+    @Inject private SuiteInvocationHistoryDao suiteInvocationHistoryDao;
+    @Inject private BuildLogCheckResultDao buildLogCheckResultDao;
+    @Inject private BuildRefDao buildRefDao;
+    @Inject private BuildStartTimeStorage buildStartTimeStorage;
+    @Inject private BuildConditionDao buildConditionDao;
+    @Inject private DefectsStorage defectsStorage;
+    @Inject private ITcBotConfig cfg;
 
     /** Logger. */
     private static final Logger logger = LoggerFactory.getLogger(Cleaner.class);
@@ -65,73 +73,82 @@ public class Cleaner {
     public void clean() {
         try {
             if (cfg.getCleanerConfig().enabled()) {
-                long safeDays = cfg.getCleanerConfig().safeDays();
-
                 int numOfItemsToDel = cfg.getCleanerConfig().numOfItemsToDel();
 
-                ZonedDateTime thresholdDate = ZonedDateTime.now().minusDays(safeDays);
+                long safeDaysForCaches = cfg.getCleanerConfig().safeDaysForCaches();
+
+                ZonedDateTime thresholdDateForCaches = ZonedDateTime.now().minusDays(safeDaysForCaches);
+
+                long safeDaysForLogs = cfg.getCleanerConfig().safeDaysForLogs();
+
+                ZonedDateTime thresholdDateForLogs = ZonedDateTime.now().minusDays(safeDaysForLogs);
 
-                logger.info("Some data (numOfItemsToDel=" + numOfItemsToDel + ") older than " + thresholdDate + " will be removed.");
+                logger.info("Some data from caches (numOfItemsToDel=" + numOfItemsToDel + ") older than " + thresholdDateForCaches + " will be removed.");
 
-                long thresholdEpochMilli = thresholdDate.toInstant().toEpochMilli();
+                logger.info("Some log files (numOfItemsToDel=" + numOfItemsToDel + ") older than " + thresholdDateForLogs + " will be removed.");
 
-                removeCacheEntries(thresholdEpochMilli, numOfItemsToDel);
+                removeCacheEntries(thresholdDateForCaches, numOfItemsToDel);
 
-                removeLogFiles(thresholdEpochMilli, numOfItemsToDel);
+                removeLogFiles(thresholdDateForLogs, numOfItemsToDel);
             }
             else
                 logger.info("Periodic cache clean disabled.");
         }
         catch (Throwable e) {
-            logger.error("Periodic cache clean failed: " + e.getMessage(), e);
+            logger.error("Periodic cache and log clean failed: " + e.getMessage(), e);
 
             e.printStackTrace();
         }
-
     }
 
-    private void removeCacheEntries(long thresholdDate, int numOfItemsToDel) {
-        List<Long> oldBuildsKeys = fatBuildDao.getOldBuilds(thresholdDate, numOfItemsToDel);
-
-        List<String> strOldBuildsKeys = oldBuildsKeys.stream().map(compositeId -> {
-                IgniteBiTuple<Integer, Integer> idTuple = FatBuildDao.cacheKeyToSrvIdAndBuildId(compositeId);
-                return "TeamCity id: " + idTuple.get1() + " build id: " + idTuple.get2();
-            })
-            .collect(Collectors.toList());
+    private int removeCacheEntries(ZonedDateTime thresholdDate, int numOfItemsToDel) {
+        long thresholdEpochMilli = thresholdDate.toInstant().toEpochMilli();
 
-        logger.info("Builds will be removed (" + strOldBuildsKeys.size() + "): " + strOldBuildsKeys);
+        Set<Long> oldBuildsKeys = fatBuildDao.getOldBuilds(thresholdEpochMilli, numOfItemsToDel);
 
-        for (Long buildCacheKey : oldBuildsKeys) {
-            suiteInvocationHistoryDao.remove(buildCacheKey);
+        Map<Integer, List<Integer>> oldBuildsTeamCityAndBuildIds = oldBuildsKeys.stream()
+            .map(FatBuildDao::cacheKeyToSrvIdAndBuildId)
+            .collect(groupingBy(IgniteBiTuple::get1, mapping(IgniteBiTuple::get2, toList())));
 
-            buildLogCheckResultDao.remove(buildCacheKey);
+        defectsStorage.checkIfPossibleToRemove(oldBuildsTeamCityAndBuildIds);
 
-            buildRefDao.remove(buildCacheKey);
+        oldBuildsKeys = oldBuildsTeamCityAndBuildIds.entrySet().stream()
+            .flatMap(entry -> entry.getValue().stream()
+                .map(buildId -> FatBuildDao.buildIdToCacheKey(entry.getKey(), buildId)))
+            .collect(toSet());
 
-            buildStartTimeStorage.remove(buildCacheKey);
+        logger.info("Builds will be removed (" + oldBuildsKeys.size() + ")");
 
-            buildConditionDao.remove(buildCacheKey);
+        suiteInvocationHistoryDao.removeAll(oldBuildsKeys);
+        buildLogCheckResultDao.removeAll(oldBuildsKeys);
+        buildRefDao.removeAll(oldBuildsKeys);
+        buildStartTimeStorage.removeAll(oldBuildsKeys);
+        buildConditionDao.removeAll(oldBuildsKeys);
+        defectsStorage.removeOldDefects(oldBuildsTeamCityAndBuildIds);
+        issuesStorage.removeOldIssues(oldBuildsTeamCityAndBuildIds);
+        fatBuildDao.removeAll(oldBuildsKeys);
 
-            fatBuildDao.remove(buildCacheKey);
-        }
+        //Need to eventually delete data with broken consistency
+        defectsStorage.removeOldDefects(thresholdDate.minusDays(60).toInstant().toEpochMilli(), numOfItemsToDel);
+        issuesStorage.removeOldIssues(thresholdDate.minusDays(60).toInstant().toEpochMilli(), numOfItemsToDel);
 
-        defectsStorage.removeOldDefects(thresholdDate, numOfItemsToDel);
-
-        issuesStorage.removeOldIssues(thresholdDate, numOfItemsToDel);
+        return oldBuildsKeys.size();
     }
 
-    private void removeLogFiles(long thresholdDate, int numOfItemsToDel) {
+    private void removeLogFiles(ZonedDateTime thresholdDate, int numOfItemsToDel) {
+        long thresholdEpochMilli = thresholdDate.toInstant().toEpochMilli();
+
         final File workDir = TcBotWorkDir.resolveWorkDir();
 
         for (String srvId : cfg.getServerIds()) {
             File srvIdLogDir = new File(workDir, cfg.getTeamcityConfig(srvId).logsDirectory());
 
-            removeFiles(srvIdLogDir, thresholdDate, numOfItemsToDel);
+            removeFiles(srvIdLogDir, thresholdEpochMilli, numOfItemsToDel);
         }
 
         File tcBotLogDir = new File(workDir, "tcbot_logs");
 
-        removeFiles(tcBotLogDir, thresholdDate, numOfItemsToDel);
+        removeFiles(tcBotLogDir, thresholdEpochMilli, numOfItemsToDel);
     }
 
     private void removeFiles(File dir, long thresholdDate, int numOfItemsToDel) {
@@ -144,9 +161,7 @@ public class Cleaner {
                 if (file.lastModified() < thresholdDate && numOfItemsToDel-- > 0)
                     filesToRmv.add(file);
 
-        logger.info("In the directory " + dir + " files will be removed (" +
-            filesToRmv.size() + "): " + filesToRmv.stream().map(File::getName).collect(Collectors.toList())
-        );
+        logger.info("In the directory " + dir + " files will be removed (" + filesToRmv.size() + ")");
 
         for (File file : filesToRmv) {
             file.delete();
@@ -165,7 +180,7 @@ public class Cleaner {
 
             executorService = Executors.newSingleThreadScheduledExecutor();
 
-            executorService.scheduleAtFixedRate(this::clean, 5, 60, TimeUnit.MINUTES);
+            executorService.scheduleAtFixedRate(this::clean, 5, cfg.getCleanerConfig().period(), TimeUnit.MINUTES);
         }
     }
 
diff --git a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/conf/CleanerConfig.java b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/conf/CleanerConfig.java
index b4a63b3..07677bd 100644
--- a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/conf/CleanerConfig.java
+++ b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/conf/CleanerConfig.java
@@ -16,33 +16,51 @@
  */
 package org.apache.ignite.tcbot.engine.conf;
 
+/** */
 public class CleanerConfig implements ICleanerConfig{
     /** */
     public static final int DEFAULT_SAVE_DAYS = 30 * 6;
 
     /** */
-    public static final int DEFAULT_NUMBER_OF_ITEMS_TO_DELETE = 100;
+    public static final int DEFAULT_NUMBER_OF_ITEMS_TO_DELETE = 100_000;
 
     /** */
-    private Integer safeDays;
+    public static final int DEFAULT_PERIOD_MINUTES = 60 * 24;
+
+    /** */
+    private Integer safeDaysForCaches;
+
+    /** */
+    private Integer safeDaysForLogs;
 
     /** */
     private Integer numOfItemsToDel;
 
     /** */
+    private Integer period;
+
+    /** */
     private Boolean enabled;
 
+    /** */
     public static CleanerConfig getDefaultCleanerConfig() {
         CleanerConfig cfg = new CleanerConfig();
-        cfg.safeDays = DEFAULT_SAVE_DAYS;
+        cfg.safeDaysForCaches = DEFAULT_SAVE_DAYS;
+        cfg.safeDaysForLogs = DEFAULT_SAVE_DAYS;
         cfg.numOfItemsToDel = DEFAULT_NUMBER_OF_ITEMS_TO_DELETE;
         cfg.enabled = true;
+        cfg.period = DEFAULT_PERIOD_MINUTES;
         return cfg;
     }
 
     /** */
-    public int safeDays() {
-        return safeDays == null || safeDays < 0 ? DEFAULT_SAVE_DAYS : safeDays;
+    public int safeDaysForCaches() {
+        return safeDaysForCaches == null || safeDaysForCaches < 0 ? DEFAULT_SAVE_DAYS : safeDaysForCaches;
+    }
+
+    /** */
+    public int safeDaysForLogs() {
+        return safeDaysForLogs == null || safeDaysForLogs < 0 ? DEFAULT_SAVE_DAYS : safeDaysForLogs;
     }
 
     /** */
@@ -51,6 +69,11 @@ public class CleanerConfig implements ICleanerConfig{
     }
 
     /** */
+    public int period() {
+        return period == null || period < 0 ? DEFAULT_PERIOD_MINUTES : period;
+    }
+
+    /** */
     public boolean enabled() {
         return enabled == null ? true : enabled;
     }
diff --git a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/conf/ICleanerConfig.java b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/conf/ICleanerConfig.java
index ab0cded..97e4f0e 100644
--- a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/conf/ICleanerConfig.java
+++ b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/conf/ICleanerConfig.java
@@ -16,13 +16,20 @@
  */
 package org.apache.ignite.tcbot.engine.conf;
 
+/** */
 public interface ICleanerConfig {
     /** */
-    int safeDays();
+    int safeDaysForCaches();
+
+    /** */
+    int safeDaysForLogs();
 
     /** */
     int numOfItemsToDel();
 
     /** */
+    int period();
+
+    /** */
     boolean enabled();
 }
diff --git a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/defect/DefectCompacted.java b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/defect/DefectCompacted.java
index 9e98d49..4252667 100644
--- a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/defect/DefectCompacted.java
+++ b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/defect/DefectCompacted.java
@@ -31,6 +31,7 @@ public class DefectCompacted {
     /** Synthetic Defect Id. */
     private int id;
 
+    /** Branch alias string ID. */
     private int tcBranch = -1;
 
     /** Tc server code hashcode. */
@@ -39,7 +40,7 @@ public class DefectCompacted {
     /** Tc server code compactor string ID. */
     private int tcSrvCodeCid = -1;
 
-    /** Tracked branch Compactor string ID. */
+    /** Tracked branch alias Compactor string ID. */
     private int trackedBranchCid = -1;
 
     /** Resolved by username id : Compactor ID of user login (principal ID). */
diff --git a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/defect/DefectsStorage.java b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/defect/DefectsStorage.java
index 407925a..78804ee 100644
--- a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/defect/DefectsStorage.java
+++ b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/defect/DefectsStorage.java
@@ -21,8 +21,8 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.function.BiFunction;
-import java.util.stream.Collectors;
 import javax.annotation.concurrent.NotThreadSafe;
 import javax.cache.Cache;
 import javax.inject.Inject;
@@ -40,6 +40,8 @@ import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.tcbot.persistence.CacheConfigs;
 
+import static java.util.stream.Collectors.toList;
+
 @NotThreadSafe
 public class DefectsStorage {
     /** Bot detected defects. */
@@ -105,7 +107,7 @@ public class DefectsStorage {
             .map(ChangeCompacted::commitVersion)
             .map(CommitCompacted::new)
             .sorted(CommitCompacted::compareTo)
-            .collect(Collectors.toList());
+            .collect(toList());
 
         try (QueryCursor<Cache.Entry<Integer, DefectCompacted>> qry = cache.query(new ScanQuery<Integer, DefectCompacted>()
             .setFilter((k, v) -> v.resolvedByUsernameId() < 1 && v.tcSrvId() == srvId))) {
@@ -175,6 +177,34 @@ public class DefectsStorage {
         cache().put(defect.id(), defect);
     }
 
+    public void checkIfPossibleToRemove(Map<Integer, List<Integer>> oldBuildsTeamCityAndBuildIds) {
+        cache().forEach(entry -> {
+            DefectCompacted defect = entry.getValue();
+
+            List<Integer> buildIdsToRemove = oldBuildsTeamCityAndBuildIds.get(defect.tcSrvId());
+
+            if (defect.resolvedTs() == -1 && buildIdsToRemove != null) {
+                defect.buildsInvolved().values().stream()
+                    .map(build -> build.build().id())
+                    .forEach(buildIdsToRemove::remove);
+            }
+        });
+    }
+
+    public void removeOldDefects(Map<Integer, List<Integer>> oldBuildsTeamCityAndBuildIds) {
+        cache().forEach(entry -> {
+            DefectCompacted defect = entry.getValue();
+
+            Optional.ofNullable(oldBuildsTeamCityAndBuildIds.get(defect.tcSrvId())).ifPresent(buildIdsToRemove -> {
+                List<Integer> defectBuildIds = defect.buildsInvolved().values().stream()
+                    .map(build -> build.build().id()).collect(toList());
+
+                if (defectBuildIds.stream().anyMatch(buildIdsToRemove::contains))
+                    cache().remove(entry.getKey());
+            });
+        });
+    }
+
     public void removeOldDefects(long thresholdDate, int numOfItemsToDel) {
         IgniteCache<Integer, BinaryObject> cacheWithBinary = cache().withKeepBinary();
 
diff --git a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/issue/IIssuesStorage.java b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/issue/IIssuesStorage.java
index 3cd3da9..8858a2b 100644
--- a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/issue/IIssuesStorage.java
+++ b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/issue/IIssuesStorage.java
@@ -17,6 +17,8 @@
 
 package org.apache.ignite.tcbot.engine.issue;
 
+import java.util.List;
+import java.util.Map;
 import java.util.stream.Stream;
 import javax.annotation.Nullable;
 import org.apache.ignite.ci.issue.Issue;
@@ -33,6 +35,8 @@ public interface IIssuesStorage {
 
     public void saveIssue(Issue issue);
 
+    public Issue getIssue(IssueKey issueKey);
+
     public Stream<Issue> allIssues();
 
     /**
@@ -46,5 +50,7 @@ public interface IIssuesStorage {
 
     public void saveIssueSubscribersStat(IssueKey key, int cntSrvAllowed, int cntSubscribed, int cntTagsFilterPassed);
 
+    public void removeOldIssues(Map<Integer, List<Integer>> oldBuildsTeamCityAndBuildIds);
+
     public void removeOldIssues(long thresholdDate, int numOfItemsToDel);
 }
diff --git a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/issue/IssuesStorage.java b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/issue/IssuesStorage.java
index 554691f..53251f7 100644
--- a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/issue/IssuesStorage.java
+++ b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/issue/IssuesStorage.java
@@ -18,6 +18,9 @@
 package org.apache.ignite.tcbot.engine.issue;
 
 import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
 import javax.annotation.Nullable;
@@ -124,10 +127,28 @@ public class IssuesStorage implements IIssuesStorage {
     }
 
     /** {@inheritDoc} */
+    @Override public Issue getIssue(IssueKey issueKey) {
+        return cache().get(issueKey);
+    }
+
+    /** {@inheritDoc} */
     @Override public Stream<Issue> allIssues() {
         return StreamSupport.stream(cache().spliterator(), false).map(Cache.Entry::getValue);
     }
 
+    public void removeOldIssues(Map<Integer, List<Integer>> oldBuildsTeamCityAndBuildIds) {
+        cache().forEach(entry -> {
+            IssueKey issueKey = entry.getKey();
+
+            Optional.ofNullable(oldBuildsTeamCityAndBuildIds.get(Math.abs(issueKey.getServer().hashCode())))
+                .ifPresent(buildIdsToRemove -> {
+                        if (buildIdsToRemove.contains(issueKey.getBuildId()))
+                            cache().remove(issueKey);
+                    }
+                );
+        });
+    }
+
     public void removeOldIssues(long thresholdDate, int numOfItemsToDel) {
         IgniteCache<BinaryObject, BinaryObject> cacheWithBinary = cache().withKeepBinary();
 
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/buildcondition/BuildConditionDao.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/buildcondition/BuildConditionDao.java
index 476c881..de66f7c 100644
--- a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/buildcondition/BuildConditionDao.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/buildcondition/BuildConditionDao.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.ci.teamcity.ignited.buildcondition;
 
+import java.util.Set;
 import javax.inject.Inject;
 import javax.inject.Provider;
 import org.apache.ignite.Ignite;
@@ -79,4 +80,8 @@ public class BuildConditionDao {
     public void remove(long key) {
         buildsCache.remove(key);
     }
+
+    public void removeAll(Set<Long> keys) {
+        buildsCache.removeAll(keys);
+    }
 }
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/build/FatBuildDao.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/build/FatBuildDao.java
index 425e31b..7a0c4c7 100644
--- a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/build/FatBuildDao.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/build/FatBuildDao.java
@@ -419,7 +419,7 @@ public class FatBuildDao {
         }
     }
 
-    public List<Long> getOldBuilds(long thresholdDate, int numOfItemsToDel) {
+    public Set<Long> getOldBuilds(long thresholdDate, int numOfItemsToDel) {
         IgniteCache<Long, BinaryObject> cacheWithBinary = buildsCache.withKeepBinary();
 
         ScanQuery<Long, BinaryObject> scan = new ScanQuery<>((key, fatBuild) -> {
@@ -433,7 +433,7 @@ public class FatBuildDao {
             }
         );
 
-        List<Long> oldBuildsKeys = new ArrayList<>(numOfItemsToDel);
+        Set<Long> oldBuildsKeys = new HashSet<>(numOfItemsToDel);
 
         for (Cache.Entry<Long, BinaryObject> entry : cacheWithBinary.query(scan)) {
             if (numOfItemsToDel > 0) {
@@ -450,6 +450,10 @@ public class FatBuildDao {
         buildsCache.remove(key);
     }
 
+    public void removeAll(Set<Long> keys) {
+        buildsCache.removeAll(keys);
+    }
+
     /**
      * Returns Build Id if current build is missing in the cache.
      */
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/BuildLogCheckResultDao.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/BuildLogCheckResultDao.java
index e1db997..7df8d2a 100644
--- a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/BuildLogCheckResultDao.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/BuildLogCheckResultDao.java
@@ -16,6 +16,7 @@
  */
 package org.apache.ignite.tcignited.buildlog;
 
+import java.util.Set;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.configuration.CacheConfiguration;
@@ -62,4 +63,8 @@ public class BuildLogCheckResultDao {
     public void remove(long key) {
         logsCache.remove(key);
     }
+
+    public void removeAll(Set<Long> keys) {
+        logsCache.removeAll(keys);
+    }
 }
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildref/BuildRefDao.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildref/BuildRefDao.java
index 715c3b5..b8fbd1e 100644
--- a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildref/BuildRefDao.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildref/BuildRefDao.java
@@ -368,4 +368,8 @@ public class BuildRefDao {
     public void remove(long key) {
         buildRefsCache.remove(key);
     }
+
+    public void removeAll(Set<Long> keys) {
+        buildRefsCache.removeAll(keys);
+    }
 }
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/history/BuildStartTimeStorage.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/history/BuildStartTimeStorage.java
index f4c344c..dc919f6 100644
--- a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/history/BuildStartTimeStorage.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/history/BuildStartTimeStorage.java
@@ -190,4 +190,8 @@ public class BuildStartTimeStorage {
         buildStartTime.remove(key);
     }
 
+    public void removeAll(Set<Long> keys) {
+        buildStartTime.removeAll(keys);
+    }
+
 }
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/history/SuiteInvocationHistoryDao.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/history/SuiteInvocationHistoryDao.java
index 96c10c4..06cbb2b 100644
--- a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/history/SuiteInvocationHistoryDao.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/history/SuiteInvocationHistoryDao.java
@@ -19,6 +19,7 @@ package org.apache.ignite.tcignited.history;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
 import javax.cache.Cache;
 import javax.cache.expiry.AccessedExpiryPolicy;
 import javax.cache.expiry.Duration;
@@ -95,4 +96,8 @@ public class SuiteInvocationHistoryDao {
     public void remove(long key) {
         suiteHist.remove(key);
     }
+
+    public void removeAll(Set<Long> keys) {
+        suiteHist.removeAll(keys);
+    }
 }