You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by dp...@apache.org on 2019/06/02 15:12:30 UTC

[ignite-teamcity-bot] branch master updated: IGNITE-10989: Finalized refactoring and removed REST data persistent caches

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

dpavlov 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 c147340  IGNITE-10989: Finalized refactoring and removed REST data persistent caches
c147340 is described below

commit c14734010b720fbde51d457f127ce7efb33e9325
Author: Dmitriy Pavlov <dp...@apache.org>
AuthorDate: Sun Jun 2 18:12:16 2019 +0300

    IGNITE-10989: Finalized refactoring and removed REST data persistent caches
---
 build.gradle                                       |   4 +-
 tcbot-teamcity/header.txt => header.txt            |   0
 ignite-tc-helper-web/header.txt                    |  14 --
 .../apache/ignite/ci/IgnitePersistentTeamcity.java | 265 ---------------------
 .../apache/ignite/ci/analysis/MultBuildRunCtx.java |  51 ++--
 .../ignite/ci/analysis/SingleBuildRunCtx.java      |  22 +-
 .../java/org/apache/ignite/ci/db/DbMigrations.java | 247 ++++++-------------
 .../java/org/apache/ignite/ci/db/Ignite1Init.java  |   9 +
 .../org/apache/ignite/ci/di/IgniteTcBotModule.java |   9 +-
 .../ignite/ci/runners/RemoteClientTmpHelper.java   |   6 +-
 .../ignite/ci/tcbot/chain/BuildChainProcessor.java | 112 ++-------
 .../ignite/ci/tcbot/chain/PrChainsProcessor.java   |   2 +-
 .../ignite/ci/tcbot/issue/IssueDetector.java       |   2 +-
 .../ci/teamcity/restcached/ITcServerProvider.java  |  33 ---
 .../restcached/InitializingServerFactory.java      |  49 ----
 .../ci/teamcity/restcached/TcRestCachedModule.java |  51 ----
 .../restcached/TcServerCachingProvider.java        |  68 ------
 .../apache/ignite/ci/web/TcApplicationResCfg.java  |   4 +-
 .../org/apache/ignite/ci/web/model/Version.java    |   2 +-
 .../ci/web/model/current/SuiteCurrentStatus.java   |   6 +-
 .../ignite/ci/web/model/current/TestFailure.java   |   4 +-
 .../org/apache/ignite/ci/web/rest/GetBuildLog.java |  24 +-
 .../ignite/ci/web/rest/GetChainResultsAsHtml.java  |   1 -
 ...on.java => ServiceStartingExceptionMapper.java} |  17 +-
 .../ServiceUnauthorizedExceptionMapper.java        |   2 -
 .../rest/tracked/GetTrackedBranchTestResults.java  |   2 +-
 .../org/apache/ignite/ci/di/DiContextTest.java     |   2 -
 .../ci/tcbot/chain/BuildChainProcessorTest.java    |   5 +-
 .../ci/tcbot/chain/MockBasedTcBotModule.java       |   4 +-
 .../ignite/ci/tcbot/issue/IssueDetectorTest.java   |   2 +-
 .../ci/teamcity/ignited/BuildKeyUnitTest.java      |   2 +-
 .../IgnitedTcInMemoryIntegrationTest.java          |  76 +++---
 jetty-launcher/header.txt                          |  14 --
 tcbot-common/header.txt                            |  14 --
 .../tcbot/common/exeption/ExceptionUtil.java       |  16 +-
 .../common/exeption/ServicesStartingException.java |  20 +-
 .../apache/ignite/tcbot/common/util/HttpUtil.java  |  12 +-
 .../ci/tcbot/common/StringFieldCompacted.java      |  25 +-
 .../ci/teamcity/ignited/IgniteStringCompactor.java |  18 +-
 .../tcbot/persistence/TcBotPersistenceModule.java  |  18 +-
 tcbot-server/README.md                             |   1 +
 tcbot-server/header.txt                            |  14 --
 tcbot-teamcity-ignited/README.md                   |   5 +
 .../teamcity/ignited/buildtype/BuildTypeSync.java  |   3 +-
 .../ci/teamcity/ignited/change/ChangeDao.java      |   3 -
 .../ignited/fatbuild/ProactiveFatBuildSync.java    |   4 +-
 .../ci/teamcity/ignited/runhist/RunHistKey.java    |   2 +
 .../apache/ignite/tcignited/ITeamcityIgnited.java  |   3 +
 .../TcIgnitedCachingProvider.java                  |  23 +-
 .../ignited => tcignited}/TeamcityIgnitedImpl.java |  28 ++-
 .../TeamcityIgnitedModule.java                     |  20 +-
 .../tcignited/buildlog/BuildLogCheckResultDao.java |  61 +++++
 .../tcignited/buildlog/BuildLogProcessor.java      | 138 +++++++++++
 .../buildlog/BuildLogProcessorModule.java          |  12 +-
 .../tcignited/buildlog}/BuildLogStreamChecker.java |   9 +-
 .../tcignited/buildlog/IBuildLogProcessor.java     |  16 +-
 .../ignite/tcignited/buildlog}/ILineHandler.java   |   2 +-
 .../ignite/tcignited/buildlog/ILogCheckResult.java |  23 +-
 .../tcignited/buildlog}/ILogProductSpecific.java   |   2 +-
 .../tcignited/buildlog/ITestLogCheckResult.java    |  19 +-
 .../buildlog/LogCheckResultCompacted.java          |  85 ++++---
 .../ignite/tcignited/buildlog}/LogCheckTask.java   |  34 +--
 .../tcignited/buildlog}/LogIgniteSpecific.java     |   2 +-
 .../ignite/tcignited/buildlog}/LogMsgToWarn.java   |   2 +-
 .../ignite/tcignited/buildlog}/LogsAnalyzer.java   |   2 +-
 .../buildlog/TestLogCheckResultCompacted.java      |  34 +--
 .../ignite/tcignited/buildlog}/TestLogHandler.java |  88 ++-----
 .../buildlog}/ThreadDumpInMemoryHandler.java       |   3 +-
 .../buildref/BuildRefDao.java                      |   2 +-
 .../buildref/BuildRefSync.java                     |   2 +-
 .../history}/RunHistCompactedDao.java              |   9 +-
 .../runhist => tcignited/history}/RunHistSync.java |   7 +-
 tcbot-teamcity/README.md                           |   5 +-
 .../org/apache/ignite/tcservice/ITeamcityConn.java |  15 ++
 .../tcservice/TeamcityServiceConnection.java       |  59 +++--
 75 files changed, 782 insertions(+), 1189 deletions(-)

diff --git a/build.gradle b/build.gradle
index 79edd89..edfb1ff 100644
--- a/build.gradle
+++ b/build.gradle
@@ -31,8 +31,8 @@ subprojects {
     apply plugin: "com.github.hierynomus.license-base"
     apply plugin: "com.github.hierynomus.license-report"
 
-
-    license.header = file('header.txt')
+    //for subprojects header can be found in top-level project.
+    license.header = file('../header.txt')
 
     license.exclude("*.xml");
 }
