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 998ccee  IGNITE-10071 Fix for case then background upload of a build 
and simultaneous bot restart may result in a queued build persisted but 
actually build is finished - Fixes #86.
998ccee is described below

commit 998cceeaffd9699b741dcac308bd9ee869ae8ea7
Author: Dmitriy Pavlov <[email protected]>
AuthorDate: Mon Dec 3 18:53:48 2018 +0300

    IGNITE-10071 Fix for case then background upload of a build and 
simultaneous bot restart may result in a queued build persisted but actually 
build is finished - Fixes #86.
    
    Signed-off-by: Dmitriy Pavlov <[email protected]>
---
 .../apache/ignite/ci/IgnitePersistentTeamcity.java |   2 +
 .../org/apache/ignite/ci/jobs/CheckQueueJob.java   |   1 -
 .../ignite/ci/teamcity/ignited/BuildRefDao.java    |  16 ++-
 .../ci/teamcity/ignited/ITeamcityIgnited.java      |   5 +-
 .../ci/teamcity/ignited/TeamcityIgnitedImpl.java   |  12 +--
 .../ignited/fatbuild/FatBuildCompacted.java        |   4 +-
 .../ci/teamcity/ignited/fatbuild/FatBuildDao.java  |   8 +-
 .../ignited/fatbuild/ProactiveFatBuildSync.java    |  78 ++++++++++----
 .../ignite/ci/teamcity/pure/ITeamcityConn.java     |   2 +-
 .../org/apache/ignite/ci/web/model/Version.java    |   2 +-
 .../ignited/IgnitedTcInMemoryIntegrationTest.java  | 113 +++++++++++++++++++++
 11 files changed, 200 insertions(+), 43 deletions(-)

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
index 8ebc749..4b256ce 100644
--- 
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
@@ -89,6 +89,8 @@ public class IgnitePersistentTeamcity implements 
IAnalyticsEnabledTeamcity, ITea
      * Teamcity
      */
     private ITeamcity teamcity;
+
+    @Nullable
     private String serverId;
 
     /** cached running builds for branch. */
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jobs/CheckQueueJob.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jobs/CheckQueueJob.java
index 5f3a60e..2f689d9 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jobs/CheckQueueJob.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jobs/CheckQueueJob.java
@@ -103,7 +103,6 @@ public class CheckQueueJob implements Runnable {
             return msg;
         }
 
-        //todo support several branches
         List<BranchTracked> tracked = 
