fix support of multiple nuget build triggers within one build configuration/build...
authorEugene Petrenko <eugene.petrenko@gmail.com>
Wed, 20 Jul 2011 17:39:56 +0000 (21:39 +0400)
committerEugene Petrenko <eugene.petrenko@gmail.com>
Wed, 20 Jul 2011 17:39:56 +0000 (21:39 +0400)
nuget-server/src/jetbrains/buildServer/nuget/server/trigger/NamedPackagesUpdateChecker.java
nuget-server/src/jetbrains/buildServer/nuget/server/trigger/ThreadedBuildTriggerPolicy.java
nuget-server/src/jetbrains/buildServer/nuget/server/trigger/TriggerUpdateChecker.java
nuget-tests/src/jetbrains/buildServer/nuget/tests/server/ThreadedBuildTriggerPolicyTest.java

index 109e91ec735327add075dcd14263629a55a18abb..280433a7cb65d33157e3b758d5318435baaf491e 100644 (file)
@@ -1,5 +1,6 @@
 package jetbrains.buildServer.nuget.server.trigger;\r
 \r
+import com.intellij.openapi.diagnostic.Logger;\r
 import jetbrains.buildServer.buildTriggers.BuildTriggerDescriptor;\r
 import jetbrains.buildServer.buildTriggers.BuildTriggerException;\r
 import jetbrains.buildServer.nuget.server.exec.ListPackagesCommand;\r