diff --git a/tcbot-teamcity/header.txt b/header.txt
similarity index 100%
rename from tcbot-teamcity/header.txt
rename to header.txt
diff --git a/ignite-tc-helper-web/header.txt b/ignite-tc-helper-web/header.txt
deleted file mode 100644
index a9ac967..0000000
--- a/ignite-tc-helper-web/header.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-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.
\ No newline at end of file
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgnitePersistentTeamcity.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgnitePersistentTeamcity.java
deleted file mode 100644
index bf7e077..0000000
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgnitePersistentTeamcity.java
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * 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.ci;
-
-import java.io.File;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedSet;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.Function;
-import javax.annotation.Nullable;
-import javax.inject.Inject;
-import org.apache.ignite.Ignite;
-import org.apache.ignite.IgniteCache;
-import org.apache.ignite.ci.analysis.LogCheckResult;
-import org.apache.ignite.ci.db.DbMigrations;
-import org.apache.ignite.tcbot.common.interceptor.AutoProfiling;
-import org.apache.ignite.tcbot.common.conf.ITcServerConfig;
-import org.apache.ignite.tcbot.persistence.CacheConfigs;
-import org.apache.ignite.tcbot.persistence.IVersionedEntity;
-import org.apache.ignite.tcservice.ITeamcity;
-import org.apache.ignite.tcservice.model.agent.Agent;
-import org.apache.ignite.tcservice.model.changes.Change;
-import org.apache.ignite.tcservice.model.changes.ChangesList;
-import org.apache.ignite.tcservice.model.conf.BuildType;
-import org.apache.ignite.tcservice.model.conf.Project;
-import org.apache.ignite.tcservice.model.conf.bt.BuildTypeFull;
-import org.apache.ignite.tcservice.model.hist.BuildRef;
-import org.apache.ignite.tcservice.model.mute.MuteInfo;
-import org.apache.ignite.tcservice.model.result.Build;
-import org.apache.ignite.tcservice.model.result.problems.ProblemOccurrences;
-import org.apache.ignite.tcservice.model.result.stat.Statistics;
-import org.apache.ignite.tcservice.model.result.tests.TestOccurrencesFull;
-import org.apache.ignite.tcservice.model.user.User;
-import org.apache.ignite.tcbot.common.util.ObjectInterner;
-import org.apache.ignite.ci.web.model.hist.VisasHistoryStorage;
-import org.jetbrains.annotations.NotNull;
-
-/**
- * Apache Ignite based cache over teamcity responses (REST caches).
- *
- * Cache is now overloaded with data, Compacted
- */
-@Deprecated
-public class IgnitePersistentTeamcity implements IAnalyticsEnabledTeamcity, ITeamcity, ITcAnalytics {
-    //V2 caches, 32 parts (V1 caches were 1024 parts)
-    @Deprecated
-    private static final String LOG_CHECK_RESULT = "logCheckResult";
-
-    @Inject
-    private Ignite ignite;
-
-    /** */
-    @Inject
-    private VisasHistoryStorage visasHistStorage;
-
-    /**
-     * Teamcity
-     */
-    private ITeamcity teamcity;
-
-    @Nullable
-    private String serverId;
-
-    @Override public void init(ITeamcity conn) {
-        this.teamcity = conn;
-        this.serverId = conn.serverCode();
-
-        DbMigrations migrations = new DbMigrations(ignite, conn.serverCode());
-
-        migrations.dataMigration(visasHistStorage.visas());
-    }
-
-    /** {@inheritDoc} */
-    @Override public User getUserByUsername(String username) {
-        return teamcity.getUserByUsername(username);
-    }
-
-    /**
-     * Creates atomic cache with 32 parts.
-     * @param name Cache name.
-     */
-    private <K, V> IgniteCache<K, V> getOrCreateCacheV2(String name) {
-        final IgniteCache<K, V> cache = ignite.getOrCreateCache(CacheConfigs.getCacheV2Config(name));
-
-        cache.enableStatistics(true);
-
-        return cache;
-    }
-
-    /** {@inheritDoc} */
-    @AutoProfiling
-    @Override public List<BuildType> getBuildTypes(String projectId) {
-        return teamcity.getBuildTypes(projectId);
-    }
-
-    /** {@inheritDoc} */
-    @Override public String serverCode() {
-        return serverId;
-    }
-
-    /** {@inheritDoc} */
-    @Override public ITcServerConfig config() {
-        return teamcity.config();
-    }
-
-    @NotNull private String ignCacheNme(String cache) {
-        return ignCacheNme(cache, serverId);
-    }
-
-    @NotNull public static String ignCacheNme(String cache, String srvId) {
-        return srvId + "." + cache;
-    }
-
-    /** {@inheritDoc} */
-    @Override public Build getBuild(int buildId) {
-        return teamcity.getBuild(buildId);
-    }
-
-    private IgniteCache<Integer, LogCheckResult> logCheckResultCache() {
-        return getOrCreateCacheV2(ignCacheNme(LOG_CHECK_RESULT));
-    }
-
-    /** {@inheritDoc} */
-    @Override public CompletableFuture<File> downloadBuildLogZip(int buildId) {
-        return teamcity.downloadBuildLogZip(buildId);
-    }
-
-    /** {@inheritDoc} */
-//    @Override public CompletableFuture<LogCheckResult> analyzeBuildLog(Integer buildId, SingleBuildRunCtx ctx) {
-//        return loadFutureIfAbsentVers(logCheckResultCache(), buildId,
-//            k -> teamcity.analyzeBuildLog(buildId, ctx));
-//    }
-
-
-    @AutoProfiling
-    @Override public String getThreadDumpCached(Integer buildId) {
-        IgniteCache<Integer, LogCheckResult> entries = logCheckResultCache();
-
-        LogCheckResult logCheckRes = entries.get(buildId);
-
-        if (logCheckRes == null)
-            return null;
-
-        int fields = ObjectInterner.internFields(logCheckRes);
-
-        return logCheckRes.getLastThreadDump();
-    }
-
-
-    /**
-     * @param cache
-     * @param key
-     * @param submitFunction caching of already submitted computations should be done by this function.
-     * @param <K>
-     * @param <V>
-     * @return
-     */
-    public <K, V extends IVersionedEntity> CompletableFuture<V> loadFutureIfAbsentVers(IgniteCache<K, V> cache,
-                                                                                       K key,
-                                                                                       Function<K, CompletableFuture<V>> submitFunction) {
-        @Nullable final V persistedVal = cache.get(key);
-
-        if (persistedVal != null && !persistedVal.isOutdatedEntityVersion()) {
-            int fields = ObjectInterner.internFields(persistedVal);
-
-            return CompletableFuture.completedFuture(persistedVal);
-        }
-
-        CompletableFuture<V> apply = submitFunction.apply(key);
-
-        return apply.thenApplyAsync(val -> {
-            if (val != null)
-                cache.put(key, val);
-
-            return val;
-        });
-    }
-
-    /** {@inheritDoc} */
-    @Override public void setExecutor(ExecutorService executor) {
-        this.teamcity.setExecutor(executor);
-    }
-
-    /** {@inheritDoc} */
-    @AutoProfiling
-    @Override public Build triggerBuild(String buildTypeId, @NotNull String branchName, boolean cleanRebuild,
-        boolean queueAtTop, Map<String, Object> buildParms) {
-        return teamcity.triggerBuild(buildTypeId, branchName, cleanRebuild, queueAtTop, buildParms);
-    }
-
-    /** {@inheritDoc} */
-    @Override public ProblemOccurrences getProblems(int buildId) {
-        return teamcity.getProblems(buildId);
-    }
-
-    /** {@inheritDoc} */
-    @Override public List<Project> getProjects() {
-        return teamcity.getProjects();
-    }
-
-    @Override public Statistics getStatistics(int buildId) {
-        return teamcity.getStatistics(buildId);
-    }
-
-    @Override public ChangesList getChangesList(int buildId) {
-        return teamcity.getChangesList(buildId);
-    }
-
-    @Override public Change getChange(int changeId) {
-        return teamcity.getChange(changeId);
-    }
-
-    /** {@inheritDoc} */
-    @Override public BuildTypeFull getBuildType(String buildTypeId) {
-        return teamcity.getBuildType(buildTypeId);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void setAuthToken(String tok) {
-        teamcity.setAuthToken(tok);
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean isTeamCityTokenAvailable() {
-        return teamcity.isTeamCityTokenAvailable();
-    }
-
-    /** {@inheritDoc} */
-    @Override public List<Agent> agents(boolean connected, boolean authorized) {
-        return teamcity.agents(connected, authorized);
-    }
-
-    /** {@inheritDoc} */
-    @Override public List<BuildRef> getBuildRefsPage(String fullUrl, AtomicReference<String> nextPage) {
-        return teamcity.getBuildRefsPage(fullUrl, nextPage);
-    }
-
-    /** {@inheritDoc} */
-    @Override public SortedSet<MuteInfo> getMutesPage(String buildTypeId, String fullUrl, AtomicReference<String> nextPage) {
-        return teamcity.getMutesPage(buildTypeId, fullUrl, nextPage);
-    }
-
-    /** {@inheritDoc} */
-    @Override public TestOccurrencesFull getTestsPage(int buildId, String href, boolean testDtls) {
-        return teamcity.getTestsPage(buildId, href, testDtls);
-    }
-}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/MultBuildRunCtx.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/MultBuildRunCtx.java
index 2c73d68..03fc6ad 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/MultBuildRunCtx.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/MultBuildRunCtx.java
@@ -18,33 +18,28 @@
 package org.apache.ignite.ci.analysis;
 
 import com.google.common.base.Strings;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.OptionalDouble;
-import java.util.Set;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.Future;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import javax.annotation.Nonnull;
-import org.apache.ignite.tcbot.common.conf.ITcServerConfig;
-import org.apache.ignite.tcservice.model.hist.BuildRef;
-import org.apache.ignite.tcservice.model.result.problems.ProblemOccurrence;
-import org.apache.ignite.tcservice.model.result.stat.Statistics;
-import org.apache.ignite.tcignited.history.IRunHistory;
-import org.apache.ignite.tcbot.persistence.IStringCompactor;
 import org.apache.ignite.ci.teamcity.ignited.change.ChangeCompacted;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.ProblemCompacted;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.TestCompacted;
 import org.apache.ignite.ci.util.CollectionUtil;
+import org.apache.ignite.tcbot.common.conf.ITcServerConfig;
+import org.apache.ignite.tcbot.persistence.IStringCompactor;
+import org.apache.ignite.tcignited.buildlog.ILogCheckResult;
+import org.apache.ignite.tcignited.buildlog.ITestLogCheckResult;
+import org.apache.ignite.tcignited.history.IRunHistory;
+import org.apache.ignite.tcservice.model.hist.BuildRef;
+import org.apache.ignite.tcservice.model.result.problems.ProblemOccurrence;
+import org.apache.ignite.tcservice.model.result.stat.Statistics;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import javax.annotation.Nonnull;
+import java.util.*;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Future;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
 /**
  * Run configuration execution results loaded from different API URLs. Includes tests and problem occurrences; if logs
  * processing is done also contains last started test
@@ -88,7 +83,7 @@ public class MultBuildRunCtx implements ISuiteResults {
         return buildsStream().map(SingleBuildRunCtx::getBuildIdIfHasThreadDump).filter(Objects::nonNull);
     }
 
-    public Stream<Map<String, TestLogCheckResult>> getLogsCheckResults() {
+    public Stream<Map<String, ITestLogCheckResult>> getLogsCheckResults() {
         return buildsStream().map(SingleBuildRunCtx::getTestLogCheckResult).filter(Objects::nonNull);
     }
 
@@ -238,11 +233,11 @@ public class MultBuildRunCtx implements ISuiteResults {
     }
 
     public long getJavaLevelDeadlocksCount() {
-        List<LogCheckResult> collect = getLogChecksIfFinished().collect(Collectors.toList());
+        List<ILogCheckResult> collect = getLogChecksIfFinished().collect(Collectors.toList());
 
-        return collect.stream().map(LogCheckResult::getCustomProblems)
-            .filter(set -> set.contains(ProblemOccurrence.JAVA_LEVEL_DEADLOCK))
-            .count();
+        return collect.stream().map(r -> r.getCustomProblems(compactor))
+                .filter(set -> set.contains(ProblemOccurrence.JAVA_LEVEL_DEADLOCK))
+                .count();
     }
 
     public long getCancelledBuildsCount() {
@@ -264,15 +259,13 @@ public class MultBuildRunCtx implements ISuiteResults {
         Map<String, Long> logSizeBytes = new HashMap<>();
 
         getLogsCheckResults()
-
             .forEach(map -> {
                 map.forEach(
                     (testName, logCheckResult) -> {
                         //todo may be it is better to find   avg
                         long bytes = (long)logCheckResult.getLogSizeBytes();
                         if (bytes > 1024 * 1024) {
-                            logSizeBytes.merge(testName, bytes, (a, b) ->
-                                Math.max(a, b));
+                            logSizeBytes.merge(testName, bytes, Math::max);
                         }
                     }
                 );
@@ -471,7 +464,7 @@ public class MultBuildRunCtx implements ISuiteResults {
         return buildsStream().flatMap(SingleBuildRunCtx::getAllTestNames).collect(Collectors.toSet());
     }
 
-    public Stream<LogCheckResult> getLogChecksIfFinished() {
+    public Stream<ILogCheckResult> getLogChecksIfFinished() {
         return buildsStream().map(SingleBuildRunCtx::getLogCheckIfFinished).filter(Objects::nonNull);
     }
 
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/SingleBuildRunCtx.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/SingleBuildRunCtx.java
index 8cbc24d..683072f 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/SingleBuildRunCtx.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/SingleBuildRunCtx.java
@@ -33,6 +33,8 @@ import java.util.regex.Pattern;
 import java.util.stream.Stream;
 import javax.annotation.Nonnull;
 
+import org.apache.ignite.tcignited.buildlog.ILogCheckResult;
+import org.apache.ignite.tcignited.buildlog.ITestLogCheckResult;
 import org.apache.ignite.tcservice.ITeamcity;
 import org.apache.ignite.tcbot.common.conf.IBuildParameterSpec;
 import org.apache.ignite.tcbot.common.conf.ITcServerConfig;
@@ -60,7 +62,7 @@ public class SingleBuildRunCtx implements ISuiteResults {
     private List<ChangeCompacted> changes = new ArrayList<>();
 
     /** Logger check result future. */
-    private CompletableFuture<LogCheckResult> logCheckResFut;
+    private CompletableFuture<ILogCheckResult> logCheckResFut;
 
     /** Tags found from filtering-enabled parameters. */
     private Set<String> tags = new HashSet<>();
@@ -125,20 +127,20 @@ public class SingleBuildRunCtx implements ISuiteResults {
         return getProblemsStream().anyMatch(p -> p.isBuildFailureOnMessage(compactor));
     }
 
-    public void setLogCheckResFut(CompletableFuture<LogCheckResult> logCheckResFut) {
+    public void setLogCheckResFut(CompletableFuture<ILogCheckResult> logCheckResFut) {
         this.logCheckResFut = logCheckResFut;
     }
 
     @Nullable public String getCriticalFailLastStartedTest() {
-        LogCheckResult logCheckRes = getLogCheckIfFinished();
+        ILogCheckResult logCheckRes = getLogCheckIfFinished();
         if (logCheckRes == null)
             return null;
 
-        return logCheckRes.getLastStartedTest();
+        return logCheckRes.getLastStartedTest(compactor);
     }
 
-    @Nullable public Map<String, TestLogCheckResult> getTestLogCheckResult() {
-        LogCheckResult logCheckRes = getLogCheckIfFinished();
+    @Nullable public Map<String, ITestLogCheckResult> getTestLogCheckResult() {
+        ILogCheckResult logCheckRes = getLogCheckIfFinished();
 
         if (logCheckRes == null)
             return null;
@@ -147,22 +149,22 @@ public class SingleBuildRunCtx implements ISuiteResults {
     }
 
     @Nullable public Integer getBuildIdIfHasThreadDump() {
-        LogCheckResult logCheckRes = getLogCheckIfFinished();
+        ILogCheckResult logCheckRes = getLogCheckIfFinished();
 
-        if (logCheckRes == null)
+        if (logCheckRes == null || !logCheckRes.hasThreadDump())
             return null;
 
         return !Strings.isNullOrEmpty(logCheckRes.getLastThreadDump()) ? buildId() : null;
     }
 
-    @Nullable public LogCheckResult getLogCheckIfFinished() {
+    @Nullable public ILogCheckResult getLogCheckIfFinished() {
         if (logCheckResFut == null)
             return null;
 
         if (!logCheckResFut.isDone() || logCheckResFut.isCancelled())
             return null;
 
-        LogCheckResult logCheckRes = FutureUtil.getResultSilent(logCheckResFut);
+        ILogCheckResult logCheckRes = FutureUtil.getResultSilent(logCheckResFut);
 
         if (logCheckRes == null)
             return null;
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/DbMigrations.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/DbMigrations.java
index a907529..628ff40 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/DbMigrations.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/DbMigrations.java
@@ -17,33 +17,26 @@
 
 package org.apache.ignite.ci.db;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import javax.cache.Cache;
+import com.google.common.collect.Sets;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.IgniteDataStreamer;
-import org.apache.ignite.binary.BinaryObject;
 import org.apache.ignite.cache.CacheAtomicityMode;
 import org.apache.ignite.cache.CacheMode;
-import org.apache.ignite.ci.IgnitePersistentTeamcity;
 import org.apache.ignite.ci.issue.Issue;
 import org.apache.ignite.ci.issue.IssueKey;
 import org.apache.ignite.ci.issue.IssuesStorage;
-import org.apache.ignite.ci.observer.CompactBuildsInfo;
-import org.apache.ignite.tcservice.model.result.Build;
-import org.apache.ignite.ci.web.model.CompactContributionKey;
-import org.apache.ignite.ci.web.model.CompactVisa;
-import org.apache.ignite.ci.web.model.CompactVisaRequest;
-import org.apache.ignite.ci.web.model.hist.VisasHistoryStorage;
 import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.tcservice.model.result.Build;
+import org.jetbrains.annotations.NotNull;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.cache.Cache;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
 /**
  * Migrations to be applied to each TC related caches.
  */
@@ -93,6 +86,7 @@ public class DbMigrations {
     /** */
     @Deprecated
     public static final String COMPACT_VISAS_HISTORY_CACHE_NAME = "compactVisasHistoryCache";
+    public static final String DONE_MIGRATION_PREFIX = "apache";
 
     interface Old {
         String TEST_FULL = "testFull";
@@ -126,90 +120,34 @@ public class DbMigrations {
         String BUILDS_FAILURE_RUN_STAT = "buildsFailureRunStat";
 
         String TESTS_RUN_STAT = "testsRunStat";
+
+        //V2 caches, 32 parts (V1 caches were 1024 parts)
+        String LOG_CHECK_RESULT = "logCheckResult";
     }
 
     private final Ignite ignite;
-    private final String serverId;
+    private final Set<String> serverIds
+            = Sets.newHashSet("apache", "public",
+            "gg", "private", "gridgain", "gg4apache", "null");
+
     private IgniteCache<String, Object> doneMigrations;
 
-    public DbMigrations(Ignite ignite, String srvId) {
+    public DbMigrations(Ignite ignite ) {
         this.ignite = ignite;
-        this.serverId = srvId;
     }
 
-    public void dataMigration(Cache<CompactContributionKey, List<CompactVisaRequest>> visasCache) {
-
+    public String dataMigration() {
         doneMigrations = doneMigrationsCache();
 
-        applyMigration(COMPACT_VISAS_HISTORY_CACHE_NAME + "-to-" + VisasHistoryStorage.VISAS_CACHE_NAME, () -> {
-            IgniteCache<Object, Object> cache = ignite.cache(COMPACT_VISAS_HISTORY_CACHE_NAME);
-            if (cache == null) {
-                System.err.println("Cache not found " + COMPACT_VISAS_HISTORY_CACHE_NAME);
-
-                return;
-            }
-
-            IgniteCache<Object, Object> oldVisasCache = cache.withKeepBinary();
-
-            if (Objects.isNull(oldVisasCache)) {
-                System.out.println("Old cache [" + COMPACT_VISAS_HISTORY_CACHE_NAME + "] not found");
-
-                return;
-            }
-
-            int size = oldVisasCache.size();
-
-            int i = 0;
+        int sizeBefore = doneMigrations.size();
 
-            for (IgniteCache.Entry<Object, Object> entry : oldVisasCache) {
-                System.out.println("Migrating entry " + i++ + " from " + size);
-
-                Collection<BinaryObject> binVisaReqs = null;
-                Object val = entry.getValue();
-                if (val instanceof List)
-                    binVisaReqs = (Collection<BinaryObject>)val;
-                else {
-                    if (val instanceof Map)
-                        binVisaReqs = ((Map<?, BinaryObject>)val).values();
-                }
-
-                if (binVisaReqs == null)
-                    continue;
-
-                List<CompactVisaRequest> compactVisaReqs = new ArrayList<>();
-
-                CompactContributionKey compactKey = ((BinaryObject)entry.getKey()).deserialize();
-
-                for (BinaryObject binVisaReq : binVisaReqs) {
-                    CompactBuildsInfo compactInfo = ((BinaryObject)binVisaReq.field("compactInfo")).deserialize();
-
-                    CompactVisa compactVisa = ((BinaryObject)binVisaReq.field("compactVisa")).deserialize();
-
-                    compactVisaReqs.add(new CompactVisaRequest(compactVisa, compactInfo, false));
-                }
-
-                visasCache.put(compactKey, compactVisaReqs);
-            }
-        });
+        applyDestroyCacheMigration(COMPACT_VISAS_HISTORY_CACHE_NAME);
 
         applyMigration("InitialFillLatestRunsV3", () -> {
         });
 
-        applyMigration("Remove-" + RUN_STAT_CACHE, () -> {
-            IgniteCache<String, Build> oldBuilds = ignite.getOrCreateCache(ignCacheNme(RUN_STAT_CACHE));
-
-            oldBuilds.clear();
-
-            oldBuilds.destroy();
-        });
-
         applyRemoveCache(Old.CURRENT_PR_FAILURES);
 
-        applyDestroyIgnCacheMigration(TEST_OCCURRENCE_FULL);
-
-        applyDestroyIgnCacheMigration(PROBLEMS);
-
-        applyDestroyIgnCacheMigration(FINISHED_BUILDS_INCLUDE_FAILED);
 
         Cache<IssueKey, Issue> issuesCache = IssuesStorage.botDetectedIssuesCache(ignite);
         applyMigration(ISSUES + "-to-" + issuesCache.getName() + "V2", () -> {
@@ -241,36 +179,13 @@ public class DbMigrations {
             }
         });
 
-        applyDestroyIgnCacheMigration(RUNNING_BUILDS);
-
-        applyDestroyIgnCacheMigration(BUILD_QUEUE);
-
-        applyDestroyIgnCacheMigration(FINISHED_BUILDS_INCLUDE_FAILED);
-        applyDestroyIgnCacheMigration(TEST_OCCURRENCE_FULL);
-
-        applyDestroyIgnCacheMigration(Old.TESTS);
-        applyDestroyIgnCacheMigration(STAT);
-        applyDestroyIgnCacheMigration(BUILD_STATISTICS);
         applyDestroyCacheMigration(BUILD_CONDITIONS_CACHE_NAME, BUILD_CONDITIONS_CACHE_NAME);
         applyDestroyCacheMigration(TEAMCITY_BUILD_CACHE_NAME_OLD, TEAMCITY_BUILD_CACHE_NAME_OLD);
 
-        applyDestroyIgnCacheMigration(Old.CHANGE_INFO_FULL);
-        applyDestroyIgnCacheMigration(Old.CHANGES_LIST);
 
-        applyDestroyIgnCacheMigration(FINISHED_BUILDS);
-        applyDestroyIgnCacheMigration(BUILD_HIST_FINISHED);
-        applyDestroyIgnCacheMigration(BUILD_HIST_FINISHED_OR_FAILED);
 
         applyDestroyCacheMigration(COMPACT_VISAS_HISTORY_CACHE_NAME, COMPACT_VISAS_HISTORY_CACHE_NAME);
 
-        applyDestroyIgnCacheMigration(Old.BUILD_PROBLEMS);
-        applyDestroyIgnCacheMigration(Old.TEST_FULL);
-
-        applyDestroyIgnCacheMigration(Old.CONFIGURATIONS);
-        applyDestroyIgnCacheMigration(Old.TESTS_OCCURRENCES);
-        applyDestroyIgnCacheMigration(Old.TEST_REFS);
-
-        applyDestroyIgnCacheMigration(Old.ISSUES_USAGES_LIST);
 
         applyDestroyCacheMigration(Old.SUITE_HIST_CACHE_NAME);
         applyDestroyCacheMigration(Old.BUILD_START_TIME_CACHE_NAME);
@@ -279,88 +194,83 @@ public class DbMigrations {
         applyDestroyCacheMigration(Old.BUILD_START_TIME_CACHE_NAME);
         applyDestroyCacheMigration(Old.BUILD_START_TIME_CACHE_NAME2);
 
-        applyDestroyIgnCacheMigration(Old.CALCULATED_STATISTIC);
-        applyDestroyIgnCacheMigration(Old.BUILDS);
-        applyDestroyIgnCacheMigration(Old.BUILD_RESULTS);
-        applyDestroyIgnCacheMigration(Old.BUILDS_FAILURE_RUN_STAT);
-        applyDestroyIgnCacheMigration(Old.TESTS_RUN_STAT);
-    }
+        for (String srvId : serverIds) {
+            if(!DONE_MIGRATION_PREFIX.equals(srvId))
+                applyDestroyIgnCacheMigration(DONE_MIGRATIONS, srvId);
 
-    private void applyDestroyIgnCacheMigration(String cacheName) {
-        String ignCacheNme = ignCacheNme(cacheName);
-        applyDestroyCacheMigration(cacheName, ignCacheNme);
-    }
+            applyMigration("Remove-" + RUN_STAT_CACHE, () -> {
+                IgniteCache<String, Build> oldBuilds = ignite.getOrCreateCache(ignCacheNme(RUN_STAT_CACHE, srvId));
 
-    private void applyDestroyCacheMigration(String cacheNme) {
-        applyDestroyCacheMigration(cacheNme, cacheNme);
-    }
+                oldBuilds.clear();
 
-    private void applyDestroyCacheMigration(String dispCacheName, String cacheNme) {
-        applyMigration("destroy-" + dispCacheName, () -> {
-            IgniteCache<Object, Object> cache = ignite.cache(cacheNme);
+                oldBuilds.destroy();
+            });
 
-            if (cache == null) {
-                System.err.println("cache [" + cacheNme + "] not found");
+            applyDestroyIgnCacheMigration(TEST_OCCURRENCE_FULL, srvId);
 
-                return;
-            }
+            applyDestroyIgnCacheMigration(PROBLEMS, srvId);
 
-            cache.destroy();
-        });
-    }
+            applyDestroyIgnCacheMigration(FINISHED_BUILDS_INCLUDE_FAILED, srvId);
+            applyDestroyIgnCacheMigration(RUNNING_BUILDS, srvId);
 
-    private <K, V> void applyV1toV2Migration(String full, Cache<K, V> cache) {
-        applyMigration(full + "-to-" + cache.getName() + "V2", () -> {
-            v1tov2cacheMigrate(full, cache);
-        });
-    }
+            applyDestroyIgnCacheMigration(BUILD_QUEUE, srvId);
 
-    private <K, V> IgniteCache<K, V> getOrCreateIgnCacheV1(String name) {
-        return ignite.getOrCreateCache(ignCacheNme(name));
-    }
+            applyDestroyIgnCacheMigration(FINISHED_BUILDS_INCLUDE_FAILED, srvId);
+            applyDestroyIgnCacheMigration(TEST_OCCURRENCE_FULL, srvId);
 
-    private <K, V> void v1tov2cacheMigrate(String deprecatedCache, Cache<K, V> newCache) {
-        String cacheNme = ignCacheNme(deprecatedCache);
-        IgniteCache<K, V> tests = ignite.cache(cacheNme);
+            applyDestroyIgnCacheMigration(Old.TESTS, srvId);
+            applyDestroyIgnCacheMigration(STAT, srvId);
+            applyDestroyIgnCacheMigration(BUILD_STATISTICS, srvId);
 
-        if (tests == null) {
-            System.err.println("Cache not found: " + cacheNme);
+            applyDestroyIgnCacheMigration(Old.CHANGE_INFO_FULL, srvId);
+            applyDestroyIgnCacheMigration(Old.CHANGES_LIST, srvId);
 
-            return;
-        }
+            applyDestroyIgnCacheMigration(FINISHED_BUILDS, srvId);
+            applyDestroyIgnCacheMigration(BUILD_HIST_FINISHED, srvId);
+            applyDestroyIgnCacheMigration(BUILD_HIST_FINISHED_OR_FAILED, srvId);
+            applyDestroyIgnCacheMigration(Old.BUILD_PROBLEMS, srvId);
+            applyDestroyIgnCacheMigration(Old.TEST_FULL, srvId);
 
-        int size = tests.size();
-        if (size > 0) {
-            ignite.cluster().disableWal(newCache.getName());
+            applyDestroyIgnCacheMigration(Old.CONFIGURATIONS, srvId);
+            applyDestroyIgnCacheMigration(Old.TESTS_OCCURRENCES, srvId);
+            applyDestroyIgnCacheMigration(Old.TEST_REFS, srvId);
 
-            try {
-                int i = 0;
+            applyDestroyIgnCacheMigration(Old.ISSUES_USAGES_LIST, srvId);
+            applyDestroyIgnCacheMigration(Old.CALCULATED_STATISTIC, srvId);
+            applyDestroyIgnCacheMigration(Old.BUILDS, srvId);
+            applyDestroyIgnCacheMigration(Old.BUILD_RESULTS, srvId);
+            applyDestroyIgnCacheMigration(Old.BUILDS_FAILURE_RUN_STAT, srvId);
+            applyDestroyIgnCacheMigration(Old.TESTS_RUN_STAT, srvId);
 
-                Map<K, V> batch = new HashMap<>();
+            applyDestroyIgnCacheMigration(Old.LOG_CHECK_RESULT, srvId);
+        }
 
-                IgniteDataStreamer<K, V> streamer = ignite.dataStreamer(newCache.getName());
+        int sizeAfter = doneMigrations.size();
+        return (sizeAfter - sizeBefore) + " Migrations done from " + sizeAfter;
 
-                for (Cache.Entry<K, V> entry : tests) {
-                    batch.put(entry.getKey(), entry.getValue());
+    }
 
-                    i++;
+    private void applyDestroyIgnCacheMigration(String cacheName, String srvId) {
+        String ignCacheNme = ignCacheNme(cacheName, srvId);
+        applyDestroyCacheMigration(cacheName, ignCacheNme);
+    }
 
-                    if (batch.size() >= 300)
-                        saveOneBatch(cacheNme, size, i, batch, streamer);
-                }
+    private void applyDestroyCacheMigration(String cacheNme) {
+        applyDestroyCacheMigration(cacheNme, cacheNme);
+    }
 
-                if (!batch.isEmpty())
-                    saveOneBatch(cacheNme, size, i, batch, streamer);
+    private void applyDestroyCacheMigration(String dispCacheName, String cacheNme) {
+        applyMigration("destroy-" + cacheNme, () -> {
+            IgniteCache<Object, Object> cache = ignite.cache(cacheNme);
 
-                streamer.flush();
-                System.err.println("Removing data from old cache " + tests.getName());
+            if (cache == null) {
+                System.err.println("cache [" + cacheNme + "] not found");
 
-                tests.destroy();
-            }
-            finally {
-                ignite.cluster().enableWal(newCache.getName());
+                return;
             }
-        }
+
+            cache.destroy();
+        });
     }
 
     /**
@@ -403,7 +313,7 @@ public class DbMigrations {
     }
 
     private IgniteCache<String, Object> doneMigrationsCache() {
-        String migrations = ignCacheNme(DONE_MIGRATIONS);
+        String migrations = ignCacheNme(DONE_MIGRATIONS, DONE_MIGRATION_PREFIX);
         CacheConfiguration<String, Object> ccfg = new CacheConfiguration<>(migrations);
         ccfg.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL);
         ccfg.setCacheMode(CacheMode.REPLICATED);
@@ -433,7 +343,8 @@ public class DbMigrations {
         }
     }
 
-    private String ignCacheNme(String tests) {
-        return IgnitePersistentTeamcity.ignCacheNme(tests, serverId);
+    @NotNull public static String ignCacheNme(String cache, String srvId) {
+        return srvId + "." + cache;
     }
+
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/Ignite1Init.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/Ignite1Init.java
index 74f4f34..66236a8 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/Ignite1Init.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/Ignite1Init.java
@@ -63,10 +63,19 @@ public class Ignite1Init {
 
         activate();
 
+        dataMigrations();
+
         return ignite;
     }
 
     @SuppressWarnings({"WeakerAccess", "UnusedReturnValue"})
+    @MonitoredTask(name = "Data Migrations")
+    @AutoProfiling
+    public String dataMigrations() {
+        return new DbMigrations(ignite).dataMigration();
+    }
+
+    @SuppressWarnings({"WeakerAccess", "UnusedReturnValue"})
     @MonitoredTask(name = "Ignition Start")
     @AutoProfiling
     protected String ignitionStart() {
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/di/IgniteTcBotModule.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/di/IgniteTcBotModule.java
index e28a968..840c352 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/di/IgniteTcBotModule.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/di/IgniteTcBotModule.java
@@ -35,11 +35,13 @@ import org.apache.ignite.ci.observer.BuildObserver;
 import org.apache.ignite.ci.observer.ObserverTask;
 import org.apache.ignite.ci.tcbot.TcBotBusinessServicesModule;
 import org.apache.ignite.ci.tcbot.issue.IssueDetector;
-import org.apache.ignite.ci.teamcity.ignited.TeamcityIgnitedModule;
+import org.apache.ignite.tcbot.common.exeption.ServicesStartingException;
+import org.apache.ignite.tcbot.persistence.TcBotPersistenceModule;
+import org.apache.ignite.tcignited.TeamcityIgnitedModule;
 import org.apache.ignite.tcbot.common.exeption.ExceptionUtil;
 import org.apache.ignite.ci.web.TcUpdatePool;
 import org.apache.ignite.ci.web.model.hist.VisasHistoryStorage;
-import org.apache.ignite.ci.web.rest.exception.ServiceStartingException;
+import org.apache.ignite.ci.web.rest.exception.ServiceStartingExceptionMapper;
 import org.apache.ignite.tcbot.common.interceptor.AutoProfiling;
 import org.apache.ignite.tcbot.common.interceptor.MonitoredTask;
 
@@ -63,7 +65,7 @@ public class IgniteTcBotModule extends AbstractModule {
                 return igniteFut.get(10, TimeUnit.SECONDS);
             }
             catch (TimeoutException e) {
-                throw new ServiceStartingException(e);
+                throw new ServicesStartingException(e);
             }
             catch (Exception e) {
                 e.printStackTrace();
@@ -78,6 +80,7 @@ public class IgniteTcBotModule extends AbstractModule {
         bind(BuildObserver.class).in(new SingletonScope());
         bind(VisasHistoryStorage.class).in(new SingletonScope());
 
+        install(new TcBotPersistenceModule());
         install(new TeamcityIgnitedModule());
         install(new JiraIgnitedModule());
         install(new GitHubIgnitedModule());
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/runners/RemoteClientTmpHelper.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/runners/RemoteClientTmpHelper.java
index e949bc5..9735909 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/runners/RemoteClientTmpHelper.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/runners/RemoteClientTmpHelper.java
@@ -36,10 +36,10 @@ import org.apache.ignite.tcservice.model.result.Build;
 import org.apache.ignite.ci.teamcity.ignited.BuildRefCompacted;
 import org.apache.ignite.tcignited.ITeamcityIgnited;
 import org.apache.ignite.tcbot.persistence.IgniteStringCompactor;
-import org.apache.ignite.ci.teamcity.ignited.buildref.BuildRefDao;
+import org.apache.ignite.tcignited.buildref.BuildRefDao;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildDao;
-import org.apache.ignite.ci.teamcity.ignited.runhist.RunHistCompactedDao;
+import org.apache.ignite.tcignited.history.RunHistCompactedDao;
 import org.apache.ignite.ci.user.TcHelperUser;
 import org.apache.ignite.tcservice.util.XmlUtil;
 import org.apache.ignite.configuration.IgniteConfiguration;
@@ -48,7 +48,7 @@ import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
 import org.jetbrains.annotations.NotNull;
 
-import static org.apache.ignite.ci.teamcity.ignited.runhist.RunHistCompactedDao.BUILD_START_TIME_CACHE_NAME;
+import static org.apache.ignite.tcignited.history.RunHistCompactedDao.BUILD_START_TIME_CACHE_NAME;
 
 /**
  * Utility class for connecting to a remote server.
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/BuildChainProcessor.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/BuildChainProcessor.java
index d06cdef..7f5333e 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/BuildChainProcessor.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/BuildChainProcessor.java
@@ -18,16 +18,15 @@
 package org.apache.ignite.ci.tcbot.chain;
 
 import com.google.common.base.Preconditions;
-import com.google.common.base.Stopwatch;
 import com.google.common.util.concurrent.Futures;
-import org.apache.ignite.ci.analysis.*;
+import org.apache.ignite.ci.analysis.FullChainRunCtx;
+import org.apache.ignite.ci.analysis.MultBuildRunCtx;
+import org.apache.ignite.ci.analysis.SingleBuildRunCtx;
 import org.apache.ignite.ci.analysis.mode.LatestRebuildMode;
 import org.apache.ignite.ci.analysis.mode.ProcessLogsMode;
-import org.apache.ignite.ci.logs.BuildLogStreamChecker;
-import org.apache.ignite.ci.teamcity.ignited.*;
+import org.apache.ignite.ci.teamcity.ignited.BuildRefCompacted;
 import org.apache.ignite.ci.teamcity.ignited.buildtype.ParametersCompacted;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
-import org.apache.ignite.ci.teamcity.ignited.runhist.RunHistSync;
 import org.apache.ignite.ci.util.FutureUtil;
 import org.apache.ignite.ci.web.TcUpdatePool;
 import org.apache.ignite.ci.web.model.long_running.LRTest;
@@ -36,7 +35,9 @@ import org.apache.ignite.tcbot.common.interceptor.AutoProfiling;
 import org.apache.ignite.tcbot.persistence.IStringCompactor;
 import org.apache.ignite.tcignited.ITeamcityIgnited;
 import org.apache.ignite.tcignited.SyncMode;
+import org.apache.ignite.tcignited.buildlog.IBuildLogProcessor;
 import org.apache.ignite.tcignited.history.IRunHistory;
+import org.apache.ignite.tcignited.history.RunHistSync;
 import org.apache.ignite.tcservice.model.hist.BuildRef;
 import org.apache.ignite.tcservice.model.result.Build;
 import org.jetbrains.annotations.NotNull;
@@ -46,21 +47,14 @@ import org.slf4j.LoggerFactory;
 
 import javax.annotation.Nonnull;
 import javax.inject.Inject;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.UncheckedIOException;
 import java.util.*;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 import java.util.stream.Stream;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
 
 /**
  * Process whole Build Chain, E.g. runAll at particular server, including all builds involved
@@ -75,11 +69,6 @@ public class BuildChainProcessor {
     /** Compactor. */
     @Inject private IStringCompactor compactor;
 
-
-    /** Build logger processing running. */
-    private ConcurrentHashMap<Integer, CompletableFuture<LogCheckTask>> buildLogProcessingRunning = new ConcurrentHashMap<>();
-
-
     /**
      * Collects data about all long-running tests (run time more than one minute) across all suites in RunAll chain in
      * master branch.
@@ -108,7 +97,11 @@ public class BuildChainProcessor {
                 List<LRTest> lrTests = new ArrayList<>();
 
                 b.getAllTests()
-                    .filter(t -> t.getDuration() > 60 * 1000)
+                    .filter(t -> {
+                        Integer duration = t.getDuration();
+
+                        return duration !=null && duration > 60 * 1000;
+                    })
                     .forEach(
                         t -> lrTests
                             .add(new LRTest(t.testName(compactor), t.getDuration(), null))
@@ -361,89 +354,24 @@ public class BuildChainProcessor {
         }
     }
 
+    @Inject IBuildLogProcessor buildLogProcessor;
+
     @SuppressWarnings("WeakerAccess")
     @AutoProfiling
     protected void analyzeTests(MultBuildRunCtx outCtx, ITeamcityIgnited teamcity,
                                 ProcessLogsMode procLog) {
         for (SingleBuildRunCtx ctx : outCtx.getBuilds()) {
             if ((procLog == ProcessLogsMode.SUITE_NOT_COMPLETE && ctx.hasSuiteIncompleteFailure())
-                || procLog == ProcessLogsMode.ALL)
-                ctx.setLogCheckResFut(analyzeBuildLog(teamcity, ctx.buildId(), ctx));
+                    || procLog == ProcessLogsMode.ALL)
+                ctx.setLogCheckResFut(
+                        CompletableFuture.supplyAsync(
+                                () -> buildLogProcessor.analyzeBuildLog(teamcity,
+                                        ctx.buildId(),
+                                        ctx.hasSuiteIncompleteFailure()),
+                                tcUpdatePool.getService()));
         }
     }
 
-    private CompletableFuture<LogCheckTask> checkBuildLogNoCache(ITeamcityIgnited teamcity, int buildId, ISuiteResults ctx) {
-        final CompletableFuture<File> zipFut = teamcity.downloadBuildLogZip(buildId);
-        boolean dumpLastTest = ctx.hasSuiteIncompleteFailure();
-
-        if (zipFut == null)
-            return null;
-
-        return zipFut.thenApplyAsync(zipFile -> runCheckForZippedLog(dumpLastTest, zipFile),
-                tcUpdatePool.getService());
-    }
-
-
-    @SuppressWarnings("WeakerAccess")
-    @AutoProfiling
-    @NotNull protected LogCheckTask runCheckForZippedLog(boolean dumpLastTest, File zipFile) {
-        LogCheckTask task = new LogCheckTask(zipFile);
-
-        try {
-            //get the zip file content
-            try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile))) {
-                ZipEntry ze = zis.getNextEntry();    //get the zipped file list entry
-
-                while (ze != null) {
-                    BuildLogStreamChecker checker = task.createChecker();
-                    checker.apply(zis, zipFile);
-                    task.finalize(dumpLastTest);
-
-                    ze = zis.getNextEntry();
-                }
-                zis.closeEntry();
-            }
-        }
-        catch (IOException | UncheckedIOException e) {
-            final String msg = "Failed to process ZIPed entry " + zipFile;
-
-            System.err.println(msg);
-            e.printStackTrace();
-
-            logger.error(msg, e);
-        }
-
-        return task;
-    }
-
-    //todo implement persistent cache for build results
-    @AutoProfiling
-    public CompletableFuture<LogCheckResult> analyzeBuildLog(ITeamcityIgnited teamcity, Integer buildId, SingleBuildRunCtx ctx) {
-        final Stopwatch started = Stopwatch.createStarted();
-
-        CompletableFuture<LogCheckTask> fut = buildLogProcessingRunning.computeIfAbsent(buildId,
-                k -> checkBuildLogNoCache(teamcity, k, ctx)
-        );
-
-        if (fut == null)
-            return null;
-
-        return fut
-                .thenApply(task -> {
-                    buildLogProcessingRunning.remove(buildId, fut);
-
-                    return task;
-                })
-                .thenApply(task -> {
-                    logger.info(Thread.currentThread().getName()
-                            + ": processBuildLog required: " + started.elapsed(TimeUnit.MILLISECONDS)
-                            + "ms for " + ctx.suiteId());
-
-                    return task;
-                })
-                .thenApply(LogCheckTask::getResult);
-    }
-
     /**
      * @param buildFut Chain build future.
      * @param mode Mode.
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/PrChainsProcessor.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/PrChainsProcessor.java
index 6048b2d..38f52fa 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/PrChainsProcessor.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/PrChainsProcessor.java
@@ -38,7 +38,7 @@ import org.apache.ignite.tcbot.persistence.IStringCompactor;
 import org.apache.ignite.tcignited.ITeamcityIgnited;
 import org.apache.ignite.tcignited.ITeamcityIgnitedProvider;
 import org.apache.ignite.tcignited.SyncMode;
-import org.apache.ignite.ci.teamcity.ignited.runhist.RunHistSync;
+import org.apache.ignite.tcignited.history.RunHistSync;
 import org.apache.ignite.ci.user.ITcBotUserCreds;
 import org.apache.ignite.ci.web.model.current.ChainAtServerCurrentStatus;
 import org.apache.ignite.ci.web.model.current.SuiteCurrentStatus;
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/issue/IssueDetector.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/issue/IssueDetector.java
index 43fb196..c27af80 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/issue/IssueDetector.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/issue/IssueDetector.java
@@ -67,7 +67,7 @@ import org.jetbrains.annotations.NotNull;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import static org.apache.ignite.ci.teamcity.ignited.runhist.RunHistSync.normalizeBranch;
+import static org.apache.ignite.tcignited.history.RunHistSync.normalizeBranch;
 
 /**
  *
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/restcached/ITcServerProvider.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/restcached/ITcServerProvider.java
deleted file mode 100644
index 837be85..0000000
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/restcached/ITcServerProvider.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.ci.teamcity.restcached;
-
-import org.apache.ignite.ci.user.ITcBotUserCreds;
-import org.apache.ignite.tcservice.ITeamcity;
-
-import javax.annotation.Nullable;
-
-/**
- * Provides instance to server with appropriate credentials, may cache instances to avoid odd server instances.
- */
-public interface ITcServerProvider {
-    /**
-     * @param srvId Server id.
-     * @param prov Prov.
-     */
-    public ITeamcity server(String srvId, @Nullable ITcBotUserCreds prov);
-}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/restcached/InitializingServerFactory.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/restcached/InitializingServerFactory.java
deleted file mode 100644
index 1b94cab..0000000
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/restcached/InitializingServerFactory.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.ci.teamcity.restcached;
-
-import com.google.common.base.Strings;
-import javax.inject.Inject;
-import javax.inject.Provider;
-import org.apache.ignite.ci.IAnalyticsEnabledTeamcity;
-import org.apache.ignite.tcservice.TeamcityServiceConnection;
-import org.apache.ignite.ci.web.TcUpdatePool;
-
-@Deprecated
- class InitializingServerFactory implements ITcServerFactory {
-    @Inject
-    Provider<IAnalyticsEnabledTeamcity> tcPersistProv;
-
-    @Inject
-    Provider<TeamcityServiceConnection> tcConnProv;
-
-    @Inject
-    private TcUpdatePool tcUpdatePool;
-
-    /** {@inheritDoc} */
-    @Override public IAnalyticsEnabledTeamcity createServer(String srvId) {
-        TeamcityServiceConnection tcConn = tcConnProv.get();
-        tcConn.init(Strings.emptyToNull(srvId));
-
-        IAnalyticsEnabledTeamcity instance = tcPersistProv.get();
-        instance.init(tcConn);
-
-        instance.setExecutor(tcUpdatePool.getService());
-
-        return instance;
-    }
-}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/restcached/TcRestCachedModule.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/restcached/TcRestCachedModule.java
deleted file mode 100644
index 60f1577..0000000
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/restcached/TcRestCachedModule.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.ci.teamcity.restcached;
-
-import com.google.inject.AbstractModule;
-import com.google.inject.internal.SingletonScope;
-import org.apache.ignite.ci.IAnalyticsEnabledTeamcity;
-import org.apache.ignite.ci.IgnitePersistentTeamcity;
-import org.apache.ignite.tcservice.http.ITeamcityHttpConnection;
-import org.apache.ignite.tcservice.TcRealConnectionModule;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * Guice module to setup TC connection With REST persistence
- */
-public class TcRestCachedModule extends AbstractModule {
-    /** Connection. */
-    @Nullable private ITeamcityHttpConnection conn;
-
-    /** {@inheritDoc} */
-    @Override protected void configure() {
-        bind(IAnalyticsEnabledTeamcity.class).to(IgnitePersistentTeamcity.class);
-        bind(ITcServerFactory.class).to(InitializingServerFactory.class).in(new SingletonScope());
-
-        bind(ITcServerProvider.class).to(TcServerCachingProvider.class).in(new SingletonScope());
-
-        TcRealConnectionModule module = new TcRealConnectionModule();
-
-        module.overrideHttp(conn);
-
-        install(module);
-    }
-
-    public void overrideHttp(ITeamcityHttpConnection conn) {
-        this.conn = conn;
-    }
-}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/restcached/TcServerCachingProvider.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/restcached/TcServerCachingProvider.java
deleted file mode 100644
index 5540551..0000000
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/restcached/TcServerCachingProvider.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.ci.teamcity.restcached;
-
-import com.google.common.base.Strings;
-import com.google.common.cache.Cache;
-import com.google.common.cache.CacheBuilder;
-import org.apache.ignite.ci.user.ITcBotUserCreds;
-import org.apache.ignite.tcbot.common.exeption.ExceptionUtil;
-import org.apache.ignite.tcservice.ITeamcity;
-
-import javax.annotation.Nullable;
-import javax.inject.Inject;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-
-/**
- *
- */
-class TcServerCachingProvider implements ITcServerProvider {
-    /** Server factory. */
-    @Inject
-    private ITcServerFactory srvFactory;
-
-    /** Servers. */
-    private final Cache<String, ITeamcity> srvs
-        = CacheBuilder.newBuilder()
-        .maximumSize(100)
-        .expireAfterAccess(16, TimeUnit.MINUTES)
-        .softValues()
-        .build();
-
-    /** {@inheritDoc} */
-    @Override public ITeamcity server(String srvId, @Nullable ITcBotUserCreds prov) {
-        String fullKey = Strings.nullToEmpty(prov == null ? null : prov.getUser(srvId)) + ":" + Strings.nullToEmpty(srvId);
-
-        try {
-            return srvs.get(fullKey, () -> {
-                ITeamcity teamcity = srvFactory.createServer(srvId);
-
-                if (prov != null) {
-                    final String user = prov.getUser(srvId);
-                    final String pwd = prov.getPassword(srvId);
-                    teamcity.setAuthData(user, pwd);
-                }
-
-                return teamcity;
-            });
-        }
-        catch (ExecutionException e) {
-            throw ExceptionUtil.propagateException(e);
-        }
-    }
-}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/TcApplicationResCfg.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/TcApplicationResCfg.java
index 301bde2..8431668 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/TcApplicationResCfg.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/TcApplicationResCfg.java
@@ -19,7 +19,7 @@ package org.apache.ignite.ci.web;
 
 import org.apache.ignite.ci.web.auth.AuthenticationFilter;
 import org.apache.ignite.ci.web.rest.exception.ExeptionsTraceLogger;
-import org.apache.ignite.ci.web.rest.exception.ServiceStartingException;
+import org.apache.ignite.ci.web.rest.exception.ServiceStartingExceptionMapper;
 import org.apache.ignite.tcbot.common.exeption.ServiceUnauthorizedException;
 import org.glassfish.jersey.logging.LoggingFeature;
 import org.glassfish.jersey.server.ResourceConfig;
@@ -36,7 +36,7 @@ public class TcApplicationResCfg extends ResourceConfig {
         register(AuthenticationFilter.class);
 
         register(ServiceUnauthorizedException.class);
-        register(ServiceStartingException.class);
+        register(ServiceStartingExceptionMapper.class);
 
         register(LoggingFeature.class);
         register(ExeptionsTraceLogger.class);
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/Version.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/Version.java
index c89b122..aacbb8f 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/Version.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/Version.java
@@ -28,7 +28,7 @@ package org.apache.ignite.ci.web.model;
     public static final String GITHUB_REF = "https://github.com/apache/ignite-teamcity-bot";
 
     /** TC Bot Version. */
-    public static final String VERSION = "20190530";
+    public static final String VERSION = "20190602";
 
     /** Java version, where Web App is running. */
     public String javaVer;
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/SuiteCurrentStatus.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/SuiteCurrentStatus.java
index 9c1fd82..5bbb383 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/SuiteCurrentStatus.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/SuiteCurrentStatus.java
@@ -31,9 +31,9 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import org.apache.ignite.ci.analysis.IMultTestOccurrence;
 import org.apache.ignite.ci.analysis.MultBuildRunCtx;
-import org.apache.ignite.ci.analysis.TestLogCheckResult;
 import org.apache.ignite.ci.issue.EventTemplates;
 import org.apache.ignite.ci.issue.ProblemRef;
+import org.apache.ignite.tcignited.buildlog.ITestLogCheckResult;
 import org.apache.ignite.tcignited.history.IRunHistory;
 import org.apache.ignite.tcbot.persistence.IStringCompactor;
 import org.apache.ignite.tcignited.ITeamcityIgnited;
@@ -41,7 +41,7 @@ import org.apache.ignite.ci.web.model.hist.FailureSummary;
 import org.apache.ignite.ci.web.rest.GetBuildLog;
 import org.jetbrains.annotations.NotNull;
 
-import static org.apache.ignite.ci.teamcity.ignited.runhist.RunHistSync.normalizeBranch;
+import static org.apache.ignite.tcignited.history.RunHistSync.normalizeBranch;
 import static org.apache.ignite.tcbot.common.util.TimeUtil.millisToDurationPrintable;
 import static org.apache.ignite.ci.util.UrlUtil.escape;
 
@@ -301,7 +301,7 @@ import static org.apache.ignite.ci.util.UrlUtil.escape;
         return failure;
     }
 
-    public void findFailureAndAddWarning(String testName, TestLogCheckResult logCheckRes) {
+    public void findFailureAndAddWarning(String testName, ITestLogCheckResult logCheckRes) {
         TestFailure failure = testFailures.stream().filter(f -> f.name.contains(testName)).findAny().orElseGet(
             () -> {
                 return warnOnly.stream().filter(f -> f.name.contains(testName)).findAny().orElseGet(
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/TestFailure.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/TestFailure.java
index 2c32b4b..c50b6a7 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/TestFailure.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/TestFailure.java
@@ -28,14 +28,14 @@ import javax.annotation.Nullable;
 import org.apache.ignite.ci.analysis.IMultTestOccurrence;
 import org.apache.ignite.ci.issue.EventTemplates;
 import org.apache.ignite.ci.issue.ProblemRef;
-import org.apache.ignite.ci.logs.LogMsgToWarn;
+import org.apache.ignite.tcignited.buildlog.LogMsgToWarn;
 import org.apache.ignite.tcignited.history.IRunHistory;
 import org.apache.ignite.tcignited.ITeamcityIgnited;
 import org.apache.ignite.ci.web.model.hist.FailureSummary;
 import org.apache.ignite.ci.web.model.hist.TestHistory;
 import org.jetbrains.annotations.NotNull;
 
-import static org.apache.ignite.ci.teamcity.ignited.runhist.RunHistSync.normalizeBranch;
+import static org.apache.ignite.tcignited.history.RunHistSync.normalizeBranch;
 import static org.apache.ignite.tcbot.common.util.TimeUtil.millisToDurationPrintable;
 import static org.apache.ignite.ci.util.UrlUtil.escape;
 
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetBuildLog.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetBuildLog.java
index 232ba22..6c9b640 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetBuildLog.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetBuildLog.java
@@ -17,10 +17,9 @@
 
 package org.apache.ignite.ci.web.rest;
 
-import org.apache.ignite.ci.ITcAnalytics;
-import org.apache.ignite.ci.teamcity.restcached.ITcServerProvider;
+import com.google.inject.Injector;
 import org.apache.ignite.ci.web.CtxListener;
-import org.apache.ignite.tcservice.ITeamcity;
+import org.apache.ignite.tcignited.buildlog.IBuildLogProcessor;
 
 import javax.annotation.security.PermitAll;
 import javax.servlet.ServletContext;
@@ -61,21 +60,18 @@ public class GetBuildLog {
     @Path(THREAD_DUMP)
     @PermitAll
     public Response getThreadDump(
-        @QueryParam(SERVER_ID) String srvId,
-        @QueryParam(BUILD_NO) Integer buildNo) {
+        @QueryParam(SERVER_ID) String srvCode,
+        @QueryParam(BUILD_NO) Integer buildId) {
+        Injector injector = CtxListener.getInjector(ctx);
 
-        ITcServerProvider helper = CtxListener.getInjector(ctx).getInstance(ITcServerProvider.class);
-        final ITeamcity server = helper.server(srvId, null);
+        IBuildLogProcessor instance = injector.getInstance(IBuildLogProcessor.class);
 
-        //todo bad code
-        if(server instanceof ITcAnalytics) {
-            ITcAnalytics srv = (ITcAnalytics) server;
-            String cached = srv.getThreadDumpCached(buildNo);
-            return sendString(cached);
-        }
+        String cached = instance.getThreadDumpCached(srvCode, buildId);
 
-        return sendString("Invalid class" + server.getClass());
+        if (cached == null)
+            return sendString("No data found for [" + srvCode + ", " + buildId + "]");
 
+        return sendString(cached);
     }
 
     private Response sendString(String data) {
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetChainResultsAsHtml.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetChainResultsAsHtml.java
index fa755f9..4745f41 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetChainResultsAsHtml.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetChainResultsAsHtml.java
@@ -38,7 +38,6 @@ import org.apache.ignite.tcbot.persistence.IStringCompactor;
 import org.apache.ignite.tcignited.ITeamcityIgnited;
 import org.apache.ignite.tcignited.ITeamcityIgnitedProvider;
 import org.apache.ignite.tcignited.SyncMode;
-import org.apache.ignite.ci.teamcity.restcached.ITcServerProvider;
 import org.apache.ignite.ci.user.ITcBotUserCreds;
 import org.apache.ignite.ci.util.FutureUtil;
 import org.apache.ignite.ci.web.CtxListener;
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/exception/ServiceStartingException.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/exception/ServiceStartingExceptionMapper.java
similarity index 75%
rename from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/exception/ServiceStartingException.java
rename to ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/exception/ServiceStartingExceptionMapper.java
index 20cb33b..26da3e7 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/exception/ServiceStartingException.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/exception/ServiceStartingExceptionMapper.java
@@ -17,23 +17,22 @@
 
 package org.apache.ignite.ci.web.rest.exception;
 
+import org.apache.ignite.tcbot.common.exeption.ServicesStartingException;
+
 import javax.ws.rs.core.Response;
 import javax.ws.rs.ext.ExceptionMapper;
 import javax.ws.rs.ext.Provider;
 
+/**
+ * Providing response code 418- I'm a teapot for starting server.
+ */
 @Provider
-public class ServiceStartingException extends RuntimeException
-        implements ExceptionMapper<ServiceStartingException> {
-    public ServiceStartingException(Exception e) {
-        super(e);
-    }
-
-    @SuppressWarnings("unused")
-    public ServiceStartingException() {
+public class ServiceStartingExceptionMapper implements ExceptionMapper<ServicesStartingException> {
+    public ServiceStartingExceptionMapper() {
     }
 
     @Override
-    public Response toResponse(ServiceStartingException exception) {
+    public Response toResponse(ServicesStartingException exception) {
         return Response.status(418).entity(exception.getMessage())
                 .type("text/plain").build();
     }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/exception/ServiceUnauthorizedExceptionMapper.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/exception/ServiceUnauthorizedExceptionMapper.java
index 6b78aef..975732e 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/exception/ServiceUnauthorizedExceptionMapper.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/exception/ServiceUnauthorizedExceptionMapper.java
@@ -29,8 +29,6 @@ import javax.ws.rs.ext.Provider;
 @Provider
 public class ServiceUnauthorizedExceptionMapper
         implements ExceptionMapper<ServiceUnauthorizedException> {
-
-    @SuppressWarnings("unused")
     public ServiceUnauthorizedExceptionMapper() {
     }
 
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/tracked/GetTrackedBranchTestResults.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/tracked/GetTrackedBranchTestResults.java
index a1ab103..c631a7f 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/tracked/GetTrackedBranchTestResults.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/tracked/GetTrackedBranchTestResults.java
@@ -42,7 +42,7 @@ import org.apache.ignite.internal.util.typedef.F;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import static org.apache.ignite.ci.teamcity.ignited.TeamcityIgnitedImpl.DEFAULT_PROJECT_ID;
+import static org.apache.ignite.tcignited.TeamcityIgnitedImpl.DEFAULT_PROJECT_ID;
 
 @Path(GetTrackedBranchTestResults.TRACKED)
 @Produces(MediaType.APPLICATION_JSON)
diff --git a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/di/DiContextTest.java b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/di/DiContextTest.java
index 52f2565..c9c009c 100644
--- a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/di/DiContextTest.java
+++ b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/di/DiContextTest.java
@@ -28,8 +28,6 @@ import org.apache.ignite.ci.observer.ObserverTask;
 import org.apache.ignite.ci.tcbot.ITcBotBgAuth;
 import org.apache.ignite.ci.tcbot.chain.BuildChainProcessor;
 import org.apache.ignite.ci.tcbot.conf.ITcBotConfig;
-import org.apache.ignite.ci.teamcity.restcached.ITcServerFactory;
-import org.apache.ignite.ci.teamcity.restcached.ITcServerProvider;
 import org.apache.ignite.ci.web.TcUpdatePool;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.tcbot.common.interceptor.MonitoredTask;
diff --git a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/BuildChainProcessorTest.java b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/BuildChainProcessorTest.java
index 5a8d5ff..2538985 100644
--- a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/BuildChainProcessorTest.java
+++ b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/BuildChainProcessorTest.java
@@ -26,6 +26,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 
+import org.apache.ignite.tcignited.buildlog.IBuildLogProcessor;
 import org.apache.ignite.tcservice.ITeamcity;
 import org.apache.ignite.ci.analysis.FullChainRunCtx;
 import org.apache.ignite.ci.analysis.IMultTestOccurrence;
@@ -43,6 +44,7 @@ import org.apache.ignite.ci.teamcity.ignited.TeamcityIgnitedMock;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
 import org.jetbrains.annotations.NotNull;
 import org.junit.Test;
+import org.mockito.Mockito;
 
 import static junit.framework.TestCase.assertEquals;
 import static junit.framework.TestCase.assertTrue;
@@ -66,7 +68,8 @@ public class BuildChainProcessorTest {
     private Injector injector = Guice.createInjector(new AbstractModule() {
         @Override protected void configure() {
             bind(IStringCompactor.class).to(InMemoryStringCompactor.class).in(new SingletonScope());
-            super.configure();
+
+            bind(IBuildLogProcessor.class).toInstance(Mockito.mock(IBuildLogProcessor.class));
         }
     });
 
diff --git a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/MockBasedTcBotModule.java b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/MockBasedTcBotModule.java
index 9fe5822..be1b4aa 100644
--- a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/MockBasedTcBotModule.java
+++ b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/MockBasedTcBotModule.java
@@ -44,9 +44,9 @@ import org.apache.ignite.tcbot.persistence.IStringCompactor;
 import org.apache.ignite.tcignited.ITeamcityIgnitedProvider;
 import org.apache.ignite.ci.teamcity.ignited.InMemoryStringCompactor;
 import org.apache.ignite.ci.teamcity.ignited.TeamcityIgnitedProviderMock;
-import org.apache.ignite.ci.teamcity.restcached.ITcServerProvider;
 import org.apache.ignite.tcbot.common.conf.ITcServerConfigSupplier;
 import org.apache.ignite.tcbot.common.conf.TcBotWorkDir;
+import org.apache.ignite.tcignited.buildlog.IBuildLogProcessor;
 import org.mockito.Mockito;
 
 import static org.mockito.ArgumentMatchers.any;
@@ -73,6 +73,8 @@ public class MockBasedTcBotModule extends AbstractModule {
     @Override protected void configure() {
         bind(IStringCompactor.class).to(InMemoryStringCompactor.class).in(new SingletonScope());
 
+        bind(IBuildLogProcessor.class).toInstance(Mockito.mock(IBuildLogProcessor.class));
+
         final IGitHubConnectionProvider ghProv = Mockito.mock(IGitHubConnectionProvider.class);
         bind(IGitHubConnectionProvider.class).toInstance(ghProv);
         when(ghProv.server(anyString())).thenReturn(Mockito.mock(IGitHubConnection.class));
diff --git a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/issue/IssueDetectorTest.java b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/issue/IssueDetectorTest.java
index f8afff5..b62568c 100644
--- a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/issue/IssueDetectorTest.java
+++ b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/issue/IssueDetectorTest.java
@@ -35,7 +35,7 @@ import org.apache.ignite.ci.tcbot.conf.BranchesTracked;
 import org.apache.ignite.tcservice.model.result.tests.TestOccurrenceFull;
 import org.apache.ignite.tcbot.persistence.IStringCompactor;
 import org.apache.ignite.tcignited.ITeamcityIgnitedProvider;
-import org.apache.ignite.ci.teamcity.ignited.TeamcityIgnitedImpl;
+import org.apache.ignite.tcignited.TeamcityIgnitedImpl;
 import org.apache.ignite.ci.teamcity.ignited.TeamcityIgnitedProviderMock;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
 import org.apache.ignite.ci.user.ITcBotUserCreds;
diff --git a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/BuildKeyUnitTest.java b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/BuildKeyUnitTest.java
index d479e90..f11b6e5 100644
--- a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/BuildKeyUnitTest.java
+++ b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/BuildKeyUnitTest.java
@@ -17,7 +17,7 @@
 
 package org.apache.ignite.ci.teamcity.ignited;
 
-import org.apache.ignite.ci.teamcity.ignited.buildref.BuildRefDao;
+import org.apache.ignite.tcignited.buildref.BuildRefDao;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildDao;
 import org.apache.ignite.tcignited.ITeamcityIgnited;
 import org.junit.Test;
diff --git a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/IgnitedTcInMemoryIntegrationTest.java b/ignite-tc-helper-web/src/test/java/org/apache/ignite/tcignited/IgnitedTcInMemoryIntegrationTest.java
similarity index 96%
rename from ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/IgnitedTcInMemoryIntegrationTest.java
rename to ignite-tc-helper-web/src/test/java/org/apache/ignite/tcignited/IgnitedTcInMemoryIntegrationTest.java
index 6967990..6f4feab 100644
--- a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/IgnitedTcInMemoryIntegrationTest.java
+++ b/ignite-tc-helper-web/src/test/java/org/apache/ignite/tcignited/IgnitedTcInMemoryIntegrationTest.java
@@ -14,48 +14,45 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.ignite.ci.teamcity.ignited;
+package org.apache.ignite.tcignited;
 
 import com.google.common.collect.Lists;
 import com.google.inject.AbstractModule;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
 import com.google.inject.internal.SingletonScope;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.stream.Collectors;
-import javax.xml.bind.JAXBException;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.Ignition;
-import org.apache.ignite.tcbot.persistence.IStringCompactor;
-import org.apache.ignite.tcbot.persistence.IgniteStringCompactor;
-import org.apache.ignite.tcignited.ITeamcityIgnited;
-import org.apache.ignite.tcignited.ITeamcityIgnitedProvider;
-import org.apache.ignite.tcignited.history.IRunHistory;
-import org.apache.ignite.tcignited.history.IRunStat;
-import org.apache.ignite.tcservice.ITeamcity;
 import org.apache.ignite.ci.db.TcHelperDb;
 import org.apache.ignite.ci.di.scheduler.DirectExecNoWaitScheduler;
-import org.apache.ignite.tcbot.persistence.scheduler.IScheduler;
 import org.apache.ignite.ci.jira.pure.IJiraIntegrationProvider;
 import org.apache.ignite.ci.tcbot.chain.PrChainsProcessorTest;
 import org.apache.ignite.ci.tcbot.conf.BranchesTracked;
 import org.apache.ignite.ci.tcbot.conf.ITcBotConfig;
+import org.apache.ignite.ci.teamcity.ignited.BuildRefCompacted;
+import org.apache.ignite.tcignited.buildref.BuildRefDao;
+import org.apache.ignite.ci.teamcity.ignited.buildtype.BuildTypeRefCompacted;
+import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
+import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildDao;
+import org.apache.ignite.ci.teamcity.ignited.fatbuild.ProactiveFatBuildSync;
+import org.apache.ignite.ci.teamcity.pure.BuildHistoryEmulator;
+import org.apache.ignite.ci.user.ITcBotUserCreds;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.apache.ignite.tcbot.common.conf.ITcServerConfig;
+import org.apache.ignite.tcbot.common.conf.ITcServerConfigSupplier;
+import org.apache.ignite.tcbot.persistence.IStringCompactor;
+import org.apache.ignite.tcbot.persistence.IgniteStringCompactor;
+import org.apache.ignite.tcbot.persistence.TcBotPersistenceModule;
+import org.apache.ignite.tcbot.persistence.scheduler.IScheduler;
+import org.apache.ignite.tcignited.history.IRunHistory;
+import org.apache.ignite.tcignited.history.IRunStat;
+import org.apache.ignite.tcignited.history.RunHistCompactedDao;
+import org.apache.ignite.tcignited.history.RunHistSync;
+import org.apache.ignite.tcservice.ITeamcity;
 import org.apache.ignite.tcservice.TeamcityServiceConnection;
+import org.apache.ignite.tcservice.http.ITeamcityHttpConnection;
 import org.apache.ignite.tcservice.model.changes.ChangesList;
 import org.apache.ignite.tcservice.model.conf.BuildType;
 import org.apache.ignite.tcservice.model.conf.Project;
@@ -71,22 +68,7 @@ import org.apache.ignite.tcservice.model.result.stat.Statistics;
 import org.apache.ignite.tcservice.model.result.tests.TestOccurrencesFull;
 import org.apache.ignite.tcservice.model.vcs.Revision;
 import org.apache.ignite.tcservice.model.vcs.Revisions;
-import org.apache.ignite.ci.teamcity.ignited.buildref.BuildRefDao;
-import org.apache.ignite.ci.teamcity.ignited.buildtype.BuildTypeRefCompacted;
-import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
-import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildDao;
-import org.apache.ignite.ci.teamcity.ignited.fatbuild.ProactiveFatBuildSync;
-import org.apache.ignite.ci.teamcity.ignited.runhist.RunHistCompactedDao;
-import org.apache.ignite.ci.teamcity.ignited.runhist.RunHistSync;
-import org.apache.ignite.ci.teamcity.pure.BuildHistoryEmulator;
-import org.apache.ignite.tcservice.ITeamcityConn;
-import org.apache.ignite.tcservice.http.ITeamcityHttpConnection;
-import org.apache.ignite.ci.teamcity.restcached.ITcServerFactory;
-import org.apache.ignite.ci.user.ITcBotUserCreds;
 import org.apache.ignite.tcservice.util.XmlUtil;
-import org.apache.ignite.configuration.IgniteConfiguration;
-import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
-import org.apache.ignite.tcbot.common.conf.ITcServerConfigSupplier;
 import org.jetbrains.annotations.NotNull;
 import org.junit.AfterClass;
 import org.junit.Before;
@@ -94,12 +76,14 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 import org.mockito.Mockito;
 
+import javax.xml.bind.JAXBException;
+import java.io.*;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.stream.Collectors;
+
 import static com.google.common.base.Preconditions.checkNotNull;
-import static junit.framework.TestCase.assertEquals;
-import static junit.framework.TestCase.assertFalse;
-import static junit.framework.TestCase.assertNotNull;
-import static junit.framework.TestCase.assertNull;
-import static junit.framework.TestCase.assertTrue;
+import static junit.framework.TestCase.*;
 import static org.apache.ignite.tcbot.common.conf.TcBotWorkDir.ensureDirExist;
 import static org.apache.ignite.tcbot.persistence.IgniteStringCompactor.STRINGS_CACHE;
 import static org.mockito.ArgumentMatchers.anyString;
@@ -759,6 +743,8 @@ public class IgnitedTcInMemoryIntegrationTest {
 
             bind(ITcBotConfig.class).toInstance(cfg);
             bind(ITcServerConfigSupplier.class).toInstance(cfg);
+
+            install(new TcBotPersistenceModule());
         }
     }
 }
diff --git a/jetty-launcher/header.txt b/jetty-launcher/header.txt
deleted file mode 100644
index a9ac967..0000000
--- a/jetty-launcher/header.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-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.
\ No newline at end of file
diff --git a/tcbot-common/header.txt b/tcbot-common/header.txt
deleted file mode 100644
index a9ac967..0000000
--- a/tcbot-common/header.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-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.
\ No newline at end of file
diff --git a/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/exeption/ExceptionUtil.java b/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/exeption/ExceptionUtil.java
index fb2ec30..3600efe 100644
--- a/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/exeption/ExceptionUtil.java
+++ b/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/exeption/ExceptionUtil.java
@@ -20,6 +20,7 @@ package org.apache.ignite.tcbot.common.exeption;
 import com.google.common.base.Throwables;
 
 import java.util.Optional;
+import java.util.concurrent.ExecutionException;
 
 /**
  *
@@ -32,6 +33,13 @@ public class ExceptionUtil {
         if (e instanceof InterruptedException)
             Thread.currentThread().interrupt();
 
+        if(e instanceof ExecutionException) {
+            ExecutionException executionException = (ExecutionException) e;
+            Throwable cause = executionException.getCause();
+
+            Throwables.throwIfUnchecked(cause);
+        }
+
         throwIfRest(e);
 
         Throwables.throwIfUnchecked(e);
@@ -41,9 +49,11 @@ public class ExceptionUtil {
 
     public static void throwIfRest(Exception e) {
         final Optional<Throwable> any = Throwables.getCausalChain(e)
-            .stream()
-            .filter(th ->false).findAny();
-                   //todo (th instanceof ExceptionMapper)).findAny();
+                .stream()
+                .filter(th ->
+                        th instanceof ServiceUnauthorizedException
+                                || th instanceof ServicesStartingException)
+                .findAny();
 
         final RuntimeException eRest = (RuntimeException) any.orElse(null);
         if (eRest != null)
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/restcached/ITcServerFactory.java b/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/exeption/ServicesStartingException.java
similarity index 70%
rename from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/restcached/ITcServerFactory.java
rename to tcbot-common/src/main/java/org/apache/ignite/tcbot/common/exeption/ServicesStartingException.java
index e0b179a..73662af 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/restcached/ITcServerFactory.java
+++ b/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/exeption/ServicesStartingException.java
@@ -14,16 +14,20 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.ignite.ci.teamcity.restcached;
 
-import org.apache.ignite.ci.IAnalyticsEnabledTeamcity;
+package org.apache.ignite.tcbot.common.exeption;
+
 
 /**
- * Factory for creating new servers
+ * Services are starting exception, special handling in REST responses.
  */
-public interface ITcServerFactory {
-    /**
-     * @param srvId Server id.
-     */
-    public IAnalyticsEnabledTeamcity createServer(String srvId);
+public class ServicesStartingException extends RuntimeException  {
+    public ServicesStartingException(Exception e) {
+        super(e);
+    }
+
+    @SuppressWarnings("unused")
+    public ServicesStartingException() {
+    }
+
 }
diff --git a/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/util/HttpUtil.java b/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/util/HttpUtil.java
index ef5bc4c..ad79518 100644
--- a/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/util/HttpUtil.java
+++ b/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/util/HttpUtil.java
@@ -74,7 +74,7 @@ public class HttpUtil {
      * @param basicAuthTok Authorization token.
      * @param url URL.
      * @return Input stream from connection.
-     * @throws IOException If failed.
+     * @throws IOException If communication failed.
      * @throws FileNotFoundException If not found (404) was returned from service.
      * @throws ServiceConflictException If conflict (409) was returned from service.
      * @throws IllegalStateException if some unexpected HTTP error returned.
@@ -135,6 +135,16 @@ public class HttpUtil {
         return getInputStream(con);
     }
 
+    /**
+     * @param tok token
+     * @param url full URL
+     * @param file destination file to save data.
+
+     * @throws IOException If communication failed.
+     * @throws FileNotFoundException If not found (404) was returned from service.
+     * @throws ServiceConflictException If conflict (409) was returned from service.
+     * @throws IllegalStateException if some unexpected HTTP error returned.
+     */
     public static void sendGetCopyToFile(String tok, String url, File file) throws IOException {
         try (InputStream inputStream = sendGetWithBasicAuth(tok, url)){
             Files.copy(inputStream, file.toPath(), StandardCopyOption.REPLACE_EXISTING);
diff --git a/tcbot-persistence/src/main/java/org/apache/ignite/ci/tcbot/common/StringFieldCompacted.java b/tcbot-persistence/src/main/java/org/apache/ignite/ci/tcbot/common/StringFieldCompacted.java
index 46af408..817e11d 100644
--- a/tcbot-persistence/src/main/java/org/apache/ignite/ci/tcbot/common/StringFieldCompacted.java
+++ b/tcbot-persistence/src/main/java/org/apache/ignite/ci/tcbot/common/StringFieldCompacted.java
@@ -19,6 +19,12 @@ package org.apache.ignite.ci.tcbot.common;
 
 import com.google.common.base.Objects;
 import com.google.common.base.Strings;
+import org.apache.ignite.tcbot.persistence.Persisted;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xerial.snappy.Snappy;
+
+import javax.annotation.Nonnull;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -27,13 +33,6 @@ import java.util.Arrays;
 import java.util.zip.GZIPInputStream;
 import java.util.zip.GZIPOutputStream;
 
-import org.apache.ignite.tcbot.persistence.Persisted;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.xerial.snappy.Snappy;
-
-import javax.annotation.Nonnull;
-
 /**
  * Field is included into bigger entries, so it is placed in backward compatible package.
  */
@@ -47,6 +46,14 @@ public class StringFieldCompacted {
     byte flag;
     byte data[];
 
+    public StringFieldCompacted() {
+
+    }
+
+    public StringFieldCompacted(String value) {
+        setValue(value);
+    }
+
     public String getValue() {
         if (data == null)
             return "";
@@ -165,4 +172,8 @@ public class StringFieldCompacted {
     @Override public int hashCode() {
         return Objects.hashCode(flag, data);
     }
+
+    public boolean isFilled() {
+        return data != null;
+    }
 }
diff --git a/tcbot-persistence/src/main/java/org/apache/ignite/ci/teamcity/ignited/IgniteStringCompactor.java b/tcbot-persistence/src/main/java/org/apache/ignite/ci/teamcity/ignited/IgniteStringCompactor.java
index 5dc6cb4..21c2037 100644
--- a/tcbot-persistence/src/main/java/org/apache/ignite/ci/teamcity/ignited/IgniteStringCompactor.java
+++ b/tcbot-persistence/src/main/java/org/apache/ignite/ci/teamcity/ignited/IgniteStringCompactor.java
@@ -1,5 +1,21 @@
+/*
+ * 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.ci.teamcity.ignited;
-//public  org.apache.ignite.ci.teamcity.ignited.IgniteStringCompactor$CompactorEntity
 import com.google.common.base.MoreObjects;
 import org.apache.ignite.cache.query.annotations.QuerySqlField;
 import org.apache.ignite.tcbot.persistence.Persisted;
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/ILineHandler.java b/tcbot-persistence/src/main/java/org/apache/ignite/tcbot/persistence/TcBotPersistenceModule.java
similarity index 68%
copy from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/ILineHandler.java
copy to tcbot-persistence/src/main/java/org/apache/ignite/tcbot/persistence/TcBotPersistenceModule.java
index 2af9c2f..38eca98 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/ILineHandler.java
+++ b/tcbot-persistence/src/main/java/org/apache/ignite/tcbot/persistence/TcBotPersistenceModule.java
@@ -15,13 +15,17 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.ci.logs;
+package org.apache.ignite.tcbot.persistence;
 
-import java.io.File;
+import com.google.inject.AbstractModule;
+import com.google.inject.internal.SingletonScope;
 
-/**
- *
- */
-public interface ILineHandler extends AutoCloseable {
-    public void accept(String line, File file);
+public class TcBotPersistenceModule extends AbstractModule {
+    @Override
+    protected void configure() {
+        super.configure();
+
+
+        bind(IStringCompactor.class).to(IgniteStringCompactor.class).in(new SingletonScope());
+    }
 }
diff --git a/tcbot-server/README.md b/tcbot-server/README.md
index 59bfb01..30d7299 100644
--- a/tcbot-server/README.md
+++ b/tcbot-server/README.md
@@ -1,3 +1,4 @@
 TC Bot server node
+------------------
 
 Incomplete module for preparing scripts to start Apache Ignite as a separate process.
\ No newline at end of file
diff --git a/tcbot-server/header.txt b/tcbot-server/header.txt
deleted file mode 100644
index a9ac967..0000000
--- a/tcbot-server/header.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-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.
\ No newline at end of file
diff --git a/tcbot-teamcity-ignited/README.md b/tcbot-teamcity-ignited/README.md
new file mode 100644
index 0000000..3647a3c
--- /dev/null
+++ b/tcbot-teamcity-ignited/README.md
@@ -0,0 +1,5 @@
+TC Bot Teamcity Ignited module
+------------------------------
+
+Module for accessing to cached data obtained from
+[TeamCity Service](../tcbot-teamcity)
\ No newline at end of file
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/buildtype/BuildTypeSync.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/buildtype/BuildTypeSync.java
index 887393e..1da2ffa 100644
--- a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/buildtype/BuildTypeSync.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/buildtype/BuildTypeSync.java
@@ -37,7 +37,8 @@ import org.apache.ignite.tcbot.common.exeption.ExceptionUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import static org.apache.ignite.ci.teamcity.ignited.TeamcityIgnitedImpl.DEFAULT_PROJECT_ID;
+import static org.apache.ignite.tcignited.TeamcityIgnitedImpl.DEFAULT_PROJECT_ID;
+
 
 public class BuildTypeSync {
     /** Logger. */
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/change/ChangeDao.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/change/ChangeDao.java
index e75c365..b79e5fd 100644
--- a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/change/ChangeDao.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/change/ChangeDao.java
@@ -39,9 +39,6 @@ public class ChangeDao {
     /** Change Compacted cache. */
     private IgniteCache<Long, ChangeCompacted> changesCache;
 
-    /** Compactor. */
-    @Inject private IStringCompactor compactor;
-
     /** */
     public void init() {
         CacheConfiguration<Long, ChangeCompacted> cfg = CacheConfigs.getCacheV2Config(TEAMCITY_CHANGE_CACHE_NAME);
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/ProactiveFatBuildSync.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/ProactiveFatBuildSync.java
index b0925e3..e9bfe7c 100644
--- a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/ProactiveFatBuildSync.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/ProactiveFatBuildSync.java
@@ -28,12 +28,12 @@ import org.apache.ignite.tcservice.model.result.problems.ProblemOccurrence;
 import org.apache.ignite.tcservice.model.result.stat.Statistics;
 import org.apache.ignite.tcservice.model.result.tests.TestOccurrencesFull;
 import org.apache.ignite.ci.teamcity.ignited.BuildRefCompacted;
-import org.apache.ignite.ci.teamcity.ignited.buildref.BuildRefDao;
+import org.apache.ignite.tcignited.buildref.BuildRefDao;
 import org.apache.ignite.tcbot.persistence.IStringCompactor;
 import org.apache.ignite.tcignited.ITeamcityIgnited;
 import org.apache.ignite.tcignited.SyncMode;
 import org.apache.ignite.ci.teamcity.ignited.change.ChangeSync;
-import org.apache.ignite.ci.teamcity.ignited.runhist.RunHistSync;
+import org.apache.ignite.tcignited.history.RunHistSync;
 import org.apache.ignite.tcservice.ITeamcityConn;
 import org.apache.ignite.tcbot.common.exeption.ExceptionUtil;
 import org.apache.ignite.tcbot.common.exeption.ServiceConflictException;
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/runhist/RunHistKey.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/runhist/RunHistKey.java
index 11b6d4a..ddb910f 100644
--- a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/runhist/RunHistKey.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/runhist/RunHistKey.java
@@ -19,10 +19,12 @@ package org.apache.ignite.ci.teamcity.ignited.runhist;
 
 import com.google.common.base.Objects;
 import org.apache.ignite.cache.query.annotations.QuerySqlField;
+import org.apache.ignite.tcbot.persistence.Persisted;
 
 /**
  *
  */
+@Persisted
 public class RunHistKey {
     /** Server ID. */
     @QuerySqlField(orderedGroups = {@QuerySqlField.Group(name = "tstAndSrv", order = 1)})
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/ITeamcityIgnited.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/ITeamcityIgnited.java
index 17c8248..548a610 100644
--- a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/ITeamcityIgnited.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/ITeamcityIgnited.java
@@ -255,4 +255,7 @@ public interface ITeamcityIgnited {
     }
 
     CompletableFuture<File> downloadBuildLogZip(int buildId);
+
+
+    @Nullable File downloadAndCacheBuildLog(int buildId);
 }
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/TcIgnitedCachingProvider.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/TcIgnitedCachingProvider.java
similarity index 95%
rename from tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/TcIgnitedCachingProvider.java
rename to tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/TcIgnitedCachingProvider.java
index 8abf79b..123da3d 100644
--- a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/TcIgnitedCachingProvider.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/TcIgnitedCachingProvider.java
@@ -14,25 +14,23 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.ignite.ci.teamcity.ignited;
+package org.apache.ignite.tcignited;
 
 import com.google.common.base.Strings;
 import com.google.common.cache.Cache;
 import com.google.common.cache.CacheBuilder;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import javax.annotation.Nullable;
-import javax.inject.Inject;
-import javax.inject.Provider;
-
-import org.apache.ignite.tcbot.common.conf.ITcServerConfigSupplier;
-import org.apache.ignite.tcignited.ITeamcityIgnited;
-import org.apache.ignite.tcignited.ITeamcityIgnitedProvider;
-import org.apache.ignite.tcignited.creds.ICredentialsProv;
 import org.apache.ignite.tcbot.common.conf.ITcServerConfig;
+import org.apache.ignite.tcbot.common.conf.ITcServerConfigSupplier;
 import org.apache.ignite.tcbot.common.exeption.ExceptionUtil;
+import org.apache.ignite.tcignited.creds.ICredentialsProv;
 import org.apache.ignite.tcservice.TeamcityServiceConnection;
 
+import javax.annotation.Nullable;
+import javax.inject.Inject;
+import javax.inject.Provider;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+
 /**
  *
  */
@@ -54,6 +52,9 @@ class TcIgnitedCachingProvider implements ITeamcityIgnitedProvider {
 
     /** {@inheritDoc} */
     @Override public boolean hasAccess(String srvCode, @Nullable ICredentialsProv prov) {
+        if (prov == null)
+            return false;
+
         String ref = cfg.getTeamcityConfig(srvCode).reference();
 
         if (!Strings.isNullOrEmpty(ref))
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedImpl.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/TeamcityIgnitedImpl.java
similarity index 96%
rename from tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedImpl.java
rename to tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/TeamcityIgnitedImpl.java
index 5201c5f..9ee9e6d 100644
--- a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedImpl.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/TeamcityIgnitedImpl.java
@@ -14,14 +14,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.ignite.ci.teamcity.ignited;
+package org.apache.ignite.tcignited;
 
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
+import org.apache.ignite.ci.teamcity.ignited.BuildRefCompacted;
 import org.apache.ignite.ci.teamcity.ignited.buildcondition.BuildCondition;
 import org.apache.ignite.ci.teamcity.ignited.buildcondition.BuildConditionDao;
-import org.apache.ignite.ci.teamcity.ignited.buildref.BuildRefDao;
-import org.apache.ignite.ci.teamcity.ignited.buildref.BuildRefSync;
+import org.apache.ignite.tcignited.buildlog.BuildLogCheckResultDao;
+import org.apache.ignite.tcignited.buildref.BuildRefDao;
+import org.apache.ignite.tcignited.buildref.BuildRefSync;
 import org.apache.ignite.ci.teamcity.ignited.buildtype.*;
 import org.apache.ignite.ci.teamcity.ignited.change.ChangeCompacted;
 import org.apache.ignite.ci.teamcity.ignited.change.ChangeDao;
@@ -31,16 +33,14 @@ import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildDao;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.ProactiveFatBuildSync;
 import org.apache.ignite.ci.teamcity.ignited.mute.MuteDao;
 import org.apache.ignite.ci.teamcity.ignited.mute.MuteSync;
-import org.apache.ignite.ci.teamcity.ignited.runhist.RunHistCompactedDao;
-import org.apache.ignite.ci.teamcity.ignited.runhist.RunHistSync;
+import org.apache.ignite.tcignited.history.RunHistCompactedDao;
+import org.apache.ignite.tcignited.history.RunHistSync;
 import org.apache.ignite.tcbot.common.conf.ITcServerConfig;
 import org.apache.ignite.tcbot.common.interceptor.AutoProfiling;
 import org.apache.ignite.tcbot.common.interceptor.GuavaCached;
 import org.apache.ignite.tcbot.common.interceptor.MonitoredTask;
 import org.apache.ignite.tcbot.persistence.IStringCompactor;
 import org.apache.ignite.tcbot.persistence.scheduler.IScheduler;
-import org.apache.ignite.tcignited.ITeamcityIgnited;
-import org.apache.ignite.tcignited.SyncMode;
 import org.apache.ignite.tcignited.history.IRunHistory;
 import org.apache.ignite.tcignited.history.IRunStat;
 import org.apache.ignite.tcservice.ITeamcity;
@@ -134,6 +134,8 @@ public class TeamcityIgnitedImpl implements ITeamcityIgnited {
     /** Run history sync. */
     @Inject private RunHistSync runHistSync;
 
+    @Inject private BuildLogCheckResultDao logCheckResultDao;
+
     /** Strings compactor. */
     @Inject private IStringCompactor compactor;
 
@@ -153,6 +155,7 @@ public class TeamcityIgnitedImpl implements ITeamcityIgnited {
         changesDao.init();
         runHistCompactedDao.init();
         muteDao.init();
+        logCheckResultDao.init();
     }
 
     /**
@@ -426,6 +429,12 @@ public class TeamcityIgnitedImpl implements ITeamcityIgnited {
         return null;
     }
 
+    @Nullable
+    @Override
+    public File downloadAndCacheBuildLog(int buildId) {
+        return conn.downloadAndCacheBuildLog(buildId);
+    }
+
     /** {@inheritDoc} */
     @Override public List<String> getCompositeBuildTypesIdsSortedByBuildNumberCounter(String projectId) {
         return buildTypeSync.getCompositeBuildTypesIdsSortedByBuildNumberCounter(srvIdMaskHigh, projectId, conn);
@@ -455,7 +464,7 @@ public class TeamcityIgnitedImpl implements ITeamcityIgnited {
     }
 
     /**
-     * Enables scheduleing for build refs/builds/history sync
+     * Enables scheduling for build refs/builds/history sync
      */
     public void ensureActualizeRequested() {
         scheduler.sheduleNamed(taskName("actualizeRecentBuildRefs"), () -> actualizeRecentBuildRefs(srvCode), 2, TimeUnit.MINUTES);
@@ -580,8 +589,9 @@ public class TeamcityIgnitedImpl implements ITeamcityIgnited {
      *
      * @param srvNme TC service name
      */
+    @SuppressWarnings("WeakerAccess")
     @MonitoredTask(name = "Prepare Actualize BuildRefs(srv, full resync)", nameExtArgsIndexes = {0})
-    String actualizeRecentBuildRefs(String srvNme) {
+    protected String actualizeRecentBuildRefs(String srvNme) {
         List<BuildRefCompacted> running = buildRefDao.getQueuedAndRunning(srvIdMaskHigh);
 
         Set<Integer> paginateUntil = new HashSet<>();
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedModule.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/TeamcityIgnitedModule.java
similarity index 84%
rename from tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedModule.java
rename to tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/TeamcityIgnitedModule.java
index 446dc17..a9b5ed3 100644
--- a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedModule.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/TeamcityIgnitedModule.java
@@ -14,13 +14,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.ignite.ci.teamcity.ignited;
+package org.apache.ignite.tcignited;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.internal.SingletonScope;
 import org.apache.ignite.ci.teamcity.ignited.buildcondition.BuildConditionDao;
-import org.apache.ignite.ci.teamcity.ignited.buildref.BuildRefDao;
-import org.apache.ignite.ci.teamcity.ignited.buildref.BuildRefSync;
+import org.apache.ignite.tcignited.buildlog.BuildLogCheckResultDao;
+import org.apache.ignite.tcignited.buildref.BuildRefDao;
+import org.apache.ignite.tcignited.buildref.BuildRefSync;
 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;
@@ -30,11 +31,9 @@ import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildDao;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.ProactiveFatBuildSync;
 import org.apache.ignite.ci.teamcity.ignited.mute.MuteDao;
 import org.apache.ignite.ci.teamcity.ignited.mute.MuteSync;
-import org.apache.ignite.ci.teamcity.ignited.runhist.RunHistCompactedDao;
-import org.apache.ignite.ci.teamcity.ignited.runhist.RunHistSync;
-import org.apache.ignite.tcbot.persistence.IStringCompactor;
-import org.apache.ignite.tcbot.persistence.IgniteStringCompactor;
-import org.apache.ignite.tcignited.ITeamcityIgnitedProvider;
+import org.apache.ignite.tcignited.buildlog.BuildLogProcessorModule;
+import org.apache.ignite.tcignited.history.RunHistCompactedDao;
+import org.apache.ignite.tcignited.history.RunHistSync;
 import org.apache.ignite.tcservice.TcRealConnectionModule;
 import org.apache.ignite.tcservice.http.ITeamcityHttpConnection;
 
@@ -65,14 +64,15 @@ public class TeamcityIgnitedModule extends AbstractModule {
         bind(RunHistSync.class).in(new SingletonScope());
         bind(MuteDao.class).in(new SingletonScope());
         bind(MuteSync.class).in(new SingletonScope());
-
-        bind(IStringCompactor.class).to(IgniteStringCompactor.class).in(new SingletonScope());
+        bind(BuildLogCheckResultDao.class).in(new SingletonScope());
 
         TcRealConnectionModule module = new TcRealConnectionModule();
         if (conn != null)
             module.overrideHttp(conn);
 
         install(module);
+
+        install(new BuildLogProcessorModule());
     }
 
     public void overrideHttp(ITeamcityHttpConnection conn) {
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
new file mode 100644
index 0000000..db4816e
--- /dev/null
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/BuildLogCheckResultDao.java
@@ -0,0 +1,61 @@
+/*
+ * 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.tcignited.buildlog;
+
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.tcbot.persistence.CacheConfigs;
+import org.apache.ignite.tcignited.ITeamcityIgnited;
+import org.apache.ignite.tcignited.buildref.BuildRefDao;
+
+import javax.annotation.Nullable;
+import javax.inject.Inject;
+import javax.inject.Provider;
+
+public class BuildLogCheckResultDao {
+    /** Cache name */
+    public static final String TEAMCITY_CHANGE_CACHE_NAME = "buildLogCheckResult";
+
+    /** Ignite provider. */
+    @Inject
+    private Provider<Ignite> igniteProvider;
+
+    /** Change Compacted cache. */
+    private IgniteCache<Long, LogCheckResultCompacted> logsCache;
+
+    public static long getCacheKey(String serverCode, int buildId) {
+        int serverId = ITeamcityIgnited.serverIdToInt(serverCode);
+
+        return BuildRefDao.buildIdToCacheKey(serverId, buildId);
+    }
+
+    /** */
+    public void init() {
+        CacheConfiguration<Long, LogCheckResultCompacted> cfg = CacheConfigs.getCacheV2Config(TEAMCITY_CHANGE_CACHE_NAME);
+
+        logsCache = igniteProvider.get().getOrCreateCache(cfg);
+    }
+
+    @Nullable public LogCheckResultCompacted get(String srvCode, int buildId) {
+        return logsCache.get(getCacheKey(srvCode, buildId));
+    }
+
+    public void put(String srvCode, int buildId, LogCheckResultCompacted logCheckResultCompacted) {
+        logsCache.put(getCacheKey(srvCode, buildId), logCheckResultCompacted);
+    }
+}
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/BuildLogProcessor.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/BuildLogProcessor.java
new file mode 100644
index 0000000..58dbeed
--- /dev/null
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/BuildLogProcessor.java
@@ -0,0 +1,138 @@
+/*
+ * 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.tcignited.buildlog;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import org.apache.ignite.tcbot.common.exeption.ExceptionUtil;
+import org.apache.ignite.tcbot.common.interceptor.AutoProfiling;
+import org.apache.ignite.tcignited.ITeamcityIgnited;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nullable;
+import javax.inject.Inject;
+import javax.inject.Provider;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+class BuildLogProcessor implements IBuildLogProcessor {
+    /** Logger. */
+    private static final Logger logger = LoggerFactory.getLogger(BuildLogProcessor.class);
+
+    @Inject
+    private Provider<LogCheckTask> taskProvider;
+
+    @Inject
+    private BuildLogCheckResultDao logCheckResultDao;
+
+    /** Non persistence cache for log check results. */
+    private final Cache<Long, ILogCheckResult> logCheckResultCache
+            = CacheBuilder.newBuilder()
+            .maximumSize(500)
+            .expireAfterAccess(3, TimeUnit.MINUTES)
+            .softValues()
+            .build();
+
+
+    @Override
+    public ILogCheckResult analyzeBuildLog(ITeamcityIgnited teamcity, int buildId, boolean dumpLastTest) {
+        long cacheKey = BuildLogCheckResultDao.getCacheKey(teamcity.serverCode(), buildId);
+
+        try {
+            return logCheckResultCache.get(cacheKey, () -> {
+                LogCheckResultCompacted val = logCheckResultDao.get(teamcity.serverCode(), buildId);
+                if (val != null)
+                    return val;
+
+                LogCheckResultCompacted logCheckResultCompacted;
+                try {
+                    logCheckResultCompacted = checkBuildLogNoCache(teamcity, buildId, dumpLastTest);
+                } catch (Exception e)   {
+                    final String msg = "Failed to process Build Log entry " + teamcity.serverCode() + "/" + buildId ;
+
+                    System.err.println(msg + ": " + e.getClass().getSimpleName() + ": " + e.getMessage());
+
+                    logger.error(msg, e);
+
+                    //protecting from retrying for invalid build log.
+                    logCheckResultCompacted = new LogCheckResultCompacted();
+                }
+
+                logCheckResultDao.put(teamcity.serverCode(), buildId, logCheckResultCompacted);
+
+                return logCheckResultCompacted;
+            });
+        } catch (ExecutionException e) {
+            throw ExceptionUtil.propagateException(e);
+        }
+    }
+
+    @Nullable
+    @Override
+    public String getThreadDumpCached(String serverCode, Integer buildId) {
+        LogCheckResultCompacted logCheckResultCompacted = logCheckResultDao.get(serverCode, buildId);
+
+        if(logCheckResultCompacted==null)
+            return null;
+
+        return logCheckResultCompacted.getLastThreadDump();
+    }
+
+
+    private LogCheckResultCompacted checkBuildLogNoCache(ITeamcityIgnited teamcity, int buildId, boolean dumpLastTest) throws IOException {
+        File zipFile = teamcity.downloadAndCacheBuildLog(buildId);
+
+        if (zipFile == null)
+            return null;
+
+        return runCheckForZippedLog(dumpLastTest, zipFile);
+    }
+
+
+    @SuppressWarnings("WeakerAccess")
+    @AutoProfiling
+    @Nullable
+    protected LogCheckResultCompacted runCheckForZippedLog(boolean dumpLastTest, File zipFile) throws IOException {
+        LogCheckTask task = taskProvider.get();
+
+
+            //get the zip file content
+            try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile))) {
+                ZipEntry ze = zis.getNextEntry();    //get the zipped file list entry
+
+                while (ze != null) {
+                    BuildLogStreamChecker checker = task.createChecker();
+                    checker.apply(zis, zipFile);
+                    LogCheckResultCompacted finalize = task.finalize(dumpLastTest);
+                    if (finalize != null)
+                        return finalize;
+
+                    ze = zis.getNextEntry();
+                }
+                zis.closeEntry();
+            }
+
+
+        return null;
+    }
+}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITcAnalytics.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/BuildLogProcessorModule.java
similarity index 70%
rename from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITcAnalytics.java
rename to tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/BuildLogProcessorModule.java
index c4e8155..aa0f5ba 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITcAnalytics.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/BuildLogProcessorModule.java
@@ -14,10 +14,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.ignite.tcignited.buildlog;
 
-package org.apache.ignite.ci;
+import com.google.inject.AbstractModule;
+import com.google.inject.internal.SingletonScope;
 
-@Deprecated
-public interface ITcAnalytics {
-    String getThreadDumpCached(Integer buildId);
+public class BuildLogProcessorModule extends AbstractModule {
+    @Override
+    protected void configure() {
+        bind(IBuildLogProcessor.class).to(BuildLogProcessor.class).in(new SingletonScope());
+    }
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/BuildLogStreamChecker.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/BuildLogStreamChecker.java
similarity index 89%
rename from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/BuildLogStreamChecker.java
rename to tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/BuildLogStreamChecker.java
index 5cd8592..7c71e84 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/BuildLogStreamChecker.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/BuildLogStreamChecker.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.ci.logs;
+package org.apache.ignite.tcignited.buildlog;
 
 import java.io.BufferedReader;
 import java.io.File;
@@ -30,15 +30,14 @@ import java.util.zip.ZipInputStream;
 /**
  * Use one instance per one stream, class is statefull and not thread safe
  */
-public class BuildLogStreamChecker {
-
+class BuildLogStreamChecker {
     private final List<ILineHandler> lineHandlersList;
 
-    public BuildLogStreamChecker(ILineHandler... lineHandlers) {
+    BuildLogStreamChecker(ILineHandler... lineHandlers) {
         lineHandlersList = Arrays.asList(lineHandlers);
     }
 
-    public void apply(ZipInputStream zipInputStream, File zipFile) {
+    void apply(ZipInputStream zipInputStream, File zipFile) {
         Reader reader = new InputStreamReader(zipInputStream, StandardCharsets.UTF_8);
 
         try (Stream<String> lines = new BufferedReader(reader).lines()) {
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/ILineHandler.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/IBuildLogProcessor.java
similarity index 68%
copy from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/ILineHandler.java
copy to tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/IBuildLogProcessor.java
index 2af9c2f..6816004 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/ILineHandler.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/IBuildLogProcessor.java
@@ -14,14 +14,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.ignite.tcignited.buildlog;
 
-package org.apache.ignite.ci.logs;
+import org.apache.ignite.tcignited.ITeamcityIgnited;
 
-import java.io.File;
+import javax.annotation.Nullable;
 
-/**
- *
- */
-public interface ILineHandler extends AutoCloseable {
-    public void accept(String line, File file);
+public interface IBuildLogProcessor {
+    public ILogCheckResult analyzeBuildLog(ITeamcityIgnited teamcity, int buildId, boolean dumpLastTest);
+
+
+    @Nullable
+    public String getThreadDumpCached(String serverCode, Integer buildId);
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/ILineHandler.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/ILineHandler.java
similarity index 95%
copy from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/ILineHandler.java
copy to tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/ILineHandler.java
index 2af9c2f..784b18a 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/ILineHandler.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/ILineHandler.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.ci.logs;
+package org.apache.ignite.tcignited.buildlog;
 
 import java.io.File;
 
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/ILineHandler.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/ILogCheckResult.java
similarity index 61%
rename from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/ILineHandler.java
rename to tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/ILogCheckResult.java
index 2af9c2f..9821b26 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/ILineHandler.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/ILogCheckResult.java
@@ -14,14 +14,23 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.ignite.tcignited.buildlog;
 
-package org.apache.ignite.ci.logs;
+import org.apache.ignite.tcbot.persistence.IStringCompactor;
 
-import java.io.File;
+import javax.annotation.Nonnull;
+import java.util.Map;
+import java.util.Set;
 
-/**
- *
- */
-public interface ILineHandler extends AutoCloseable {
-    public void accept(String line, File file);
+public interface ILogCheckResult {
+    @Nonnull
+    public Set<String> getCustomProblems(IStringCompactor compactor);
+
+    public String getLastStartedTest(IStringCompactor compactor);
+
+    public Map<String, ITestLogCheckResult> getTestLogCheckResult();
+
+    boolean hasThreadDump();
+
+    String getLastThreadDump();
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/ILogProductSpecific.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/ILogProductSpecific.java
similarity index 95%
rename from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/ILogProductSpecific.java
rename to tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/ILogProductSpecific.java
index 64ecb78..9950fbe 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/ILogProductSpecific.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/ILogProductSpecific.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.ci.logs;
+package org.apache.ignite.tcignited.buildlog;
 
 /**
  *
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IAnalyticsEnabledTeamcity.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/ITestLogCheckResult.java
similarity index 72%
rename from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IAnalyticsEnabledTeamcity.java
rename to tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/ITestLogCheckResult.java
index 47eda4d..5db50b0 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IAnalyticsEnabledTeamcity.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/ITestLogCheckResult.java
@@ -14,15 +14,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.ignite.tcignited.buildlog;
 
-package org.apache.ignite.ci;
+import javax.annotation.Nonnull;
+import java.util.List;
 
-import org.apache.ignite.tcservice.ITeamcity;
+public interface ITestLogCheckResult {
+    public int getLogSizeBytes();
 
-/**
- * Combination of REST data and persisted statistics.
- */
-@Deprecated
-public interface IAnalyticsEnabledTeamcity extends ITeamcity, ITcAnalytics {
-    public void init(ITeamcity conn);
+    @Nonnull
+    public List<String> getWarns();
+
+    public default boolean hasWarns() {
+        return !getWarns().isEmpty();
+    }
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/LogCheckResult.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/LogCheckResultCompacted.java
similarity index 54%
rename from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/LogCheckResult.java
rename to tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/LogCheckResultCompacted.java
index 6bdce53..e3eca05 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/LogCheckResult.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/LogCheckResultCompacted.java
@@ -15,56 +15,59 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.ci.analysis;
+package org.apache.ignite.tcignited.buildlog;
 
 import com.google.common.base.MoreObjects;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.TreeSet;
-import javax.annotation.Nonnull;
-
+import org.apache.ignite.ci.tcbot.common.StringFieldCompacted;
+import org.apache.ignite.tcbot.persistence.IStringCompactor;
 import org.apache.ignite.tcbot.persistence.IVersionedEntity;
 import org.apache.ignite.tcbot.persistence.Persisted;
-import org.jetbrains.annotations.Nullable;
+import org.apache.ignite.tcignited.ITeamcityIgnited;
+import org.apache.ignite.tcignited.buildref.BuildRefDao;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * Persistable Log from suite run check task result.
  */
 @Persisted
-public class LogCheckResult implements IVersionedEntity {
+class LogCheckResultCompacted implements ILogCheckResult, IVersionedEntity {
     /** Latest version. */
-    private static final int LATEST_VERSION = 6;
+    private static final int LATEST_VERSION = 7;
 
     /** Entity version. */
     @SuppressWarnings("FieldCanBeLocal") private Integer _version = LATEST_VERSION;
 
     /** Last started test. Optionally filled from log post processor */
-    private String lastStartedTest;
+    private int lastStartedTest = -1;
 
     /** Last thread dump. */
-    private String lastThreadDump;
+    private StringFieldCompacted lastThreadDump = new StringFieldCompacted();
 
     /**
      * Test name -> its log check results
      */
-    private Map<String, TestLogCheckResult> testLogCheckResult = new TreeMap<>();
+    private Map<String, TestLogCheckResultCompacted> testLogCheckResult = new TreeMap<>();
 
     @Nullable
-    private Set<String> buildCustomProblems = null;
+    private Set<Integer> buildCustomProblems = null;
 
-    public void setLastStartedTest(String lastStartedTest) {
-        this.lastStartedTest = lastStartedTest;
+    void setLastStartedTest(String lastStartedTest, IStringCompactor compactor) {
+        this.lastStartedTest = compactor.getStringId(lastStartedTest);
     }
 
-    public void setLastThreadDump(String lastThreadDump) {
-        this.lastThreadDump = lastThreadDump;
+    void setLastThreadDump(String lastThreadDump) {
+        this.lastThreadDump.setValue(lastThreadDump);
     }
 
-    public String getLastStartedTest() {
-        return lastStartedTest;
+    public String getLastStartedTest(IStringCompactor compactor) {
+        if (lastStartedTest > 0)
+            return compactor.getStringFromId(lastStartedTest);
+
+        return null;
     }
 
     /** {@inheritDoc} */
@@ -78,7 +81,7 @@ public class LogCheckResult implements IVersionedEntity {
     }
 
     public String getLastThreadDump() {
-        return lastThreadDump;
+        return lastThreadDump.getValue();
     }
 
     /** {@inheritDoc} */
@@ -110,29 +113,47 @@ public class LogCheckResult implements IVersionedEntity {
         return sb.toString();
     }
 
-    public Map<String, TestLogCheckResult> getTestLogCheckResult() {
+    public Map<String, ITestLogCheckResult> getTestLogCheckResult() {
         return Collections.unmodifiableMap(testLogCheckResult);
     }
 
-    public TestLogCheckResult getOrCreateTestResult(String name) {
-        return testLogCheckResult.computeIfAbsent(name, k -> new TestLogCheckResult());
+    @Override
+    public boolean hasThreadDump() {
+        return lastThreadDump.isFilled();
     }
 
-    public void addProblem(String code) {
+    TestLogCheckResultCompacted getOrCreateTestResult(String name) {
+        return testLogCheckResult.computeIfAbsent(name, k -> new TestLogCheckResultCompacted());
+    }
+
+    public void addProblem(String code, IStringCompactor compactor) {
         if (buildCustomProblems == null)
             buildCustomProblems = new TreeSet<>();
 
-        buildCustomProblems.add(code);
+        int problemId = compactor.getStringId(code);
+        buildCustomProblems.add(problemId);
     }
 
-    public boolean hasProblem(String deadlock) {
-        return buildCustomProblems != null && buildCustomProblems.contains(deadlock);
+    boolean hasProblem(String code, IStringCompactor compactor) {
+        if (buildCustomProblems == null)
+            return false;
+
+        Integer stringIdIfPresent = compactor.getStringIdIfPresent(code);
+        if (stringIdIfPresent == null)
+            return false;
+
+        return buildCustomProblems.contains(stringIdIfPresent);
     }
 
     /**
      *
      */
-    @Nonnull public Set<String> getCustomProblems() {
-        return buildCustomProblems == null ? Collections.emptySet() : Collections.unmodifiableSet(buildCustomProblems);
+    @Nonnull public Set<String> getCustomProblems(IStringCompactor compactor) {
+        return buildCustomProblems == null
+                ? Collections.emptySet()
+                : buildCustomProblems
+                .stream()
+                .map(compactor::getStringFromId)
+                .collect(Collectors.toSet());
     }
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/LogCheckTask.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/LogCheckTask.java
similarity index 67%
rename from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/LogCheckTask.java
rename to tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/LogCheckTask.java
index eedb5d2..ded6c41 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/LogCheckTask.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/LogCheckTask.java
@@ -15,31 +15,33 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.ci.analysis;
+package org.apache.ignite.tcignited.buildlog;
 
-import java.io.File;
-import org.apache.ignite.ci.logs.BuildLogStreamChecker;
-import org.apache.ignite.ci.logs.handlers.TestLogHandler;
-import org.apache.ignite.ci.logs.handlers.ThreadDumpInMemoryHandler;
+
+import org.apache.ignite.tcbot.persistence.IStringCompactor;
+
+import javax.inject.Inject;
 
 import static org.apache.ignite.tcservice.model.result.problems.ProblemOccurrence.JAVA_LEVEL_DEADLOCK;
 
 /**
  *
  */
-public class LogCheckTask {
-    LogCheckResult result;
-    private File zipFile;
+class LogCheckTask {
+    private LogCheckResultCompacted result;
     final ThreadDumpInMemoryHandler threadDumpCp = new ThreadDumpInMemoryHandler();
 
     /** Test logger handler. */
-    final TestLogHandler testLogHandler = new TestLogHandler();
+    @Inject
+    private TestLogHandler testLogHandler;
+
+    @Inject
+    private IStringCompactor compactor;
 
-    public LogCheckTask(File zipFile) {
-        this.zipFile = zipFile;
+    public LogCheckTask() {
     }
 
-    public LogCheckResult getResult() {
+    public LogCheckResultCompacted getResult() {
         return result;
     }
 
@@ -47,14 +49,16 @@ public class LogCheckTask {
         return new BuildLogStreamChecker(threadDumpCp, testLogHandler);
     }
 
-    public void finalize(boolean isIncompleteSuite) {
-        LogCheckResult logCheckRes = testLogHandler.getResult(isIncompleteSuite);
+    public LogCheckResultCompacted finalize(boolean isIncompleteSuite) {
+        LogCheckResultCompacted logCheckRes = testLogHandler.getResult(isIncompleteSuite);
 
         if (isIncompleteSuite)
             logCheckRes.setLastThreadDump(threadDumpCp.getLastThreadDump());
-        else if (logCheckRes.hasProblem(JAVA_LEVEL_DEADLOCK))
+        else if (logCheckRes.hasProblem(JAVA_LEVEL_DEADLOCK, compactor))
             logCheckRes.setLastThreadDump(threadDumpCp.getLastThreadDump());
 
         this.result = logCheckRes;
+
+        return result;
     }
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/LogIgniteSpecific.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/LogIgniteSpecific.java
similarity index 97%
rename from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/LogIgniteSpecific.java
rename to tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/LogIgniteSpecific.java
index a053c25..3f2f227 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/LogIgniteSpecific.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/LogIgniteSpecific.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.ci.logs;
+package org.apache.ignite.tcignited.buildlog;
 
 /**
  * Ignite specific logic related to build logs.
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/LogMsgToWarn.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/LogMsgToWarn.java
similarity index 97%
rename from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/LogMsgToWarn.java
rename to tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/LogMsgToWarn.java
index bd302df..2580dba 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/LogMsgToWarn.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/LogMsgToWarn.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.ci.logs;
+package org.apache.ignite.tcignited.buildlog;
 
 import javax.annotation.Nullable;
 import org.apache.ignite.tcservice.model.result.problems.ProblemOccurrence;
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/LogsAnalyzer.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/LogsAnalyzer.java
similarity index 98%
rename from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/LogsAnalyzer.java
rename to tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/LogsAnalyzer.java
index c9a0529..460032d 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/LogsAnalyzer.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/LogsAnalyzer.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.ci.logs;
+package org.apache.ignite.tcignited.buildlog;
 
 import java.io.File;
 import java.io.IOException;
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/TestLogCheckResult.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/TestLogCheckResultCompacted.java
similarity index 67%
rename from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/TestLogCheckResult.java
rename to tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/TestLogCheckResultCompacted.java
index 51413e1..98640a4 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/TestLogCheckResult.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/TestLogCheckResultCompacted.java
@@ -15,41 +15,45 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.ci.analysis;
+package org.apache.ignite.tcignited.buildlog;
 
+import org.apache.ignite.ci.tcbot.common.StringFieldCompacted;
+import org.apache.ignite.tcbot.persistence.Persisted;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-import javax.annotation.Nullable;
-import javax.validation.constraints.NotNull;
-import org.apache.ignite.tcbot.persistence.Persisted;
+import java.util.stream.Collectors;
 
 @Persisted
-public class TestLogCheckResult {
+class TestLogCheckResultCompacted implements ITestLogCheckResult {
     /** Warnings found. */
-    @Nullable List<String> warns;
+    @Nullable
+    private List<StringFieldCompacted> warns;
 
     /** Count of lines. */
-    int cntLines = 0;
+    private int cntLines = 0;
 
     /** Count of bytes. */
 
-    int cntBytes = 0;
+    private int cntBytes = 0;
 
-    public void addWarning(String line) {
+    void addWarning(String line) {
         if (warns == null)
             warns = new ArrayList<>();
 
-        warns.add(line);
+        warns.add(new StringFieldCompacted(line));
     }
 
-    @NotNull public List<String> getWarns() {
-        return warns == null ? Collections.emptyList() : warns;
+    @Nonnull
+    public List<String> getWarns() {
+        return warns == null
+                ? Collections.emptyList()
+                : warns.stream().map(StringFieldCompacted::getValue).collect(Collectors.toList());
     }
 
-    public boolean hasWarns() {
-        return warns != null && !warns.isEmpty();
-    }
 
     public void addLineStat(String line) {
         int i = line.length() + 1; //here suppose UTF-8, 1 byte per char; 1 newline char
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/handlers/TestLogHandler.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/TestLogHandler.java
similarity index 51%
rename from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/handlers/TestLogHandler.java
rename to tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/TestLogHandler.java
index 6e66882..87e9332 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/handlers/TestLogHandler.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/TestLogHandler.java
@@ -15,20 +15,12 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.ci.logs.handlers;
+package org.apache.ignite.tcignited.buildlog;
 
 import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.ignite.ci.analysis.LogCheckResult;
-import org.apache.ignite.ci.analysis.TestLogCheckResult;
-import org.apache.ignite.ci.logs.ILineHandler;
-import org.apache.ignite.ci.logs.ILogProductSpecific;
-import org.apache.ignite.ci.logs.LogIgniteSpecific;
-import org.apache.ignite.ci.logs.LogMsgToWarn;
+import org.apache.ignite.tcbot.persistence.IStringCompactor;
+
+import javax.inject.Inject;
 
 /**
  * Use one instance per one file, class is statefull and not thread safe
@@ -36,22 +28,18 @@ import org.apache.ignite.ci.logs.LogMsgToWarn;
 public class TestLogHandler implements ILineHandler {
     private static final String STARTING_TEST = ">>> Starting test: ";
     private static final String TEST_NAME_END = " <<<";
-    private static final String ENDL = String.format("%n");
 
     private static final ILogProductSpecific logSpecific = new LogIgniteSpecific();
-    public static final TestLogCheckResult FAKE_RESULT = new TestLogCheckResult();
-    private final List<String> curTestLog = new ArrayList<>();
+    public static final TestLogCheckResultCompacted FAKE_RESULT = new TestLogCheckResultCompacted();
 
     private String currentTestName = null;
     private File workFolder;
 
-    /** Dump last test. This mode is enabled if suite was timed out */
-    private boolean saveLastTestToFile;
-
-    private static boolean SAVE_LOG_STAT = true;
-
     /** Result. */
-    private LogCheckResult res = new LogCheckResult();
+    private LogCheckResultCompacted res = new LogCheckResultCompacted();
+
+    @Inject
+    private IStringCompactor compactor;
 
     @Override public void accept(String line, File fromLogFile) {
         if (workFolder == null)
@@ -60,7 +48,6 @@ public class TestLogHandler implements ILineHandler {
         if (logSpecific.isTestStarting(line)) {
             if (currentTestName != null) {
                 currentTestName = null;
-                curTestLog.clear();
             }
             String startTest = line.substring(line.indexOf(STARTING_TEST) + STARTING_TEST.length(), line.indexOf(TEST_NAME_END));
 
@@ -68,14 +55,13 @@ public class TestLogHandler implements ILineHandler {
         }
         else if (currentTestName != null && logSpecific.isTestStopping(line)) {
             //currentTestName = null;
-            //curTestLog.clear();
+
         }
 
         if (currentTestName == null)
             return;
 
-        if (SAVE_LOG_STAT)
-            curTest().addLineStat(line);
+        curTest().addLineStat(line);
 
         if (LogMsgToWarn.needWarn(line))
             curTest().addWarning(line);
@@ -83,23 +69,10 @@ public class TestLogHandler implements ILineHandler {
         String problemCode = LogMsgToWarn.getProblemCode(line);
 
         if (problemCode != null)
-            res.addProblem(problemCode);
-
-        if (!saveLastTestToFile)
-            return;
-
-        curTestLog.add(line);
-
-        if (currentTestName != null) {
-            if (line.contains("Test has been timed out [")) {
-                dumpCurrentToFile("timedOut_");
-                currentTestName = null;
-                curTestLog.clear();
-            }
-        }
+            res.addProblem(problemCode, compactor);
     }
 
-    private TestLogCheckResult curTest() {
+    private TestLogCheckResultCompacted curTest() {
         String curName = getLastTestName();
 
         return curName == null ? FAKE_RESULT : res.getOrCreateTestResult(curName);
@@ -107,34 +80,7 @@ public class TestLogHandler implements ILineHandler {
 
     /** {@inheritDoc} */
     @Override public void close() {
-        if (saveLastTestToFile && currentTestName != null && !curTestLog.isEmpty())
-            dumpCurrentToFile("lastStartedTest_");
-
-    }
-
-    private void dumpCurrentToFile(String logPrefix) {
-        try {
-            dumpCurrentToFileX(logPrefix);
-        }
-        catch (IOException e) {
-            throw new UncheckedIOException(e);
-        }
-    }
 
-    private void dumpCurrentToFileX(String logPrefix) throws IOException {
-        String name = getLastTestName();
-        try (FileWriter writer = new FileWriter(new File(workFolder, logPrefix + name + ".log"))) {
-            curTestLog.forEach(line -> {
-                try {
-                    writer.write(line);
-                    writer.write(ENDL);
-                }
-                catch (IOException e) {
-                    throw new UncheckedIOException(e);
-                }
-            });
-        }
-        curTestLog.clear();
     }
 
     /**
@@ -153,13 +99,9 @@ public class TestLogHandler implements ILineHandler {
         return str;
     }
 
-    public void setSaveLastTestToFile(boolean saveLastTestToFile) {
-        this.saveLastTestToFile = saveLastTestToFile;
-    }
-
-    public LogCheckResult getResult(boolean isIncompleteSuite) {
+    public LogCheckResultCompacted getResult(boolean isIncompleteSuite) {
         if (isIncompleteSuite)
-            res.setLastStartedTest(getLastTestName());
+            res.setLastStartedTest(getLastTestName(), compactor);
 
         return res;
     }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/handlers/ThreadDumpInMemoryHandler.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/ThreadDumpInMemoryHandler.java
similarity index 95%
rename from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/handlers/ThreadDumpInMemoryHandler.java
rename to tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/ThreadDumpInMemoryHandler.java
index f9b6aff..5e0e390 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/logs/handlers/ThreadDumpInMemoryHandler.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/ThreadDumpInMemoryHandler.java
@@ -15,11 +15,10 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.ci.logs.handlers;
+package org.apache.ignite.tcignited.buildlog;
 
 import java.io.File;
 import javax.annotation.Nullable;
-import org.apache.ignite.ci.logs.ILineHandler;
 
 /**
  * Saves last observed thread dump. Use one instance per one file, class is stateful and not thread safe
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/buildref/BuildRefDao.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildref/BuildRefDao.java
similarity index 99%
rename from tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/buildref/BuildRefDao.java
rename to tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildref/BuildRefDao.java
index bbd0cdc..a4c73d4 100644
--- a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/buildref/BuildRefDao.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildref/BuildRefDao.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.ci.teamcity.ignited.buildref;
+package org.apache.ignite.tcignited.buildref;
 
 import java.util.*;
 import java.util.stream.Collectors;
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/buildref/BuildRefSync.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildref/BuildRefSync.java
similarity index 98%
rename from tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/buildref/BuildRefSync.java
rename to tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildref/BuildRefSync.java
index bf35c19..05c3d2d 100644
--- a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/buildref/BuildRefSync.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildref/BuildRefSync.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.ignite.ci.teamcity.ignited.buildref;
+package org.apache.ignite.tcignited.buildref;
 
 import org.apache.ignite.tcbot.common.interceptor.AutoProfiling;
 import org.apache.ignite.tcbot.common.interceptor.MonitoredTask;
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/runhist/RunHistCompactedDao.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/history/RunHistCompactedDao.java
similarity index 96%
rename from tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/runhist/RunHistCompactedDao.java
rename to tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/history/RunHistCompactedDao.java
index 1891e97..92d0544 100644
--- a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/runhist/RunHistCompactedDao.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/history/RunHistCompactedDao.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.ci.teamcity.ignited.runhist;
+package org.apache.ignite.tcignited.history;
 
 import java.util.Collections;
 import java.util.List;
@@ -32,15 +32,16 @@ import org.apache.ignite.IgniteCluster;
 import org.apache.ignite.cache.QueryEntity;
 import org.apache.ignite.cache.query.QueryCursor;
 import org.apache.ignite.cache.query.SqlQuery;
+import org.apache.ignite.ci.teamcity.ignited.runhist.Invocation;
+import org.apache.ignite.ci.teamcity.ignited.runhist.RunHistCompacted;
+import org.apache.ignite.ci.teamcity.ignited.runhist.RunHistKey;
 import org.apache.ignite.tcbot.common.interceptor.AutoProfiling;
-import org.apache.ignite.tcignited.history.IRunHistory;
-import org.apache.ignite.tcignited.history.IRunStat;
 import org.apache.ignite.tcbot.persistence.IStringCompactor;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.tcbot.common.interceptor.GuavaCached;
 import org.apache.ignite.tcbot.persistence.CacheConfigs;
 
-import static org.apache.ignite.ci.teamcity.ignited.runhist.RunHistSync.normalizeBranch;
+import static org.apache.ignite.tcignited.history.RunHistSync.normalizeBranch;
 
 /**
  *
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/runhist/RunHistSync.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/history/RunHistSync.java
similarity index 97%
rename from tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/runhist/RunHistSync.java
rename to tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/history/RunHistSync.java
index 99708c5..7212243 100644
--- a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/ci/teamcity/ignited/runhist/RunHistSync.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/history/RunHistSync.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.ci.teamcity.ignited.runhist;
+package org.apache.ignite.tcignited.history;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -34,6 +34,9 @@ import javax.annotation.Nullable;
 import javax.annotation.concurrent.GuardedBy;
 import javax.inject.Inject;
 
+import org.apache.ignite.ci.teamcity.ignited.runhist.Invocation;
+import org.apache.ignite.ci.teamcity.ignited.runhist.InvocationData;
+import org.apache.ignite.ci.teamcity.ignited.runhist.RunHistKey;
 import org.apache.ignite.tcbot.common.conf.ITcServerConfigSupplier;
 import org.apache.ignite.tcbot.common.interceptor.MonitoredTask;
 import org.apache.ignite.tcbot.persistence.scheduler.IScheduler;
@@ -43,7 +46,7 @@ import org.apache.ignite.tcbot.common.interceptor.AutoProfiling;
 import org.apache.ignite.tcbot.common.conf.TcBotSystemProperties;
 import org.apache.ignite.tcbot.persistence.IStringCompactor;
 import org.apache.ignite.tcignited.ITeamcityIgnited;
-import org.apache.ignite.ci.teamcity.ignited.buildref.BuildRefDao;
+import org.apache.ignite.tcignited.buildref.BuildRefDao;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildDao;
 import org.slf4j.Logger;
diff --git a/tcbot-teamcity/README.md b/tcbot-teamcity/README.md
index d3bbe1c..839b090 100644
--- a/tcbot-teamcity/README.md
+++ b/tcbot-teamcity/README.md
@@ -1,3 +1,4 @@
-TC Bot Teamcity (service module).
+TC Bot Teamcity (service) module
+--------------------------------
 
-Module for pure (non cached) requests to TeamCity services
\ No newline at end of file
+Module for pure (non cached) requests to TeamCity service
\ No newline at end of file
diff --git a/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/ITeamcityConn.java b/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/ITeamcityConn.java
index 24738fc..fc362ef 100644
--- a/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/ITeamcityConn.java
+++ b/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/ITeamcityConn.java
@@ -17,7 +17,9 @@
 
 package org.apache.ignite.tcservice;
 
+import java.io.File;
 import java.io.FileNotFoundException;
+import java.io.IOException;
 import java.io.UncheckedIOException;
 import java.util.List;
 import java.util.Map;
@@ -25,6 +27,8 @@ import java.util.SortedSet;
 import java.util.concurrent.atomic.AtomicReference;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
+
+import org.apache.ignite.tcbot.common.interceptor.AutoProfiling;
 import org.apache.ignite.tcservice.model.agent.Agent;
 import org.apache.ignite.tcservice.model.changes.Change;
 import org.apache.ignite.tcservice.model.changes.ChangesList;
@@ -167,4 +171,15 @@ public interface ITeamcityConn {
      * @return List of teamcity agents.
      */
     public List<Agent> agents(boolean connected, boolean authorized);
+
+    /**
+     * @param buildId
+     * @return
+     *
+     * @throws UncheckedIOException caused by IOException If communication failed.
+     * @throws UncheckedIOException caused by FileNotFoundException If not found (404) was returned from service.
+     * @throws ServiceConflictException If conflict (409) was returned from service.
+     * @throws IllegalStateException if some unexpected HTTP error returned.
+     */
+    @Nullable public File downloadAndCacheBuildLog(int buildId);
 }
diff --git a/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/TeamcityServiceConnection.java b/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/TeamcityServiceConnection.java
index 04c74b8..3710139 100644
--- a/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/TeamcityServiceConnection.java
+++ b/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/TeamcityServiceConnection.java
@@ -19,6 +19,14 @@ package org.apache.ignite.tcservice;
 
 import com.google.common.base.Strings;
 import com.google.common.util.concurrent.MoreExecutors;
+import org.apache.ignite.tcbot.common.conf.ITcServerConfig;
+import org.apache.ignite.tcbot.common.conf.ITcServerConfigSupplier;
+import org.apache.ignite.tcbot.common.conf.TcBotWorkDir;
+import org.apache.ignite.tcbot.common.exeption.ExceptionUtil;
+import org.apache.ignite.tcbot.common.exeption.ServiceConflictException;
+import org.apache.ignite.tcbot.common.interceptor.AutoProfiling;
+import org.apache.ignite.tcbot.common.util.HttpUtil;
+import org.apache.ignite.tcservice.http.ITeamcityHttpConnection;
 import org.apache.ignite.tcservice.model.agent.Agent;
 import org.apache.ignite.tcservice.model.agent.AgentsRef;
 import org.apache.ignite.tcservice.model.changes.Change;
@@ -37,15 +45,7 @@ import org.apache.ignite.tcservice.model.result.stat.Statistics;
 import org.apache.ignite.tcservice.model.result.tests.TestOccurrencesFull;
 import org.apache.ignite.tcservice.model.user.User;
 import org.apache.ignite.tcservice.model.user.Users;
-import org.apache.ignite.tcservice.http.ITeamcityHttpConnection;
 import org.apache.ignite.tcservice.util.XmlUtil;
-import org.apache.ignite.tcbot.common.conf.ITcServerConfig;
-import org.apache.ignite.tcbot.common.conf.ITcServerConfigSupplier;
-import org.apache.ignite.tcbot.common.conf.TcBotWorkDir;
-import org.apache.ignite.tcbot.common.exeption.ExceptionUtil;
-import org.apache.ignite.tcbot.common.exeption.ServiceConflictException;
-import org.apache.ignite.tcbot.common.interceptor.AutoProfiling;
-import org.apache.ignite.tcbot.common.util.HttpUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -121,29 +121,36 @@ public class TeamcityServiceConnection implements ITeamcity {
             .collect(Collectors.toList());
     }
 
+    /** {@inheritDoc} */
     @AutoProfiling
+    @Deprecated
     public CompletableFuture<File> downloadBuildLogZip(int buildId) {
-        Supplier<File> supplier = () -> {
-            String buildIdStr = Integer.toString(buildId);
-            final File buildDir = TcBotWorkDir.ensureDirExist(new File(logsDir(), "buildId" + buildIdStr));
-            final File file = new File(buildDir, "build.log.zip");
-            if (file.exists() && file.canRead() && file.length() > 0) {
-                logger.info("Nothing to do, file is cached locally: [" + file + "]");
-
-                return file;
-            }
-            String url = host() + "downloadBuildLog.html" + "?buildId=" + buildIdStr + "&archived=true";
+        Supplier<File> supplier = () -> downloadAndCacheBuildLog(buildId);
+
+        return supplyAsync(supplier, executor);
+    }
+
+
+    /** {@inheritDoc} */
+    @AutoProfiling
+    public File downloadAndCacheBuildLog(int buildId) {
+        String buildIdStr = Integer.toString(buildId);
+        File file = new File(logsDir(), "build" + buildIdStr + ".log.zip");
+
+        if (file.exists() && file.canRead() && file.length() > 0) {
+            logger.info("Nothing to do, file is cached locally: [" + file + "]");
 
-            try {
-                HttpUtil.sendGetCopyToFile(basicAuthTok, url, file);
-            }
-            catch (IOException e) {
-                throw new UncheckedIOException(e);
-            }
             return file;
-        };
+        }
+        String url = host() + "downloadBuildLog.html" + "?buildId=" + buildIdStr + "&archived=true";
 
-        return supplyAsync(supplier, executor);
+        try {
+            HttpUtil.sendGetCopyToFile(basicAuthTok, url, file);
+        }
+        catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+        return file;
     }
 
     private static File resolveLogs(File workDir, String logsProp) {