HelperConfig.getTrackedBranches().getBranches();
 
         if (tracked == null || tracked.isEmpty()) {
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/BuildRefDao.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/BuildRefDao.java
index 5e4a1cb..de96fdc 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/BuildRefDao.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/BuildRefDao.java
@@ -55,19 +55,21 @@ public class BuildRefDao {
     @Inject private IStringCompactor compactor;
 
     /** */
-    public void init() {
+    public BuildRefDao init() {
         CacheConfiguration<Long, BuildRefCompacted> cfg = 
TcHelperDb.getCacheV2Config(TEAMCITY_BUILD_CACHE_NAME);
 
         cfg.setQueryEntities(Collections.singletonList(new 
QueryEntity(Long.class, BuildRefCompacted.class)));
 
         buildRefsCache = igniteProvider.get().getOrCreateCache(cfg);
+
+        return this;
     }
 
     /**
      * @param srvId Server id.
      * @return all builds for a server, full scan.
      */
-    @NotNull protected Stream<BuildRefCompacted> compactedBuildsForServer(int 
srvId) {
+    @NotNull public Stream<BuildRefCompacted> compactedBuildsForServer(int 
srvId) {
         return StreamSupport.stream(buildRefsCache.spliterator(), false)
             .filter(entry -> isKeyForServer(entry.getKey(), srvId))
             .map(javax.cache.Cache.Entry::getValue);
@@ -86,7 +88,7 @@ public class BuildRefDao {
      * @param ghData Gh data.
      */
     @AutoProfiling
-    public Set<Long> saveChunk(long srvId, List<BuildRef> ghData) {
+    public Set<Long> saveChunk(int srvId, List<BuildRef> ghData) {
         Set<Long> ids = ghData.stream().map(BuildRef::getId)
             .filter(Objects::nonNull)
             .map(buildId -> buildIdToCacheKey(srvId, buildId))
@@ -228,12 +230,16 @@ public class BuildRefDao {
     public int[] getAllIds(int srvId) {
         GridIntList res = new GridIntList(buildRefsCache.size());
 
-        StreamSupport.stream(buildRefsCache.spliterator(), false)
+        getAllBuildRefs(srvId)
                 .map(Cache.Entry::getKey)
-                .filter(entry -> isKeyForServer(entry, srvId))
                 .map(BuildRefDao::cacheKeyToBuildId)
                 .forEach(res::add);
 
         return res.array();
     }
+
+    @NotNull public Stream<Cache.Entry<Long, BuildRefCompacted>> 
getAllBuildRefs(int srvId) {
+        return StreamSupport.stream(buildRefsCache.spliterator(), false)
+                .filter(entry -> isKeyForServer(entry.getKey(), srvId));
+    }
 }
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/ITeamcityIgnited.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/ITeamcityIgnited.java
index bc3788c..bfd5bc9 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/ITeamcityIgnited.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/ITeamcityIgnited.java
@@ -84,7 +84,10 @@ public interface ITeamcityIgnited {
      * @param srvId Server id.
      * @return integer representation of server ID.
      */
-    public static int serverIdToInt(String srvId) {
+    public static int serverIdToInt(@Nullable final String srvId) {
+        if (srvId == null)
+            return 0;
+
         return Math.abs(srvId.hashCode());
     }
 
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedImpl.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedImpl.java
index df11962..1d0b4bc 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedImpl.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedImpl.java
@@ -443,13 +443,8 @@ public class TeamcityIgnitedImpl implements 
ITeamcityIgnited {
         if (mode == SyncMode.NONE) {
             if (existingBuild != null)
                 return existingBuild;
-            else {
-                FatBuildCompacted buildCompacted = new FatBuildCompacted();
-
-                buildCompacted.setFakeStub(true);
-
-                return buildCompacted; // providing fake builds
-            }
+            else
+                return new FatBuildCompacted().setFakeStub(true); // providing 
fake builds
         }
 
         FatBuildCompacted savedVer = buildSync.loadBuild(conn, buildId, 
existingBuild, mode);
@@ -458,9 +453,6 @@ public class TeamcityIgnitedImpl implements 
ITeamcityIgnited {
         if (savedVer == null)
             return existingBuild;
 
-        buildRefDao.save(srvIdMaskHigh, new BuildRefCompacted(savedVer));
-        runHistSync.saveToHistoryLater(srvNme, savedVer);
-
         return savedVer;
     }
 
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildCompacted.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildCompacted.java
index fd153e9..1a50a5d 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildCompacted.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildCompacted.java
@@ -158,8 +158,10 @@ public class FatBuildCompacted extends BuildRefCompacted 
implements IVersionedEn
             setFakeStub(true);
     }
 
-    public void setFakeStub(boolean val) {
+    public FatBuildCompacted setFakeStub(boolean val) {
         setFlag(FAKE_BUILD_F, val);
+
+        return this;
     }
 
     public void buildTypeName(String btName, IStringCompactor compactor) {
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildDao.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildDao.java
index 2c4df80..0e2e4bd 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildDao.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildDao.java
@@ -63,8 +63,10 @@ public class FatBuildDao {
     /**
      *
      */
-    public void init() {
+    public FatBuildDao init() {
         buildsCache = 
igniteProvider.get().getOrCreateCache(TcHelperDb.getCacheV2Config(TEAMCITY_FAT_BUILD_CACHE_NAME));
+
+        return this;
     }
 
     /**
@@ -172,7 +174,7 @@ public class FatBuildDao {
         return key!=null && key >> 32 == srvId;
     }
 
-    public boolean containsKey(int srvIdMaskHigh, int buildRefKey) {
-        return buildsCache.containsKey(buildIdToCacheKey(srvIdMaskHigh, 
buildRefKey));
+    public boolean containsKey(int srvIdMaskHigh, int buildId) {
+        return buildsCache.containsKey(buildIdToCacheKey(srvIdMaskHigh, 
buildId));
     }
 }
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/ProactiveFatBuildSync.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/ProactiveFatBuildSync.java
index 6a63289..753a12f 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/ProactiveFatBuildSync.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/ProactiveFatBuildSync.java
@@ -18,6 +18,7 @@ package org.apache.ignite.ci.teamcity.ignited.fatbuild;
 
 import com.google.common.base.Strings;
 import com.google.common.base.Throwables;
+import java.util.stream.Stream;
 import org.apache.ignite.ci.di.AutoProfiling;
 import org.apache.ignite.ci.di.MonitoredTask;
 import org.apache.ignite.ci.di.scheduler.IScheduler;
@@ -26,11 +27,13 @@ import org.apache.ignite.ci.tcmodel.result.Build;
 import org.apache.ignite.ci.tcmodel.result.problems.ProblemOccurrence;
 import org.apache.ignite.ci.tcmodel.result.stat.Statistics;
 import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrencesFull;
+import org.apache.ignite.ci.teamcity.ignited.BuildRefCompacted;
 import org.apache.ignite.ci.teamcity.ignited.BuildRefDao;
 import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
 import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnited;
 import org.apache.ignite.ci.teamcity.ignited.SyncMode;
 import org.apache.ignite.ci.teamcity.ignited.change.ChangeSync;
+import org.apache.ignite.ci.teamcity.ignited.runhist.RunHistSync;
 import org.apache.ignite.ci.teamcity.pure.ITeamcityConn;
 import org.apache.ignite.ci.util.ExceptionUtil;
 import org.apache.ignite.internal.util.GridConcurrentHashSet;
@@ -65,8 +68,12 @@ public class ProactiveFatBuildSync {
 
     @Inject private IStringCompactor compactor;
 
+    /** Change sync. */
     @Inject private ChangeSync changeSync;
 
+    /** Run history sync. */
+    @Inject private RunHistSync runHistSync;
+
     @GuardedBy("this")
     private Map<String, SyncTask> buildToLoad = new HashMap<>();
 
@@ -93,7 +100,6 @@ public class ProactiveFatBuildSync {
         if (buildsToAskFromTc.isEmpty())
             return;
 
-
         synchronized (this) {
             final SyncTask syncTask = getSyncTask(conn);
 
@@ -124,28 +130,34 @@ public class ProactiveFatBuildSync {
     protected String findMissingBuildsFromBuildRef(String srvId, ITeamcityConn 
conn) {
         int srvIdMaskHigh = ITeamcityIgnited.serverIdToInt(srvId);
 
-        final int[] buildRefKeys = buildRefDao.getAllIds(srvIdMaskHigh);
+        Stream<BuildRefCompacted> buildRefs = 
buildRefDao.compactedBuildsForServer(srvIdMaskHigh);
 
         List<Integer> buildsIdsToLoad = new ArrayList<>();
-        int totalAskedToLoad = 0;
+        AtomicInteger totalAskedToLoad = new AtomicInteger();
+
+        buildRefs.forEach(buildRef -> {
+            Integer buildId = buildRef.getId();
+            if (buildId == null)
+                return;
 
-        for (int buildRefKey : buildRefKeys) {
-            if (!fatBuildDao.containsKey(srvIdMaskHigh, buildRefKey))
-                buildsIdsToLoad.add(buildRefKey);
+            if (buildRef.isRunning(compactor)
+                || buildRef.isQueued(compactor)
+                || !fatBuildDao.containsKey(srvIdMaskHigh, buildId))
+                buildsIdsToLoad.add(buildId);
 
             if (buildsIdsToLoad.size() >= 100) {
-                totalAskedToLoad += buildsIdsToLoad.size();
+                totalAskedToLoad.addAndGet(buildsIdsToLoad.size());
                 scheduleBuildsLoad(conn, buildsIdsToLoad);
                 buildsIdsToLoad.clear();
             }
-        }
+        });
 
         if (!buildsIdsToLoad.isEmpty()) {
-            totalAskedToLoad += buildsIdsToLoad.size();
+            totalAskedToLoad.addAndGet(buildsIdsToLoad.size());
             scheduleBuildsLoad(conn, buildsIdsToLoad);
         }
 
-        return "Invoked later load for " + totalAskedToLoad + " builds from " 
+ srvId;
+        return "Invoked later load for " + totalAskedToLoad.get() + " builds 
from " + srvId;
     }
 
     /** */
@@ -224,6 +236,11 @@ public class ProactiveFatBuildSync {
         return ProactiveFatBuildSync.class.getSimpleName() +"." + taskName + 
"." + srvName;
     }
 
+    /**
+     * Schedule missing builds into Fat builds cache. Sync is based by 
BuildRefs cache.
+     * @param srvName Server name.
+     * @param conn Connection.
+     */
     public void invokeLaterFindMissingByBuildRef(String srvName, ITeamcityConn 
conn) {
         scheduler.sheduleNamed(taskName("findMissingBuildsFromBuildRef", 
srvName),
                 () -> findMissingBuildsFromBuildRef(srvName, conn), 360, 
TimeUnit.MINUTES);
@@ -239,16 +256,32 @@ public class ProactiveFatBuildSync {
      */
     @Nullable
     public FatBuildCompacted loadBuild(ITeamcityConn conn, int buildId,
-                                       @Nullable FatBuildCompacted 
existingBuild,
-                                       SyncMode mode) {
+        @Nullable FatBuildCompacted existingBuild,
+        SyncMode mode) {
         if (existingBuild != null && !existingBuild.isOutdatedEntityVersion()) 
{
-            boolean finished = !existingBuild.isRunning(compactor) && 
!existingBuild.isQueued(compactor);
+            boolean finished =
+                existingBuild.state(compactor) != null // don't count old fake 
builds as finished
+                    && !existingBuild.isRunning(compactor)
+                    && !existingBuild.isQueued(compactor);
 
             if (finished || mode != SyncMode.RELOAD_QUEUED)
                 return null;
         }
 
-        return reloadBuild(conn, buildId, existingBuild);
+        FatBuildCompacted savedVer = reloadBuild(conn, buildId, existingBuild);
+
+        BuildRefCompacted refCompacted = new BuildRefCompacted(savedVer);
+        if (savedVer.isFakeStub())
+            refCompacted.setId(buildId); //to provide possiblity to save the 
build
+
+        final String srvName = conn.serverId();
+        final int srvIdMask = ITeamcityIgnited.serverIdToInt(srvName);
+
+        buildRefDao.save(srvIdMask, refCompacted);
+
+        runHistSync.saveToHistoryLater(srvName, savedVer);
+
+        return savedVer;
     }
 
     /**
@@ -264,8 +297,8 @@ public class ProactiveFatBuildSync {
         //  System.err.println(Thread.currentThread().getName()+ ": Build " + 
buildId);
         //todo some sort of locking to avoid double requests
 
-        final String srvNme = conn.serverId();
-        final int srvIdMask = ITeamcityIgnited.serverIdToInt(srvNme);
+        final String srvName = conn.serverId();
+        final int srvIdMask = ITeamcityIgnited.serverIdToInt(srvName);
 
         Build build;
         List<TestOccurrencesFull> tests = new ArrayList<>();
@@ -275,6 +308,9 @@ public class ProactiveFatBuildSync {
         try {
             build = conn.getBuild(buildId);
 
+            if (build.isFakeStub())
+                build.setCancelled();
+
             if(build.testOccurrences != null && !build.isComposite()) { // 
don't query tests for compoite
                 String nextHref = null;
                 do {
@@ -304,7 +340,7 @@ public class ProactiveFatBuildSync {
         }
         catch (Exception e) {
             if (Throwables.getRootCause(e) instanceof FileNotFoundException) {
-                logger.info("Loading build [" + buildId + "] for server [" + 
srvNme + "] failed:" + e.getMessage(), e);
+                logger.info("Loading build [" + buildId + "] for server [" + 
srvName + "] failed:" + e.getMessage(), e);
 
                 if (existingBuild != null) {
                     build = existingBuild.toBuild(compactor);
@@ -316,11 +352,13 @@ public class ProactiveFatBuildSync {
 
                     problems = existingBuild.problems(compactor);
                 }
-                else
+                else {
                     build = Build.createFakeStub();
-                //todo here can be situation we have build ref, but don't have 
a build
+
+                    build.setCancelled();
+                }
             } else {
-                logger.error("Loading build [" + buildId + "] for server [" + 
srvNme + "] failed:" + e.getMessage(), e);
+                logger.error("Loading build [" + buildId + "] for server [" + 
srvName + "] failed:" + e.getMessage(), e);
 
                 e.printStackTrace();
 
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/pure/ITeamcityConn.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/pure/ITeamcityConn.java
index c2884ed..5538bce 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/pure/ITeamcityConn.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/pure/ITeamcityConn.java
@@ -39,7 +39,7 @@ public interface ITeamcityConn {
     /**
      * @return Internal server ID as string
      */
-    String serverId();
+    @Nullable public String serverId();
 
     /**
      * @return Normalized Host address, ends with '/'.
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 54def0f..2b6fae3 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
@@ -25,7 +25,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 = "20181202";
+    public static final String VERSION = "20181203";
 
     /** TC Bot Version. */
     public String version = VERSION;
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/ci/teamcity/ignited/IgnitedTcInMemoryIntegrationTest.java
index c472447..923ba18 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/ci/teamcity/ignited/IgnitedTcInMemoryIntegrationTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.ignite.ci.teamcity.ignited;
 
+import com.google.common.collect.Lists;
 import com.google.inject.AbstractModule;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
@@ -32,6 +33,7 @@ import javax.xml.bind.JAXBException;
 
 import com.google.inject.internal.SingletonScope;
 import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
 import org.apache.ignite.Ignition;
 import org.apache.ignite.ci.ITeamcity;
 import org.apache.ignite.ci.analysis.SuiteInBranch;
@@ -54,22 +56,29 @@ import 
org.apache.ignite.ci.tcmodel.result.tests.TestOccurrencesFull;
 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.ci.teamcity.pure.ITeamcityConn;
 import org.apache.ignite.ci.teamcity.pure.ITeamcityHttpConnection;
+import org.apache.ignite.ci.teamcity.restcached.ITcServerFactory;
 import org.apache.ignite.ci.user.ICredentialsProv;
 import org.apache.ignite.ci.util.XmlUtil;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.jetbrains.annotations.NotNull;
 import org.junit.AfterClass;
+import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.mockito.Mockito;
 
+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 org.apache.ignite.ci.HelperConfig.ensureDirExist;
 import static 
org.apache.ignite.ci.teamcity.ignited.IgniteStringCompactor.STRINGS_CACHE;
@@ -116,6 +125,25 @@ public class IgnitedTcInMemoryIntegrationTest {
             ignite.close();
     }
 
+    /**
+     * Clear relevant ignite caches to avoid tests invluence to each other.
+     */
+    @Before
+    public void clearIgniteCaches() {
+        clearCache(BuildRefDao.TEAMCITY_BUILD_CACHE_NAME);
+        clearCache(FatBuildDao.TEAMCITY_FAT_BUILD_CACHE_NAME);
+    }
+
+    /**
+     * @param cacheName Cache name to clear.
+     */
+    private void clearCache(String cacheName) {
+        IgniteCache<Long, BuildRefCompacted> buildRefCache = 
ignite.cache(cacheName);
+
+        if (buildRefCache != null)
+            buildRefCache.clear();
+    }
+
     @Test
     public void saveAndLoadBuildReference() throws IOException {
         ITeamcityHttpConnection http = 
Mockito.mock(ITeamcityHttpConnection.class);
@@ -535,6 +563,91 @@ public class IgnitedTcInMemoryIntegrationTest {
         assertEquals(0.5, testRunHist.getFailRate(), 0.1);
     }
 
+    @Test
+    public void testQueuedBuildsRemoved() {
+        TeamcityIgnitedModule module = new TeamcityIgnitedModule();
+        module.overrideHttp(new ITeamcityHttpConnection() {
+            @Override public InputStream sendGet(String basicAuthTok, String 
url) throws IOException {
+                throw new FileNotFoundException(url);
+            }
+        });
+        Injector injector = Guice.createInjector(module, new 
IgniteAndShedulerTestModule());
+
+        IStringCompactor c = injector.getInstance(IStringCompactor.class);
+        BuildRefDao buildRefDao = 
injector.getInstance(BuildRefDao.class).init();
+        FatBuildDao fatBuildDao = 
injector.getInstance(FatBuildDao.class).init();
+
+        int buildIdQ = 1000042;
+        BuildRef refQ = new BuildRef();
+        refQ.buildTypeId = "Testbuild";
+        refQ.branchName = ITeamcity.REFS_HEADS_MASTER;
+        refQ.state = BuildRef.STATE_QUEUED;
+        refQ.setId(buildIdQ);
+
+        int buildIdR = 1000043;
+        BuildRef refR = new BuildRef();
+        refR.buildTypeId = "Testbuild";
+        refR.branchName = ITeamcity.REFS_HEADS_MASTER;
+        refR.state = BuildRef.STATE_RUNNING;
+        refR.setId(buildIdR);
+
+        String srvId = APACHE;
+        int srvIdInt = ITeamcityIgnited.serverIdToInt(srvId);
+        ITeamcityConn srvConn = 
injector.getInstance(ITcServerFactory.class).createServer(srvId);
+
+        buildRefDao.saveChunk(srvIdInt, Lists.newArrayList(refQ, refR));
+
+        List<BuildRefCompacted> running = 
buildRefDao.getQueuedAndRunning(srvIdInt);
+        assertFalse(checkNotNull(running).isEmpty());
+
+        System.out.println("Running builds (before sync): " + printRefs(c, 
running));
+
+        ProactiveFatBuildSync buildSync = 
injector.getInstance(ProactiveFatBuildSync.class);
+        buildSync.invokeLaterFindMissingByBuildRef(srvId, srvConn);
+
+        FatBuildCompacted fatBuild = fatBuildDao.getFatBuild(srvIdInt, 
buildIdQ);
+        System.out.println(fatBuild);
+
+        assertNotNull(fatBuild);
+        assertTrue(fatBuild.isFakeStub());
+
+        assertTrue(fatBuild.isCancelled(c));
+
+        List<BuildRefCompacted> running2 = 
buildRefDao.getQueuedAndRunning(srvIdInt);
+        System.out.println("Running builds (after sync): " + printRefs(c, 
running2));
+        assertTrue(checkNotNull(running2).isEmpty());
+
+        // Now we have 2 fake stubs, retry to actualize
+        buildRefDao.saveChunk(srvIdInt, Lists.newArrayList(refQ, refR));
+
+        List<BuildRefCompacted> running3 = 
buildRefDao.getQueuedAndRunning(srvIdInt);
+        System.out.println("Running builds (before with fake builds): " + 
printRefs(c, running3));
+        assertFalse(checkNotNull(running3).isEmpty());
+
+        putOldFashionFakeBuild(c, fatBuildDao, buildIdQ, srvIdInt);
+        putOldFashionFakeBuild(c, fatBuildDao, buildIdR, srvIdInt);
+
+        buildSync.invokeLaterFindMissingByBuildRef(srvId, srvConn);
+
+        List<BuildRefCompacted> running4 = 
buildRefDao.getQueuedAndRunning(srvIdInt);
+        System.out.println("Running builds (before with fake builds): " + 
printRefs(c, running4));
+        assertTrue(checkNotNull(running4).isEmpty());
+    }
+
+    public void putOldFashionFakeBuild(IStringCompactor c, FatBuildDao 
fatBuildDao, int buildId, int srvIdInt) {
+        FatBuildCompacted fb = fatBuildDao.getFatBuild(srvIdInt, buildId);
+
+        fb.fillFieldsFromBuildRef(c, new BuildRef());
+
+        fatBuildDao.putFatBuild(srvIdInt, buildId, fb);
+
+        assertNull(fatBuildDao.getFatBuild(srvIdInt, buildId).state(c));
+    }
+
+    @NotNull public List<BuildRef> printRefs(IStringCompactor c, 
List<BuildRefCompacted> running2) {
+        return 
running2.stream().map(bref->bref.toBuildRef(c)).collect(Collectors.toList());
+    }
+
     /**
      *
      */

Reply via email to