@@ -16,6 +17,8 @@ import java.util.*;
  * Date: 14.07.11 15:41\r
  */\r
 public class NamedPackagesUpdateChecker implements TriggerUpdateChecker {\r
+  private static final Logger LOG = Logger.getInstance(NamedPackagesUpdateChecker.class.getName());\r
+\r
   public static final String KEY = "hash";\r
   private final ListPackagesCommand myCommand;\r
 \r
@@ -50,8 +53,10 @@ public class NamedPackagesUpdateChecker implements TriggerUpdateChecker {
       throw new BuildTriggerException("Failed to check for package versions. " + t.getMessage(), t);\r
     }\r
     final String hash = serializeHashcode(result);\r
+    final String oldHash = storage.getValue(KEY);\r
 \r
-    String oldHash = storage.getValue(KEY);\r
+    LOG.debug("Recieved packages hash: " + hash);\r
+    LOG.debug("          old hash was: " + oldHash);\r
     if (!hash.equals(oldHash)) {\r
       storage.putValue(KEY, hash);\r
       storage.flush();\r
index c6784442c3e0ecb905ed765e4de7e1b351003739..b735549aaff57791cc845171e484b3af330624ad 100644 (file)
@@ -20,6 +20,8 @@ import com.intellij.openapi.diagnostic.Logger;
 import jetbrains.buildServer.buildTriggers.BuildTriggerException;\r
 import jetbrains.buildServer.buildTriggers.PolledBuildTrigger;\r
 import jetbrains.buildServer.buildTriggers.PolledTriggerContext;\r
+import jetbrains.buildServer.serverSide.CustomDataStorage;\r
+import jetbrains.buildServer.util.StringUtil;\r
 import org.jetbrains.annotations.NotNull;\r
 \r
 import java.util.concurrent.*;\r
@@ -30,10 +32,11 @@ import java.util.concurrent.*;
  */\r
 public class ThreadedBuildTriggerPolicy extends PolledBuildTrigger {\r
   private static final Logger LOG = Logger.getInstance(ThreadedBuildTriggerPolicy.class.getName());\r
+  private static final String HASH = "jtriggerId";\r
 \r
   private final ExecutorService myExecutor;\r
   private final TriggerUpdateChecker myUpdater;\r
-  private Future<BuildStartReason> myUpdateRequired;\r
+  private ConcurrentMap<String, Future<BuildStartReason>> myUpdatesRequired = new ConcurrentHashMap<String, Future<BuildStartReason>>();\r
 \r
   public ThreadedBuildTriggerPolicy(@NotNull final ExecutorService executor,\r
                                     @NotNull final TriggerUpdateChecker updater) {\r
@@ -43,9 +46,20 @@ public class ThreadedBuildTriggerPolicy extends PolledBuildTrigger {
 \r
   @Override\r
   public synchronized void triggerBuild(@NotNull PolledTriggerContext context) throws BuildTriggerException {\r
+    final CustomDataStorage storage = context.getCustomDataStorage();\r
+\r
+    String value = storage.getValue(HASH);\r
+    if (value == null) {\r
+      value = StringUtil.generateUniqueHash();\r
+      storage.putValue(HASH, value);\r
+      storage.flush();\r
+    }\r
+\r
+    Future<BuildStartReason> myUpdateRequired = myUpdatesRequired.get(value);\r
     if (myUpdateRequired == null) {\r
       try {\r
         myUpdateRequired = myExecutor.submit(createUpdateTask(context));\r
+        myUpdatesRequired.put(value, myUpdateRequired);\r
       } catch (RejectedExecutionException e) {\r
         String msg = "Failed to enqueue trigger task: " + myUpdater + ". " + e.getMessage();\r
         LOG.warn(msg);\r
@@ -66,7 +80,7 @@ public class ThreadedBuildTriggerPolicy extends PolledBuildTrigger {
       if (cause instanceof BuildTriggerException) throw (BuildTriggerException)cause;\r
       throw new BuildTriggerException(cause.getMessage(), cause);\r
     } finally {\r
-      myUpdateRequired = null;\r
+      myUpdatesRequired.remove(value);\r
     }\r
 \r
     if (result != null) {\r
index d358ffe909d6ed16c9388954b2c67a07404c40c9..ce67141313d0af2236637fb4e950c000f11b58ce 100644 (file)
@@ -30,6 +30,9 @@ public interface TriggerUpdateChecker {
   /**\r
    * Called from background thread to check for updates\r
    *\r
+   * Update is called for different trigger settings and thus there should\r
+   * be nothing cached in instance\r
+   *\r
    * @param descriptor build trigger desciptor to check for parameters\r
    * @param storage    trigger state\r
    * @return null or StartReason instance to start a build\r
index 5520cdcf30950fdd9455e1096e893732da6dbaaa..1f19624bf6e5e96ac2069cb58aa5b37cb1d9c29e 100644 (file)
@@ -22,6 +22,7 @@ import jetbrains.buildServer.buildTriggers.PolledTriggerContext;
 import jetbrains.buildServer.nuget.server.trigger.BuildStartReason;\r
 import jetbrains.buildServer.nuget.server.trigger.ThreadedBuildTriggerPolicy;\r
 import jetbrains.buildServer.nuget.server.trigger.TriggerUpdateChecker;\r
+import jetbrains.buildServer.serverSide.CustomDataStorage;\r
 import jetbrains.buildServer.serverSide.SBuildType;\r
 import org.jmock.Expectations;\r
 import org.jmock.Mockery;\r
@@ -41,7 +42,11 @@ public class ThreadedBuildTriggerPolicyTest extends BaseTestCase {
   private TriggerUpdateChecker checker;\r
   private ThreadedBuildTriggerPolicy policy;\r
   private PolledTriggerContext ctx;\r
+  private PolledTriggerContext ctx2;\r
   private Future future;\r
+  private Future future2;\r
+  private CustomDataStorage store1;\r
+  private CustomDataStorage store2;\r
   private SBuildType bt;\r
 \r
 \r
@@ -53,12 +58,23 @@ public class ThreadedBuildTriggerPolicyTest extends BaseTestCase {
     executor = m.mock(ExecutorService.class);\r
     checker = m.mock(TriggerUpdateChecker.class);\r
     policy = new ThreadedBuildTriggerPolicy(executor, checker);\r
-    ctx = m.mock(PolledTriggerContext.class);\r
-    future = m.mock(Future.class);\r
+    ctx = m.mock(PolledTriggerContext.class, "ctx1");\r
+    ctx2 = m.mock(PolledTriggerContext.class, "ctx2");\r
+    future = m.mock(Future.class, "future1");\r
+    future2 = m.mock(Future.class, "future2");\r
     bt = m.mock(SBuildType.class);\r
+    store1 = m.mock(CustomDataStorage.class, "store1");\r
+    store2 = m.mock(CustomDataStorage.class, "store2");\r
 \r
     m.checking(new Expectations(){{\r
       allowing(ctx).getBuildType(); will(returnValue(bt));\r
+      allowing(ctx2).getBuildType(); will(returnValue(bt));\r
+\r
+      allowing(ctx).getCustomDataStorage(); will(returnValue(store1));\r
+      allowing(ctx2).getCustomDataStorage(); will(returnValue(store2));\r
+\r
+      allowing(store1).getValue("jtriggerId"); will(returnValue("x"));\r
+      allowing(store2).getValue("jtriggerId"); will(returnValue("y"));\r
     }});\r
   }\r
 \r
@@ -72,6 +88,8 @@ public class ThreadedBuildTriggerPolicyTest extends BaseTestCase {
       oneOf(future).isDone(); will(returnValue(false));\r
     }});\r
      policy.triggerBuild(ctx);\r
+\r
+    m.assertIsSatisfied();\r
   }\r
 \r
   @Test\r
@@ -83,6 +101,8 @@ public class ThreadedBuildTriggerPolicyTest extends BaseTestCase {
     }});\r
 \r
     policy.triggerBuild(ctx);\r
+\r
+    m.assertIsSatisfied();\r
   }\r
 \r
   @Test\r
@@ -96,6 +116,8 @@ public class ThreadedBuildTriggerPolicyTest extends BaseTestCase {
     }});\r
 \r
     policy.triggerBuild(ctx);\r
+\r
+    m.assertIsSatisfied();\r
   }\r
 \r
   @Test\r
@@ -108,6 +130,8 @@ public class ThreadedBuildTriggerPolicyTest extends BaseTestCase {
     }});\r
 \r
     policy.triggerBuild(ctx);\r
+\r
+    m.assertIsSatisfied();\r
   }\r
 \r
   @Test\r
@@ -125,6 +149,8 @@ public class ThreadedBuildTriggerPolicyTest extends BaseTestCase {
     } catch (BuildTriggerException e) {\r
       Assert.assertEquals(e.getMessage(), "fail");\r
     }\r
+\r
+    m.assertIsSatisfied();\r
   }\r
 \r
   @Test\r
@@ -136,5 +162,27 @@ public class ThreadedBuildTriggerPolicyTest extends BaseTestCase {
     }});\r
 \r
     policy.triggerBuild(ctx);\r
+\r
+    m.assertIsSatisfied();\r
+  }\r
+\r
+  @Test\r
+  @SuppressWarnings({"unchecked"})\r
+  public void test_should_not_reuse_same_taks_in_several_triggers() {\r
+    m.checking(new Expectations(){{\r
+      oneOf(executor).submit(with(any(Callable.class)));\r
+      will(returnValue(future));\r
+\r
+      oneOf(executor).submit(with(any(Callable.class)));\r
+      will(returnValue(future2));\r
+\r
+      oneOf(future).isDone(); will(returnValue(false));\r
+      oneOf(future2).isDone(); will(returnValue(false));\r
+    }\r
+    });\r
+    policy.triggerBuild(ctx);\r
+    policy.triggerBuild(ctx2);\r
+\r
+    m.assertIsSatisfied();\r
   }\r
 }\r