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 2018/11/19 16:34:08 UTC
[ignite-teamcity-bot] branch master updated: IGNITE-10275 Several
JIRA comments are issued in case ignite.cache.remove failed. - Fixes #74.
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 ca99bfd IGNITE-10275 Several JIRA comments are issued in case ignite.cache.remove failed. - Fixes #74.
ca99bfd is described below
commit ca99bfd60d8c64186179df38cb1a8b0b4f52ff0d
Author: ololo3000 <pm...@gmail.com>
AuthorDate: Mon Nov 19 19:34:00 2018 +0300
IGNITE-10275 Several JIRA comments are issued in case ignite.cache.remove failed. - Fixes #74.
Signed-off-by: Dmitriy Pavlov <dp...@apache.org>
---
.../main/java/org/apache/ignite/ci/TcHelper.java | 8 +-
.../apache/ignite/ci/observer/BuildObserver.java | 60 ++++---
.../org/apache/ignite/ci/observer/BuildsInfo.java | 84 +++++-----
.../ignite/ci/observer/CompactBuildsInfo.java | 34 ++--
.../apache/ignite/ci/observer/ObserverTask.java | 174 +++++++++++++--------
.../tcbot/visa/TcBotTriggerAndSignOffService.java | 49 ++++--
.../apache/ignite/ci/tcbot/visa/VisaStatus.java | 5 +-
.../ci/web/model/CompactContributionKey.java | 13 +-
.../ignite/ci/web/model/ContributionKey.java | 19 ++-
.../java/org/apache/ignite/ci/web/model/Visa.java | 1 -
.../ci/web/model/hist/VisasHistoryStorage.java | 9 +-
.../ignite/ci/web/rest/visa/TcBotVisaService.java | 13 ++
ignite-tc-helper-web/src/main/webapp/visas.html | 36 ++++-
13 files changed, 322 insertions(+), 183 deletions(-)
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/TcHelper.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/TcHelper.java
index f3ae04a..7df5074 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/TcHelper.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/TcHelper.java
@@ -178,8 +178,12 @@ public class TcHelper implements ITcHelper, IJiraIntegration {
String comment = generateJiraComment(suitesStatuses, build.webUrl);
- blockers = suitesStatuses.stream().mapToInt(suite ->
- suite.testFailures.size()).sum();
+ blockers = suitesStatuses.stream().mapToInt(suite -> {
+ if (suite.testFailures.isEmpty())
+ return 1;
+
+ return suite.testFailures.size();})
+ .sum();
res = objectMapper.readValue(teamcity.sendJiraComment(ticket, comment), JiraCommentResponse.class);
}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/BuildObserver.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/BuildObserver.java
index cf29468..b4686f7 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/BuildObserver.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/BuildObserver.java
@@ -17,19 +17,24 @@
package org.apache.ignite.ci.observer;
-import java.util.Collection;
import java.util.Objects;
import java.util.Timer;
import javax.inject.Inject;
+import org.apache.ignite.ci.IAnalyticsEnabledTeamcity;
+import org.apache.ignite.ci.ITcHelper;
import org.apache.ignite.ci.tcmodel.result.Build;
import org.apache.ignite.ci.user.ICredentialsProv;
-import org.apache.ignite.ci.web.model.VisaRequest;
-import org.apache.ignite.ci.web.model.hist.VisasHistoryStorage;
+import org.apache.ignite.ci.web.model.ContributionKey;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
*
*/
public class BuildObserver {
+ /** Logger. */
+ private static final Logger logger = LoggerFactory.getLogger(BuildObserver.class);
+
/** Time between observing actions in milliseconds. */
private static final long PERIOD = 10 * 60 * 1_000;
@@ -39,8 +44,8 @@ public class BuildObserver {
/** Task, which should be done periodically. */
private ObserverTask observerTask;
- /** Visas History Storage. */
- @Inject private VisasHistoryStorage visasStorage;
+ /** Helper. */
+ @Inject private ITcHelper tcHelper;
/**
*/
@@ -60,6 +65,25 @@ public class BuildObserver {
timer.cancel();
}
+ /** */
+ public ObserverTask getObserverTask() {
+ return observerTask;
+ }
+
+ /** */
+ public boolean stopObservation(ContributionKey key) {
+ try {
+ observerTask.removeBuildInfo(key);
+
+ return true;
+ }
+ catch (Exception e) {
+ logger.error("Observation stop: " + e.getMessage(), e);
+
+ return false;
+ }
+ }
+
/**
* @param srvId Server id.
* @param prov Credentials.
@@ -69,28 +93,26 @@ public class BuildObserver {
public void observe(String srvId, ICredentialsProv prov, String ticket, String branchForTc, Build... builds) {
BuildsInfo buildsInfo = new BuildsInfo(srvId, prov, ticket, branchForTc, builds);
- visasStorage.put(new VisaRequest(buildsInfo));
-
observerTask.addInfo(buildsInfo);
}
/**
- * @param srvId Server id.
- * @param branch Branch.
+ * @param key {@code Contribution Key}.
*/
- public String getObservationStatus(String srvId, String branch) {
+ public String getObservationStatus(ContributionKey key) {
StringBuilder sb = new StringBuilder();
- Collection<BuildsInfo> builds = observerTask.getInfos();
+ BuildsInfo buildsInfo = observerTask.getInfo(key);
+
+ ICredentialsProv creds = tcHelper.getServerAuthorizerCreds();
+
+ IAnalyticsEnabledTeamcity teamcity = tcHelper.server(key.srvId, creds);
- for (BuildsInfo bi : builds) {
- if (Objects.equals(bi.branchForTc, branch)
- && Objects.equals(bi.srvId, srvId)) {
- sb.append(bi.ticket).append(" to be commented, waiting for builds. ");
- sb.append(bi.finishedBuildsCount());
- sb.append(" builds done from ");
- sb.append(bi.buildsCount());
- }
+ if (Objects.nonNull(buildsInfo)) {
+ sb.append(buildsInfo.ticket).append(" to be commented, waiting for builds. ");
+ sb.append(buildsInfo.finishedBuildsCount(teamcity));
+ sb.append(" builds done from ");
+ sb.append(buildsInfo.buildsCount());
}
return sb.toString();
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/BuildsInfo.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/BuildsInfo.java
index 7117169..e02ad5b 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/BuildsInfo.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/BuildsInfo.java
@@ -17,11 +17,11 @@
package org.apache.ignite.ci.observer;
+import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.List;
import java.util.Objects;
import org.apache.ignite.ci.IAnalyticsEnabledTeamcity;
import org.apache.ignite.ci.tcmodel.result.Build;
@@ -34,13 +34,13 @@ import org.apache.ignite.ci.web.model.ContributionKey;
*/
public class BuildsInfo {
/** */
- public static final String FINISHED_STATE = "finished";
+ public static final String FINISHED_STATUS = "finished";
/** */
- public static final String RUNNING_STATE = "running";
+ public static final String RUNNING_STATUS = "running";
/** */
- public static final String FINISHED_WITH_FAILURES_STATE = "finished with failures";
+ public static final String CANCELLED_STATUS = "cancelled";
/** */
public final String userName;
@@ -61,17 +61,17 @@ public class BuildsInfo {
public final Date date;
/** Finished builds. */
- private final Map<Integer, Boolean> finishedBuilds = new HashMap<>();
+ private final List<Integer> builds = new ArrayList<>();
/** */
- public BuildsInfo(CompactBuildsInfo buildsInfo, IStringCompactor strCompactor) {
- this.userName = strCompactor.getStringFromId(buildsInfo.userName());
- this.date = buildsInfo.date();
- this.srvId = strCompactor.getStringFromId(buildsInfo.srvId());
- this.ticket = strCompactor.getStringFromId(buildsInfo.ticket());
- this.branchForTc = strCompactor.getStringFromId(buildsInfo.branchForTc());
- this.buildTypeId = strCompactor.getStringFromId(buildsInfo.buildTypeId());
- this.finishedBuilds.putAll(buildsInfo.getFinishedBuilds());
+ public BuildsInfo(CompactBuildsInfo compactBuildsInfo, IStringCompactor strCompactor) {
+ this.userName = strCompactor.getStringFromId(compactBuildsInfo.userName());
+ this.date = compactBuildsInfo.date();
+ this.srvId = strCompactor.getStringFromId(compactBuildsInfo.srvId());
+ this.ticket = strCompactor.getStringFromId(compactBuildsInfo.ticket());
+ this.branchForTc = strCompactor.getStringFromId(compactBuildsInfo.branchForTc());
+ this.buildTypeId = strCompactor.getStringFromId(compactBuildsInfo.buildTypeId());
+ this.builds.addAll(compactBuildsInfo.getBuilds());
}
/**
@@ -90,71 +90,73 @@ public class BuildsInfo {
this.buildTypeId = builds.length == 1 ? builds[0].buildTypeId : "IgniteTests24Java8_RunAll";
for (Build build : builds)
- finishedBuilds.put(build.getId(), false);
+ this.builds.add(build.getId());
}
/**
* @param teamcity Teamcity.
*/
public String getState(IAnalyticsEnabledTeamcity teamcity) {
- for (Map.Entry<Integer, Boolean> entry : finishedBuilds.entrySet()) {
- if (entry.getValue() == null)
- return FINISHED_WITH_FAILURES_STATE;
+ boolean isFinished = true;
- if (!entry.getValue()) {
- Build build = teamcity.getBuild(entry.getKey());
+ for (Integer id : builds) {
+ Build build = teamcity.getBuild(id);
- if (build.isFinished()) {
- if (build.isUnknown()) {
- entry.setValue(null);
+ if (build.isUnknown())
+ return CANCELLED_STATUS;
- return FINISHED_WITH_FAILURES_STATE;
- }
-
- entry.setValue(true);
- }
- }
+ if (!build.isFinished())
+ isFinished = false;
}
- return finishedBuilds.containsValue(false) ? RUNNING_STATE : FINISHED_STATE;
+ return isFinished ? FINISHED_STATUS : RUNNING_STATUS;
}
/**
* @param teamcity Teamcity.
*/
public boolean isFinished(IAnalyticsEnabledTeamcity teamcity) {
- return FINISHED_STATE.equals(getState(teamcity));
+ return FINISHED_STATUS.equals(getState(teamcity));
}
/**
* @param teamcity Teamcity.
*/
- public boolean isFinishedWithFailures(IAnalyticsEnabledTeamcity teamcity) {
- return FINISHED_WITH_FAILURES_STATE.equals(getState(teamcity));
+ public boolean isCancelled(IAnalyticsEnabledTeamcity teamcity) {
+ return CANCELLED_STATUS.equals(getState(teamcity));
}
/**
* Return builds count.
*/
public int buildsCount(){
- return finishedBuilds.size();
+ return builds.size();
}
/**
* Return finished builds count.
*/
- public int finishedBuildsCount(){
- return (int)finishedBuilds.values().stream().filter(v -> v).count();
+ public int finishedBuildsCount(IAnalyticsEnabledTeamcity teamcity){
+ int finishedCnt = 0;
+
+ for (Integer id : builds) {
+ Build build = teamcity.getBuild(id);
+
+ if (build.isFinished())
+ ++finishedCnt;
+ }
+
+ return finishedCnt;
}
/** */
public ContributionKey getContributionKey() {
- return new ContributionKey(srvId, ticket, branchForTc);
+ return new ContributionKey(srvId, branchForTc);
}
/** */
- public Map<Integer, Boolean> getBuilds() {
- return Collections.unmodifiableMap(finishedBuilds);
+ public List<Integer> getBuilds() {
+ return Collections.unmodifiableList(builds);
}
/** {@inheritDoc} */
@@ -171,12 +173,12 @@ public class BuildsInfo {
Objects.equals(buildTypeId, info.buildTypeId) &&
Objects.equals(branchForTc, info.branchForTc) &&
Objects.equals(ticket, info.ticket) &&
- Objects.equals(finishedBuilds.keySet(), info.finishedBuilds.keySet()) &&
+ Objects.equals(builds, info.builds) &&
Objects.equals(date, info.date);
}
/** {@inheritDoc} */
@Override public int hashCode() {
- return Objects.hash(srvId, buildTypeId, branchForTc, ticket, finishedBuilds.keySet(), date);
+ return Objects.hash(srvId, buildTypeId, branchForTc, ticket, builds, date);
}
}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/CompactBuildsInfo.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/CompactBuildsInfo.java
index c07f05a..df70048 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/CompactBuildsInfo.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/CompactBuildsInfo.java
@@ -17,10 +17,10 @@
package org.apache.ignite.ci.observer;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.List;
import java.util.Objects;
import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
@@ -46,9 +46,11 @@ public class CompactBuildsInfo {
/** */
private Date date;
- /** Finished builds. */
- private final Map<Integer, Boolean> finishedBuilds = new HashMap<>();
+ /** Builds. */
+ private final List<Integer> builds = new ArrayList<>();
+
+ /** */
public CompactBuildsInfo() {
}
@@ -61,12 +63,12 @@ public class CompactBuildsInfo {
this.ticket = strCompactor.getStringId(buildsInfo.ticket);
this.branchForTc = strCompactor.getStringId(buildsInfo.branchForTc);
this.buildTypeId = strCompactor.getStringId(buildsInfo.buildTypeId);
- this.finishedBuilds.putAll(buildsInfo.getBuilds());
+ this.builds.addAll(buildsInfo.getBuilds());
}
/** */
- public Map<Integer, Boolean> getFinishedBuilds() {
- return Collections.unmodifiableMap(finishedBuilds);
+ public List<Integer> getBuilds() {
+ return Collections.unmodifiableList(builds);
}
/** */
@@ -144,44 +146,48 @@ public class CompactBuildsInfo {
Objects.equals(buildTypeId, info.buildTypeId) &&
Objects.equals(branchForTc, info.branchForTc) &&
Objects.equals(ticket, info.ticket) &&
- Objects.equals(finishedBuilds.keySet(), info.finishedBuilds.keySet()) &&
+ Objects.equals(builds, info.builds) &&
Objects.equals(date, info.date);
}
/** {@inheritDoc} */
@Override public int hashCode() {
- return Objects.hash(srvId, buildTypeId, branchForTc, ticket, finishedBuilds.keySet(), date);
+ return Objects.hash(srvId, buildTypeId, branchForTc, ticket, builds, date);
}
+ /** */
public void userName(int val) {
this.userName = val;
}
+ /** */
public void date(long ts) {
this.date = new Date(ts);
}
+ /** */
public int userName() {
return userName;
}
+ /** */
public Date date() {
return date;
}
+ /** */
public int srvId() {
return srvId;
}
+ /** */
public void srvId(int srvId) {
this.srvId = srvId;
}
+ /** */
public void addBuild(int... arr) {
- for (int i = 0; i < arr.length; i++) {
- int i1 = arr[i];
-
- finishedBuilds.put(i1, false);
- }
+ for (int i = 0; i < arr.length; i++)
+ builds.add(arr[i]);
}
}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/ObserverTask.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/ObserverTask.java
index 8676868..68335c8 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/ObserverTask.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/ObserverTask.java
@@ -19,13 +19,16 @@ package org.apache.ignite.ci.observer;
import com.google.common.base.Preconditions;
import java.util.ArrayList;
-import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Collection;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.TimerTask;
-import javax.cache.Cache;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.stream.Collectors;
import javax.inject.Inject;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
@@ -37,9 +40,13 @@ import org.apache.ignite.ci.di.MonitoredTask;
import org.apache.ignite.ci.jira.IJiraIntegration;
import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
import org.apache.ignite.ci.user.ICredentialsProv;
+import org.apache.ignite.ci.web.model.CompactContributionKey;
+import org.apache.ignite.ci.web.model.ContributionKey;
import org.apache.ignite.ci.web.model.Visa;
+import org.apache.ignite.ci.web.model.VisaRequest;
import org.apache.ignite.ci.web.model.hist.VisasHistoryStorage;
import org.apache.ignite.internal.util.typedef.X;
+import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -51,7 +58,7 @@ public class ObserverTask extends TimerTask {
private static final Logger logger = LoggerFactory.getLogger(ObserverTask.class);
/** */
- public static final String BUILDS_CACHE_NAME = "compactBuildsInfos";
+ public static final String BUILDS_CACHE_NAME = "compactBuildsInfosCache";
/** Helper. */
@Inject private ITcHelper tcHelper;
@@ -63,33 +70,76 @@ public class ObserverTask extends TimerTask {
@Inject private Ignite ignite;
/** */
- @Inject private VisasHistoryStorage visasHistoryStorage;
+ @Inject private VisasHistoryStorage visasHistStorage;
/** */
@Inject private IStringCompactor strCompactor;
+ /** */
+ private ReentrantLock observationLock = new ReentrantLock();
+
/**
*/
ObserverTask() {
}
/** */
- private IgniteCache<CompactBuildsInfo, Object> compactInfos() {
+ private IgniteCache<CompactContributionKey, CompactBuildsInfo> compactInfos() {
return ignite.getOrCreateCache(TcHelperDb.getCacheV2TxConfig(BUILDS_CACHE_NAME));
}
/** */
+ @Nullable public BuildsInfo getInfo(ContributionKey key) {
+ CompactBuildsInfo compactBuildsInfo = compactInfos().get(new CompactContributionKey(key, strCompactor));
+
+ return Objects.isNull(compactBuildsInfo) ? null : compactBuildsInfo.toBuildInfo(strCompactor);
+ }
+
+
+ /** */
public Collection<BuildsInfo> getInfos() {
List<BuildsInfo> buildsInfos = new ArrayList<>();
- compactInfos().forEach(entry -> buildsInfos.add(entry.getKey().toBuildInfo(strCompactor)));
+ compactInfos().forEach(entry -> buildsInfos.add(entry.getValue().toBuildInfo(strCompactor)));
return buildsInfos;
}
/** */
public void addInfo(BuildsInfo info) {
- compactInfos().put(new CompactBuildsInfo(info, strCompactor), new Object());
+ visasHistStorage.put(new VisaRequest(info));
+
+ compactInfos().put(new CompactContributionKey(info.getContributionKey(), strCompactor),
+ new CompactBuildsInfo(info, strCompactor));
+ }
+
+ /** */
+ public void removeBuildInfo(ContributionKey key) {
+ observationLock.lock();
+
+ try {
+ removeBuildInfo(new CompactContributionKey(key, strCompactor));
+ }
+ finally {
+ observationLock.unlock();
+ }
+ }
+
+ /** */
+ private void removeBuildInfo(CompactContributionKey key) {
+ try {
+ boolean rmv = compactInfos().remove(key);
+
+ Preconditions.checkState(rmv, "Key not found: " + key.toContributionKey(strCompactor).toString());
+ }
+ catch (Exception e) {
+ logger.error("Cache remove: " + e.getMessage(), e);
+
+ throw new RuntimeException("Observer queue: " +
+ getInfos().stream().map(bi -> bi.getContributionKey().toString())
+ .collect(Collectors.joining(", ")) +
+ " Error: " + X.getFullStackTrace(e));
+ }
}
/** {@inheritDoc} */
@@ -108,88 +158,80 @@ public class ObserverTask extends TimerTask {
@AutoProfiling
@MonitoredTask(name = "Build Observer")
protected String runObserverTask() {
- if (!tcHelper.isServerAuthorized())
- return "Server authorization required.";
-
- int checkedBuilds = 0;
- int notFinishedBuilds = 0;
- Set<String> ticketsNotified = new HashSet<>();
-
- ObjectMapper objMapper = new ObjectMapper();
+ observationLock.lock();
- List<String> rmvdVisas = new ArrayList<>();
+ try {
+ if (!tcHelper.isServerAuthorized())
+ return "Server authorization required.";
- List<String> queuedVisas = new ArrayList<>();
+ int checkedBuilds = 0;
+ int notFinishedBuilds = 0;
+ Set<String> ticketsNotified = new HashSet<>();
- for (Cache.Entry<CompactBuildsInfo, Object> entry : compactInfos()) {
- CompactBuildsInfo compactInfo = entry.getKey();
+ Map<CompactContributionKey, Boolean> rmv = new HashMap<>();
- try {
- queuedVisas.add(objMapper.writeValueAsString(compactInfo));
- }
- catch (Exception e) {
- logger.error("JSON string parse failed: " + e.getMessage(), e);
+ for (IgniteCache.Entry<CompactContributionKey, CompactBuildsInfo> entry : compactInfos()) {
+ CompactBuildsInfo compactInfo = entry.getValue();
- return "Exception while JSON parsing " + e.getClass().getSimpleName() + ": " + e.getMessage();
- }
+ BuildsInfo info = compactInfo.toBuildInfo(strCompactor);
- BuildsInfo info = compactInfo.toBuildInfo(strCompactor);
+ IAnalyticsEnabledTeamcity teamcity = tcHelper.server(info.srvId, tcHelper.getServerAuthorizerCreds());
- checkedBuilds += info.buildsCount();
+ checkedBuilds += info.buildsCount();
- IAnalyticsEnabledTeamcity teamcity = tcHelper.server(info.srvId, tcHelper.getServerAuthorizerCreds());
+ if (info.isCancelled(teamcity)) {
+ rmv.put(entry.getKey(), false);
- if (info.isFinishedWithFailures(teamcity)) {
- boolean rmv = compactInfos().remove(compactInfo);
+ logger.error("JIRA will not be commented." +
+ " [ticket: " + info.ticket + ", branch:" + info.branchForTc + "] : " +
+ "one or more re-runned blocker's builds finished with UNKNOWN status.");
- Preconditions.checkState(rmv, "Key not found: " + compactInfo);
+ continue;
+ }
- logger.error("JIRA will not be commented." +
- " [ticket: " + info.ticket + ", branch:" + info.branchForTc + "] : " +
- "one or more re-runned blocker's builds finished with UNKNOWN status.");
+ if (!info.isFinished(teamcity)) {
+ notFinishedBuilds += info.buildsCount() - info.finishedBuildsCount(teamcity);
- continue;
- }
+ continue;
+ }
- if (!info.isFinished(teamcity)) {
- notFinishedBuilds += info.buildsCount() - info.finishedBuildsCount();
+ Visa visa = visasHistStorage.getVisaRequest(info.getContributionKey(), info.date).getResult();
- continue;
- }
+ if (Objects.isNull(visa))
+ continue;
- try {
- rmvdVisas.add(objMapper.writeValueAsString(compactInfo));
- }
- catch (Exception e) {
- logger.error("JSON string parse failed: " + e.getMessage(), e);
+ if (!visa.isSuccess()) {
+ ICredentialsProv creds = tcHelper.getServerAuthorizerCreds();
- return "Exception while JSON parsing: " + e.getClass().getSimpleName() + ": " + e.getMessage();
- }
+ visa = jiraIntegration.notifyJira(info.srvId, creds, info.buildTypeId,
+ info.branchForTc, info.ticket);
- try {
- boolean rmv = compactInfos().remove(compactInfo);
+ visasHistStorage.updateVisaRequestResult(info.getContributionKey(), info.date, visa);
- if (!rmv)
- continue;
- }
- catch (Exception e) {
- logger.error("cache remove: " + e.getMessage(), e);
+ if (visa.isSuccess())
+ ticketsNotified.add(info.ticket);
+ }
- return X.getFullStackTrace(e);
+ if (visa.isSuccess())
+ rmv.put(entry.getKey(), false);
}
- ICredentialsProv creds = tcHelper.getServerAuthorizerCreds();
-
- Visa visa = jiraIntegration.notifyJira(info.srvId, creds, info.buildTypeId,
- info.branchForTc, info.ticket);
+ rmv.entrySet().forEach(entry -> {
+ try {
+ removeBuildInfo(entry.getKey());
- visasHistoryStorage.updateVisaRequestRes(info.getContributionKey(), info.date, visa);
+ entry.setValue(true);
+ }
+ catch (Exception e) {
+ logger.error(e.getMessage(), e);
+ }
+ });
- ticketsNotified.add(info.ticket);
+ return "Checked " + checkedBuilds + " not finished " + notFinishedBuilds + " notified: " + ticketsNotified +
+ " Rmv problems: " + rmv.values().stream().filter(v -> !v).count();
+ }
+ finally {
+ observationLock.unlock();
}
-
- return "Checked " + checkedBuilds + " not finished " + notFinishedBuilds + " notified: " + ticketsNotified +
- " Visas in queue: [" + String.join(", ", queuedVisas) +
- "] Visas to rmv: [" + String.join(", ", rmvdVisas) + ']';
}
}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/TcBotTriggerAndSignOffService.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/TcBotTriggerAndSignOffService.java
index 751050e..312a033 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/TcBotTriggerAndSignOffService.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/TcBotTriggerAndSignOffService.java
@@ -19,6 +19,7 @@ package org.apache.ignite.ci.tcbot.visa;
import com.google.common.base.Strings;
import com.google.inject.Provider;
+import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
@@ -38,6 +39,7 @@ import org.apache.ignite.ci.github.pure.IGitHubConnection;
import org.apache.ignite.ci.github.pure.IGitHubConnectionProvider;
import org.apache.ignite.ci.jira.IJiraIntegration;
import org.apache.ignite.ci.observer.BuildObserver;
+import org.apache.ignite.ci.observer.ObserverTask;
import org.apache.ignite.ci.observer.BuildsInfo;
import org.apache.ignite.ci.tcbot.chain.PrChainsProcessor;
import org.apache.ignite.ci.tcmodel.result.Build;
@@ -46,6 +48,7 @@ import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnited;
import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnitedProvider;
import org.apache.ignite.ci.teamcity.ignited.SyncMode;
+import org.apache.ignite.ci.web.model.ContributionKey;
import org.apache.ignite.ci.web.model.VisaRequest;
import org.apache.ignite.ci.web.model.Visa;
import org.apache.ignite.ci.user.ICredentialsProv;
@@ -56,10 +59,20 @@ import org.apache.ignite.internal.util.typedef.F;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import static org.apache.ignite.ci.observer.BuildsInfo.CANCELLED_STATUS;
+import static org.apache.ignite.ci.observer.BuildsInfo.FINISHED_STATUS;
+import static org.apache.ignite.ci.observer.BuildsInfo.RUNNING_STATUS;
+
/**
* Provides method for TC Bot Visa obtaining
*/
public class TcBotTriggerAndSignOffService {
+ /** */
+ private static final ThreadLocal<DateFormat> THREAD_FORMATTER = new ThreadLocal<DateFormat>() {
+ @Override protected DateFormat initialValue() {
+ return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ }
+ };
@Inject Provider<BuildObserver> buildObserverProvider;
@@ -88,12 +101,7 @@ public class TcBotTriggerAndSignOffService {
@Inject PrChainsProcessor prChainsProcessor;
-
-
- /** */
- //todo fix concurrency issue:
- private final SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-
+
/** */
public void startObserver() {
buildObserverProvider.get();
@@ -105,6 +113,8 @@ public class TcBotTriggerAndSignOffService {
IAnalyticsEnabledTeamcity teamcity = tcHelper.server(srvId, prov);
+ ObserverTask observerTask = buildObserverProvider.get().getObserverTask();
+
for (VisaRequest visaRequest : visasHistoryStorage.getVisas()) {
VisaStatus visaStatus = new VisaStatus();
@@ -112,15 +122,19 @@ public class TcBotTriggerAndSignOffService {
Visa visa = visaRequest.getResult();
- visaStatus.date = formatter.format(info.date);
+ visaStatus.date = THREAD_FORMATTER.get().format(info.date);
visaStatus.branchName = info.branchForTc;
visaStatus.userName = info.userName;
visaStatus.ticket = info.ticket;
- if (info.isFinished(teamcity)) {
- if (visa.isEmpty())
- visaStatus.state = BuildsInfo.FINISHED_STATE + " [ waiting results ]";
- else if (visa.isSuccess()) {
+ String buildsStatus = visaStatus.status = info.getState(teamcity);
+
+ BuildsInfo observInfo = observerTask.getInfo(info.getContributionKey());
+
+ boolean isObserving = Objects.nonNull(observInfo) && observInfo.date.equals(info.date);
+
+ if (FINISHED_STATUS.equals(buildsStatus)) {
+ if (visa.isSuccess()) {
visaStatus.commentUrl = "https://issues.apache.org/jira/browse/" + visaStatus.ticket +
"?focusedCommentId=" + visa.getJiraCommentResponse().getId() +
"&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-" +
@@ -128,13 +142,18 @@ public class TcBotTriggerAndSignOffService {
visaStatus.blockers = visa.getBlockers();
- visaStatus.state = BuildsInfo.FINISHED_STATE;
+ visaStatus.status = FINISHED_STATUS;
}
else
- visaStatus.state = BuildsInfo.FINISHED_WITH_FAILURES_STATE;
+ visaStatus.status = isObserving ? "waiting results" : CANCELLED_STATUS;
}
+ else if (RUNNING_STATUS.equals(buildsStatus))
+ visaStatus.status = isObserving ? RUNNING_STATUS : CANCELLED_STATUS;
else
- visaStatus.state = info.getState(teamcity);
+ visaStatus.status = buildsStatus;
+
+ if (isObserving)
+ visaStatus.cancelUrl = "/rest/visa/cancel?server=" + srvId + "&branch=" + info.branchForTc;
visaStatuses.add(visaStatus);
}
@@ -377,7 +396,7 @@ public class TcBotTriggerAndSignOffService {
else
status.resolvedBranch = !allRunAlls.isEmpty() ? allRunAlls.get(0).branchName(compactor) : branchForTcA(prId);
- String observationsStatus = observer.get().getObservationStatus(srvId, status.resolvedBranch);
+ String observationsStatus = observer.get().getObservationStatus(new ContributionKey(srvId, status.resolvedBranch));
status.observationsStatus = Strings.emptyToNull(observationsStatus);
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/VisaStatus.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/VisaStatus.java
index 1dfe31f..e20c52b 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/VisaStatus.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/VisaStatus.java
@@ -33,7 +33,7 @@ public class VisaStatus {
@Nullable public String ticket;
/** */
- @Nullable public String state;
+ @Nullable public String status;
/** */
@Nullable public String commentUrl;
@@ -42,5 +42,8 @@ public class VisaStatus {
@Nullable public String date;
/** */
+ @Nullable public String cancelUrl;
+
+ /** */
public int blockers;
}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/CompactContributionKey.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/CompactContributionKey.java
index 3c6a6f0..217a961 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/CompactContributionKey.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/CompactContributionKey.java
@@ -18,7 +18,6 @@
package org.apache.ignite.ci.web.model;
import java.util.Objects;
-
import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
/**
@@ -29,16 +28,17 @@ public class CompactContributionKey {
public final int srvId;
/** */
- public final int ticket;
-
- /** */
public final int branchForTc;
/** */
public CompactContributionKey(ContributionKey key, IStringCompactor strCompactor) {
this.branchForTc = strCompactor.getStringId(key.branchForTc);
this.srvId = strCompactor.getStringId(key.srvId);
- this.ticket = strCompactor.getStringId(key.ticket);
+ }
+
+ /** */
+ public ContributionKey toContributionKey(IStringCompactor strCompactor) {
+ return new ContributionKey(this, strCompactor);
}
/** {@inheritDoc} */
@@ -52,12 +52,11 @@ public class CompactContributionKey {
CompactContributionKey key = (CompactContributionKey)o;
return Objects.equals(srvId, key.srvId) &&
- Objects.equals(ticket, key.ticket) &&
Objects.equals(branchForTc, key.branchForTc);
}
/** {@inheritDoc} */
@Override public int hashCode() {
- return Objects.hash(srvId, branchForTc, ticket);
+ return Objects.hash(srvId, branchForTc);
}
}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/ContributionKey.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/ContributionKey.java
index fa62ea6..570f2c9 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/ContributionKey.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/ContributionKey.java
@@ -17,6 +17,8 @@
package org.apache.ignite.ci.web.model;
+import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
+
/**
*
*/
@@ -25,15 +27,22 @@ public class ContributionKey {
public final String srvId;
/** */
- public final String ticket;
-
- /** */
public final String branchForTc;
/** */
- public ContributionKey(String srvId, String ticket, String branchForTc) {
+ public ContributionKey(String srvId, String branchForTc) {
this.branchForTc = branchForTc;
this.srvId = srvId;
- this.ticket = ticket;
+ }
+
+ /** */
+ public ContributionKey(CompactContributionKey key, IStringCompactor strCompactor) {
+ this.branchForTc = strCompactor.getStringFromId(key.branchForTc);
+ this.srvId = strCompactor.getStringFromId(key.srvId);
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return "{srv: " + this.srvId + " branch: " + this.branchForTc + '}';
}
}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/Visa.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/Visa.java
index 4d234ba..e826cc4 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/Visa.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/Visa.java
@@ -76,7 +76,6 @@ public class Visa {
return EMPTY_VISA_STATUS.equals(status);
}
-
/** */
@Override public String toString() {
return status;
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/hist/VisasHistoryStorage.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/hist/VisasHistoryStorage.java
index 9a50296..28299f7 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/hist/VisasHistoryStorage.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/hist/VisasHistoryStorage.java
@@ -42,7 +42,7 @@ import org.apache.ignite.ci.web.model.VisaRequest;
*/
public class VisasHistoryStorage {
/** */
- private static final String VISAS_CACHE_NAME = "visasCompactCache";
+ private static final String VISAS_CACHE_NAME = "compactVisasHistoryCache";
/** */
@Inject
@@ -68,7 +68,6 @@ public class VisasHistoryStorage {
CompactContributionKey key = new CompactContributionKey(new ContributionKey(
visaReq.getInfo().srvId,
- visaReq.getInfo().ticket,
visaReq.getInfo().branchForTc), strCompactor);
Map<Date, CompactVisaRequest> contributionVisas = visas().get(key);
@@ -82,7 +81,7 @@ public class VisasHistoryStorage {
}
/** */
- public VisaRequest getVisaReq(ContributionKey key, Date date) {
+ public VisaRequest getVisaRequest(ContributionKey key, Date date) {
Map<Date, CompactVisaRequest> reqs = visas().get(new CompactContributionKey(key, strCompactor));
if (Objects.isNull(reqs))
@@ -92,8 +91,8 @@ public class VisasHistoryStorage {
}
/** */
- public boolean updateVisaRequestRes(ContributionKey key, Date date, Visa visa) {
- VisaRequest req = getVisaReq(key, date);
+ public boolean updateVisaRequestResult(ContributionKey key, Date date, Visa visa) {
+ VisaRequest req = getVisaRequest(key, date);
if (req == null)
return false;
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/visa/TcBotVisaService.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/visa/TcBotVisaService.java
index 18e2f60..f70975d 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/visa/TcBotVisaService.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/visa/TcBotVisaService.java
@@ -27,6 +27,7 @@ import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
+import org.apache.ignite.ci.observer.BuildObserver;
import org.apache.ignite.ci.tcbot.visa.ContributionCheckStatus;
import org.apache.ignite.ci.tcbot.visa.ContributionToCheck;
import org.apache.ignite.ci.tcbot.visa.CurrentVisaStatus;
@@ -34,7 +35,9 @@ import org.apache.ignite.ci.tcbot.visa.TcBotTriggerAndSignOffService;
import org.apache.ignite.ci.tcbot.visa.VisaStatus;
import org.apache.ignite.ci.user.ICredentialsProv;
import org.apache.ignite.ci.web.CtxListener;
+import org.apache.ignite.ci.web.model.ContributionKey;
import org.apache.ignite.ci.web.rest.exception.ServiceUnauthorizedException;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@Path("visa")
@@ -48,6 +51,16 @@ public class TcBotVisaService {
@Context
private HttpServletRequest req;
+ /** */
+ @GET
+ @Path("cancel")
+ public boolean stopObservation(@NotNull @QueryParam("server") String srv,
+ @NotNull @QueryParam("branch") String branchForTc) {
+ return CtxListener.getInjector(ctx)
+ .getInstance(BuildObserver.class)
+ .stopObservation(new ContributionKey(srv, branchForTc));
+ }
+
/**
* @param srvId Server id.
*/
diff --git a/ignite-tc-helper-web/src/main/webapp/visas.html b/ignite-tc-helper-web/src/main/webapp/visas.html
index 87c1864..cc8a950 100644
--- a/ignite-tc-helper-web/src/main/webapp/visas.html
+++ b/ignite-tc-helper-web/src/main/webapp/visas.html
@@ -22,7 +22,7 @@
<br>
<div id="loadStatus"></div>
<br>
- <table id="visasTable" class="cell-border" style="width:100%">
+ <table id="visasTable" class="row-border" style="width:100%">
<thead>
<tr class="ui-widget-header ">
<th>.</th>
@@ -73,6 +73,16 @@ $(document).ready(function() {
$.ajax({ url: "rest/branches/version", success: showVersionInfo, error: showErrInLoadStatus });
});
+function sendCancelRequest(url) {
+ $.ajax({
+ url: url,
+ success: function (result) {
+ location.reload();
+ },
+ error: showErrInLoadStatus
+ });
+}
+
function showVisasTable(result) {
let visasTable = $('#visasTable');
@@ -91,15 +101,28 @@ function showVisasTable(result) {
],
columns: [
{
- "data": "state",
+ "data": "status",
title: "Status",
"render": function (data, type, row, meta) {
+ let res = '';
+
if (type === 'display') {
- if (data ==='finished' && row.commentUrl)
- data = "<a href='" + row.commentUrl + "'>" + data + "</a>";
+ res += "<table width='100%'><tr><td width='70%' style='vertical-align: middle'>";
+
+ if (data === 'finished' && row.commentUrl)
+ res += "<a href='" + row.commentUrl + "'>" + data + "</a>";
+ else
+ res += data;
+
+ res += "</td><td width=\"30%\">";
+
+ if (row.cancelUrl != null)
+ res += '<button class="more white short" onclick="sendCancelRequest(\'' + row.cancelUrl + '\')">×</button>';
+
+ res += "</td></tr>";
}
- return data;
+ return res;
}
},
{
@@ -123,14 +146,13 @@ function showVisasTable(result) {
title: "Blockers",
"render": function (data, type, row, meta) {
if (type === 'display') {
- if (row.state != 'finished')
+ if (row.status != 'finished')
data = "";
}
return data;
}
}
-
]
});
}