@@ -19,6 +19,7 @@ | |||
*/ | |||
package org.sonar.ce.monitoring; | |||
import java.util.Optional; | |||
import org.sonar.api.ce.ComputeEngineSide; | |||
@ComputeEngineSide | |||
@@ -50,12 +51,12 @@ public interface CEQueueStatus { | |||
long addSuccess(long processingTime); | |||
/** | |||
* Adds 1 to the count of batch reports which processing ended with an error and removes 1 from the count of batch | |||
* reports under processing. Adds the specified time to the processing time counter. | |||
* Adds 1 to the count of tasks which processing ended with an error and removes 1 from the count of tasks | |||
* under processing. Adds the specified time to the processing time counter. | |||
* | |||
* @param processingTime duration of processing in ms | |||
* | |||
* @return the new count of batch reports which processing ended with an error | |||
* @return the new count of tasks which processing ended with an error | |||
* | |||
* @see #getErrorCount() | |||
* @see #getInProgressCount() | |||
@@ -65,27 +66,32 @@ public interface CEQueueStatus { | |||
long addError(long processingTime); | |||
/** | |||
* Count of batch reports waiting for processing since startup, including reports received before instance startup. | |||
* Number of pending tasks, including tasks received before instance startup. | |||
*/ | |||
long getPendingCount(); | |||
/** | |||
* Count of batch reports under processing. | |||
* The age, in ms, of the oldest pending task. | |||
*/ | |||
Optional<Long> getLongestTimePending(); | |||
/** | |||
* Count of tasks under processing. | |||
*/ | |||
long getInProgressCount(); | |||
/** | |||
* Count of batch reports which processing ended with an error since instance startup. | |||
* Count of tasks which processing ended with an error since instance startup. | |||
*/ | |||
long getErrorCount(); | |||
/** | |||
* Count of batch reports which processing ended successfully since instance startup. | |||
* Count of tasks which processing ended successfully since instance startup. | |||
*/ | |||
long getSuccessCount(); | |||
/** | |||
* Time spent processing batch reports since startup, in milliseconds. | |||
* Time spent processing tasks since startup, in milliseconds. | |||
*/ | |||
long getProcessingTime(); | |||
@@ -21,6 +21,7 @@ package org.sonar.ce.monitoring; | |||
import java.util.Optional; | |||
import java.util.concurrent.atomic.AtomicLong; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.ce.CeQueueDto; | |||
@@ -31,13 +32,15 @@ import static com.google.common.base.Preconditions.checkArgument; | |||
public class CEQueueStatusImpl implements CEQueueStatus { | |||
private final DbClient dbClient; | |||
private final System2 system; | |||
private final AtomicLong inProgress = new AtomicLong(0); | |||
private final AtomicLong error = new AtomicLong(0); | |||
private final AtomicLong success = new AtomicLong(0); | |||
private final AtomicLong processingTime = new AtomicLong(0); | |||
public CEQueueStatusImpl(DbClient dbClient) { | |||
public CEQueueStatusImpl(DbClient dbClient, System2 system) { | |||
this.dbClient = dbClient; | |||
this.system = system; | |||
} | |||
@Override | |||
@@ -71,6 +74,14 @@ public class CEQueueStatusImpl implements CEQueueStatus { | |||
} | |||
} | |||
@Override | |||
public Optional<Long> getLongestTimePending() { | |||
try (DbSession dbSession = dbClient.openSession(false)) { | |||
return dbClient.ceQueueDao().selectCreationDateOfOldestPendingByMainComponentUuid(dbSession, null) | |||
.map(creationDate -> system.now() - creationDate); | |||
} | |||
} | |||
@Override | |||
public boolean areWorkersPaused() { | |||
try (DbSession dbSession = dbClient.openSession(false)) { |
@@ -20,33 +20,39 @@ | |||
package org.sonar.ce.monitoring; | |||
import java.util.List; | |||
import java.util.Optional; | |||
public interface CeTasksMBean { | |||
String OBJECT_NAME = "SonarQube:name=ComputeEngineTasks"; | |||
/** | |||
* Count of batch reports waiting for processing since startup, including reports received before instance startup. | |||
* Number of pending tasks, including tasks received before instance startup. | |||
*/ | |||
long getPendingCount(); | |||
/** | |||
* Count of batch reports under processing. | |||
* The age, in ms, of the oldest pending task. | |||
*/ | |||
Optional<Long> getLongestTimePending(); | |||
/** | |||
* Count of tasks under processing. | |||
*/ | |||
long getInProgressCount(); | |||
/** | |||
* Count of batch reports which processing ended with an error since instance startup. | |||
* Count of tasks which processing ended with an error since instance startup. | |||
*/ | |||
long getErrorCount(); | |||
/** | |||
* Count of batch reports which processing ended successfully since instance startup. | |||
* Count of tasks which processing ended successfully since instance startup. | |||
*/ | |||
long getSuccessCount(); | |||
/** | |||
* Time spent processing reports since startup, in milliseconds. | |||
* Time spent processing tasks since startup, in milliseconds. | |||
*/ | |||
long getProcessingTime(); | |||
@@ -20,6 +20,7 @@ | |||
package org.sonar.ce.monitoring; | |||
import java.util.List; | |||
import java.util.Optional; | |||
import java.util.Set; | |||
import java.util.stream.Collectors; | |||
import org.picocontainer.Startable; | |||
@@ -62,6 +63,11 @@ public class CeTasksMBeanImpl implements CeTasksMBean, Startable, SystemInfoSect | |||
return queueStatus.getPendingCount(); | |||
} | |||
@Override | |||
public Optional<Long> getLongestTimePending() { | |||
return queueStatus.getLongestTimePending(); | |||
} | |||
@Override | |||
public long getInProgressCount() { | |||
return queueStatus.getInProgressCount(); | |||
@@ -116,6 +122,7 @@ public class CeTasksMBeanImpl implements CeTasksMBean, Startable, SystemInfoSect | |||
ProtobufSystemInfo.Section.Builder builder = ProtobufSystemInfo.Section.newBuilder(); | |||
builder.setName("Compute Engine Tasks"); | |||
builder.addAttributesBuilder().setKey("Pending").setLongValue(getPendingCount()).build(); | |||
builder.addAttributesBuilder().setKey("Longest Time Pending (ms)").setLongValue(getLongestTimePending().orElse(0L)).build(); | |||
builder.addAttributesBuilder().setKey("In Progress").setLongValue(getInProgressCount()).build(); | |||
builder.addAttributesBuilder().setKey("Processed With Error").setLongValue(getErrorCount()).build(); | |||
builder.addAttributesBuilder().setKey("Processed With Success").setLongValue(getSuccessCount()).build(); |
@@ -19,11 +19,12 @@ | |||
*/ | |||
package org.sonar.ce.monitoring; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.db.DbClient; | |||
public class DistributedCEQueueStatusImpl extends CEQueueStatusImpl { | |||
public DistributedCEQueueStatusImpl(DbClient dbClient) { | |||
super(dbClient); | |||
public DistributedCEQueueStatusImpl(DbClient dbClient, System2 system2) { | |||
super(dbClient, system2); | |||
} | |||
@Override |
@@ -28,6 +28,7 @@ import java.util.concurrent.ThreadFactory; | |||
import java.util.concurrent.TimeUnit; | |||
import org.junit.After; | |||
import org.junit.Test; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.db.DbClient; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
@@ -42,7 +43,7 @@ public class CEQueueStatusImplConcurrentTest { | |||
return new Thread(r, CEQueueStatusImplConcurrentTest.class.getSimpleName() + cnt++); | |||
} | |||
}); | |||
private CEQueueStatusImpl underTest = new CEQueueStatusImpl(mock(DbClient.class)); | |||
private CEQueueStatusImpl underTest = new CEQueueStatusImpl(mock(DbClient.class), mock(System2.class)); | |||
@After | |||
public void tearDown() { |
@@ -21,6 +21,7 @@ package org.sonar.ce.monitoring; | |||
import org.junit.Test; | |||
import org.mockito.Mockito; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.ce.CeQueueDto; | |||
@@ -31,7 +32,7 @@ import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
public class CEQueueStatusImplTest extends CommonCEQueueStatusImplTest { | |||
private CEQueueStatusImpl underTest = new CEQueueStatusImpl(getDbClient()); | |||
private CEQueueStatusImpl underTest = new CEQueueStatusImpl(getDbClient(), mock(System2.class)); | |||
public CEQueueStatusImplTest() { | |||
super(mock(DbClient.class, Mockito.RETURNS_DEEP_STUBS)); |
@@ -22,6 +22,7 @@ package org.sonar.ce.monitoring; | |||
import com.google.common.collect.ImmutableSet; | |||
import java.lang.management.ManagementFactory; | |||
import java.util.List; | |||
import java.util.Optional; | |||
import java.util.Random; | |||
import java.util.Set; | |||
import java.util.stream.Collectors; | |||
@@ -46,6 +47,7 @@ import static org.mockito.Mockito.when; | |||
public class CeTasksMBeanImplTest { | |||
private static final long PENDING_COUNT = 2; | |||
private static final Optional<Long> PENDING_TIME = Optional.of(10_000L); | |||
private static final long IN_PROGRESS_COUNT = 5; | |||
private static final long ERROR_COUNT = 10; | |||
private static final long SUCCESS_COUNT = 13; | |||
@@ -91,6 +93,7 @@ public class CeTasksMBeanImplTest { | |||
@Test | |||
public void get_methods_delegate_to_the_CEQueueStatus_instance() { | |||
assertThat(underTest.getPendingCount()).isEqualTo(PENDING_COUNT); | |||
assertThat(underTest.getLongestTimePending()).isEqualTo(PENDING_TIME); | |||
assertThat(underTest.getInProgressCount()).isEqualTo(IN_PROGRESS_COUNT); | |||
assertThat(underTest.getErrorCount()).isEqualTo(ERROR_COUNT); | |||
assertThat(underTest.getSuccessCount()).isEqualTo(SUCCESS_COUNT); | |||
@@ -142,7 +145,7 @@ public class CeTasksMBeanImplTest { | |||
public void export_system_info() { | |||
ProtobufSystemInfo.Section section = underTest.toProtobuf(); | |||
assertThat(section.getName()).isEqualTo("Compute Engine Tasks"); | |||
assertThat(section.getAttributesCount()).isEqualTo(8); | |||
assertThat(section.getAttributesCount()).isEqualTo(9); | |||
} | |||
private static class DumbCEQueueStatus implements CEQueueStatus { | |||
@@ -152,6 +155,11 @@ public class CeTasksMBeanImplTest { | |||
return PENDING_COUNT; | |||
} | |||
@Override | |||
public Optional<Long> getLongestTimePending() { | |||
return PENDING_TIME; | |||
} | |||
@Override | |||
public long addInProgress() { | |||
return methodNotImplemented(); | |||
@@ -197,6 +205,7 @@ public class CeTasksMBeanImplTest { | |||
} | |||
} | |||
private static class DumbCeConfiguration implements CeConfiguration { | |||
@Override |
@@ -21,6 +21,7 @@ package org.sonar.ce.monitoring; | |||
import org.junit.Test; | |||
import org.mockito.Mockito; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.db.DbClient; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
@@ -28,7 +29,7 @@ import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.verifyZeroInteractions; | |||
public class DistributedCEQueueStatusImplTest extends CommonCEQueueStatusImplTest { | |||
private DistributedCEQueueStatusImpl underTest = new DistributedCEQueueStatusImpl(getDbClient()); | |||
private DistributedCEQueueStatusImpl underTest = new DistributedCEQueueStatusImpl(getDbClient(), mock(System2.class)); | |||
public DistributedCEQueueStatusImplTest() { | |||
super(mock(DbClient.class, Mockito.RETURNS_DEEP_STUBS)); |
@@ -80,7 +80,7 @@ public class InternalCeQueueImplTest { | |||
private DbSession session = db.getSession(); | |||
private UuidFactory uuidFactory = UuidFactoryImpl.INSTANCE; | |||
private CEQueueStatus queueStatus = new CEQueueStatusImpl(db.getDbClient()); | |||
private CEQueueStatus queueStatus = new CEQueueStatusImpl(db.getDbClient(), mock(System2.class)); | |||
private DefaultOrganizationProvider defaultOrganizationProvider = mock(DefaultOrganizationProvider.class); | |||
private ComputeEngineStatus computeEngineStatus = mock(ComputeEngineStatus.class); | |||
private InternalCeQueue underTest = new InternalCeQueueImpl(system2, db.getDbClient(), uuidFactory, queueStatus, defaultOrganizationProvider, computeEngineStatus); |
@@ -142,9 +142,12 @@ public class CeQueueDao implements Dao { | |||
return mapper(dbSession).countByStatusAndMainComponentUuid(status, mainComponentUuid); | |||
} | |||
public Optional<Long> selectCreationDateOfOldestPendingByMainComponentUuid(DbSession dbSession, @Nullable String mainComponentUuid) { | |||
return Optional.ofNullable(mapper(dbSession).selectCreationDateOfOldestPendingByMainComponentUuid(mainComponentUuid)); | |||
} | |||
/** | |||
* Counts entries in the queue with the specified status for each specified main component uuid. | |||
* | |||
* The returned map doesn't contain any entry for main component uuids for which there is no entry in the queue (ie. | |||
* all entries have a value >= 0). | |||
*/ |
@@ -68,6 +68,9 @@ public interface CeQueueMapper { | |||
int countByStatusAndMainComponentUuid(@Param("status") CeQueueDto.Status status, @Nullable @Param("mainComponentUuid") String mainComponentUuid); | |||
@CheckForNull | |||
Long selectCreationDateOfOldestPendingByMainComponentUuid(@Nullable @Param("mainComponentUuid") String mainComponentUuid); | |||
List<QueueCount> countByStatusAndMainComponentUuids(@Param("status") CeQueueDto.Status status, @Param("mainComponentUuids") List<String> mainComponentUuids); | |||
void insert(CeQueueDto dto); |
@@ -49,6 +49,18 @@ | |||
</if> | |||
</select> | |||
<select id="selectCreationDateOfOldestPendingByMainComponentUuid" parameterType="map" resultType="Long"> | |||
select | |||
min(created_at) | |||
from | |||
ce_queue | |||
where | |||
status='PENDING' | |||
<if test="mainComponentUuid!=null"> | |||
and main_component_uuid=#{mainComponentUuid,jdbcType=VARCHAR} | |||
</if> | |||
</select> | |||
<select id="countByStatusAndMainComponentUuids" resultType="org.sonar.db.ce.QueueCount"> | |||
select | |||
main_component_uuid as mainComponentUuid, |
@@ -28,6 +28,7 @@ import java.util.List; | |||
import java.util.Map; | |||
import java.util.Optional; | |||
import java.util.Random; | |||
import java.util.function.Consumer; | |||
import java.util.stream.Stream; | |||
import javax.annotation.Nullable; | |||
import org.junit.Rule; | |||
@@ -172,6 +173,58 @@ public class CeQueueDaoTest { | |||
.containsOnly("p1", "p2", "p3"); | |||
} | |||
@Test | |||
public void selectCreationDateOfOldestPendingByMainComponentUuid_on_any_component_returns_date() { | |||
long time = alwaysIncreasingSystem2.now() + 10_000; | |||
insertPending("p1", dto -> { | |||
dto.setCreatedAt(time); | |||
dto.setUpdatedAt(time+500); | |||
dto.setMainComponentUuid("c1"); | |||
}); | |||
insertPending("p2", dto -> { | |||
dto.setCreatedAt(time + 1000); | |||
dto.setUpdatedAt(time + 2000); | |||
dto.setMainComponentUuid("c2"); | |||
}); | |||
makeInProgress("w1", alwaysIncreasingSystem2.now(), insertPending("i1", dto -> dto.setMainComponentUuid("c3"))); | |||
assertThat(underTest.selectCreationDateOfOldestPendingByMainComponentUuid(db.getSession(), null)) | |||
.isEqualTo(Optional.of(time)); | |||
} | |||
@Test | |||
public void selectCreationDateOfOldestPendingByMainComponentUuid_on_specific_component_returns_date() { | |||
long time = alwaysIncreasingSystem2.now() + 10_000; | |||
insertPending("p1", dto -> { | |||
dto.setCreatedAt(time); | |||
dto.setUpdatedAt(time+500); | |||
dto.setMainComponentUuid("c2"); | |||
}); | |||
insertPending("p2", dto -> { | |||
dto.setCreatedAt(time + 2000); | |||
dto.setUpdatedAt(time + 3000); | |||
dto.setMainComponentUuid("c1"); | |||
}); | |||
insertPending("p3", dto -> { | |||
dto.setCreatedAt(time + 4000); | |||
dto.setUpdatedAt(time + 5000); | |||
dto.setMainComponentUuid("c1"); | |||
}); | |||
makeInProgress("w1", alwaysIncreasingSystem2.now(), insertPending("i1", dto -> dto.setMainComponentUuid("c1"))); | |||
assertThat(underTest.selectCreationDateOfOldestPendingByMainComponentUuid(db.getSession(), "c1")) | |||
.isEqualTo(Optional.of(time+2000)); | |||
} | |||
@Test | |||
public void selectCreationDateOfOldestPendingByMainComponentUuid_returns_empty_when_no_pending_tasks() { | |||
makeInProgress("w1", alwaysIncreasingSystem2.now(), insertPending("i1")); | |||
assertThat(underTest.selectCreationDateOfOldestPendingByMainComponentUuid(db.getSession(), null)) | |||
.isEmpty(); | |||
} | |||
@Test | |||
public void selectWornout_returns_task_pending_with_a_non_null_startedAt() { | |||
insertPending("p1"); | |||
@@ -583,11 +636,18 @@ public class CeQueueDaoTest { | |||
} | |||
private CeQueueDto insertPending(String uuid) { | |||
return insertPending(uuid, (Consumer<CeQueueDto>) null); | |||
} | |||
private CeQueueDto insertPending(String uuid, @Nullable Consumer<CeQueueDto> dtoConsumer) { | |||
CeQueueDto dto = new CeQueueDto(); | |||
dto.setUuid(uuid); | |||
dto.setTaskType(CeTaskTypes.REPORT); | |||
dto.setStatus(PENDING); | |||
dto.setSubmitterUuid("henri"); | |||
if (dtoConsumer != null) { | |||
dtoConsumer.accept(dto); | |||
} | |||
underTestAlwaysIncreasingSystem2.insert(db.getSession(), dto); | |||
db.getSession().commit(); | |||
return dto; | |||
@@ -629,7 +689,7 @@ public class CeQueueDaoTest { | |||
} | |||
private void verifyCeQueueStatuses(String taskUuid1, CeQueueDto.Status taskStatus1, String taskUuid2, CeQueueDto.Status taskStatus2) { | |||
verifyCeQueueStatuses(new String[]{taskUuid1, taskUuid2}, new CeQueueDto.Status[]{taskStatus1, taskStatus2}); | |||
verifyCeQueueStatuses(new String[] {taskUuid1, taskUuid2}, new CeQueueDto.Status[] {taskStatus1, taskStatus2}); | |||
} | |||
private void verifyCeQueueStatuses(String[] taskUuids, CeQueueDto.Status[] statuses) { |
@@ -19,10 +19,13 @@ | |||
*/ | |||
package org.sonar.server.ce.ws; | |||
import com.google.common.base.Optional; | |||
import java.util.Optional; | |||
import javax.annotation.CheckForNull; | |||
import javax.annotation.Nullable; | |||
import org.sonar.api.server.ws.Change; | |||
import org.sonar.api.server.ws.Response; | |||
import org.sonar.api.server.ws.WebService; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.api.web.UserRole; | |||
import org.sonar.core.util.Uuids; | |||
import org.sonar.db.DbClient; | |||
@@ -44,18 +47,20 @@ public class ActivityStatusAction implements CeWsAction { | |||
private final UserSession userSession; | |||
private final DbClient dbClient; | |||
private final ComponentFinder componentFinder; | |||
private final System2 system2; | |||
public ActivityStatusAction(UserSession userSession, DbClient dbClient, ComponentFinder componentFinder) { | |||
public ActivityStatusAction(UserSession userSession, DbClient dbClient, ComponentFinder componentFinder, System2 system2) { | |||
this.userSession = userSession; | |||
this.dbClient = dbClient; | |||
this.componentFinder = componentFinder; | |||
this.system2 = system2; | |||
} | |||
@Override | |||
public void define(WebService.NewController controller) { | |||
WebService.NewAction action = controller | |||
.createAction("activity_status") | |||
.setDescription("Return CE activity related metrics.<br>" + | |||
.setDescription("Returns CE activity related metrics.<br>" + | |||
"Requires 'Administer System' permission or 'Administer' rights on the specified project.") | |||
.setSince("5.5") | |||
.setResponseExample(getClass().getResource("activity_status-example.json")) | |||
@@ -70,6 +75,7 @@ public class ActivityStatusAction implements CeWsAction { | |||
.setExampleValue(KeyExamples.KEY_PROJECT_EXAMPLE_001); | |||
action.setChangelog(new Change("6.6", "New field 'inProgress' in response")); | |||
action.setChangelog(new Change("7.8", "New field 'pendingTime' in response, only included when there are pending tasks")); | |||
} | |||
@Override | |||
@@ -81,17 +87,25 @@ public class ActivityStatusAction implements CeWsAction { | |||
private ActivityStatusWsResponse doHandle(Request request) { | |||
try (DbSession dbSession = dbClient.openSession(false)) { | |||
Optional<ComponentDto> component = searchComponent(dbSession, request); | |||
String componentUuid = component.isPresent() ? component.get().uuid() : null; | |||
String componentUuid = component.map(ComponentDto::uuid).orElse(null); | |||
checkPermissions(component); | |||
int pendingCount = dbClient.ceQueueDao().countByStatusAndMainComponentUuid(dbSession, CeQueueDto.Status.PENDING, componentUuid); | |||
int inProgressCount = dbClient.ceQueueDao().countByStatusAndMainComponentUuid(dbSession, CeQueueDto.Status.IN_PROGRESS, componentUuid); | |||
int failingCount = dbClient.ceActivityDao().countLastByStatusAndMainComponentUuid(dbSession, CeActivityDto.Status.FAILED, componentUuid); | |||
return ActivityStatusWsResponse.newBuilder() | |||
Optional<Long> creationDate = dbClient.ceQueueDao().selectCreationDateOfOldestPendingByMainComponentUuid(dbSession, componentUuid); | |||
ActivityStatusWsResponse.Builder builder = ActivityStatusWsResponse.newBuilder() | |||
.setPending(pendingCount) | |||
.setInProgress(inProgressCount) | |||
.setFailing(failingCount) | |||
.build(); | |||
.setFailing(failingCount); | |||
creationDate.ifPresent(d -> { | |||
long ageOfOldestPendingTime = system2.now() - d; | |||
builder.setPendingTime(ageOfOldestPendingTime); | |||
}); | |||
return builder.build(); | |||
} | |||
} | |||
@@ -100,7 +114,7 @@ public class ActivityStatusAction implements CeWsAction { | |||
if (hasComponentInRequest(request)) { | |||
component = componentFinder.getByUuidOrKey(dbSession, request.getComponentId(), request.getComponentKey(), COMPONENT_ID_AND_KEY); | |||
} | |||
return Optional.fromNullable(component); | |||
return Optional.ofNullable(component); | |||
} | |||
private void checkPermissions(Optional<ComponentDto> component) { | |||
@@ -116,30 +130,24 @@ public class ActivityStatusAction implements CeWsAction { | |||
} | |||
private static Request toWsRequest(org.sonar.api.server.ws.Request request) { | |||
return new Request() | |||
.setComponentId(request.param(PARAM_COMPONENT_ID)) | |||
.setComponentKey(request.param(DEPRECATED_PARAM_COMPONENT_KEY)); | |||
return new Request(request.param(PARAM_COMPONENT_ID), request.param(DEPRECATED_PARAM_COMPONENT_KEY)); | |||
} | |||
private static class Request { | |||
private String componentId; | |||
private String componentKey; | |||
public Request setComponentId(String componentId) { | |||
Request(@Nullable String componentId, @Nullable String componentKey) { | |||
this.componentId = componentId; | |||
return this; | |||
this.componentKey = componentKey; | |||
} | |||
@CheckForNull | |||
public String getComponentId() { | |||
return componentId; | |||
} | |||
public Request setComponentKey(String componentKey) { | |||
this.componentKey = componentKey; | |||
return this; | |||
} | |||
@CheckForNull | |||
public String getComponentKey() { | |||
return componentKey; | |||
} |
@@ -1,5 +1,6 @@ | |||
{ | |||
"pending": 2, | |||
"inProgress": 1, | |||
"failing": 5 | |||
"failing": 5, | |||
"pendingTime": 100123 | |||
} |
@@ -44,6 +44,8 @@ import org.sonar.server.ws.WsActionTester; | |||
import org.sonarqube.ws.Ce; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
import static org.sonar.db.ce.CeQueueTesting.newCeQueueDto; | |||
import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; | |||
import static org.sonar.server.ce.ws.CeWsParameters.DEPRECATED_PARAM_COMPONENT_KEY; | |||
@@ -59,9 +61,11 @@ public class ActivityStatusActionTest { | |||
@Rule | |||
public DbTester db = DbTester.create(System2.INSTANCE); | |||
private System2 system2 = mock(System2.class); | |||
private DbClient dbClient = db.getDbClient(); | |||
private DbSession dbSession = db.getSession(); | |||
private WsActionTester ws = new WsActionTester(new ActivityStatusAction(userSession, dbClient, TestComponentFinder.from(db))); | |||
private WsActionTester ws = new WsActionTester(new ActivityStatusAction(userSession, dbClient, TestComponentFinder.from(db), system2)); | |||
@Test | |||
public void test_definition() { | |||
@@ -74,7 +78,8 @@ public class ActivityStatusActionTest { | |||
@Test | |||
public void json_example() { | |||
dbClient.ceQueueDao().insert(dbSession, newCeQueueDto("ce-queue-uuid-1").setStatus(CeQueueDto.Status.PENDING)); | |||
when(system2.now()).thenReturn(200123L); | |||
dbClient.ceQueueDao().insert(dbSession, newCeQueueDto("ce-queue-uuid-1").setStatus(CeQueueDto.Status.PENDING).setCreatedAt(100000)); | |||
dbClient.ceQueueDao().insert(dbSession, newCeQueueDto("ce-queue-uuid-2").setStatus(CeQueueDto.Status.PENDING)); | |||
dbClient.ceQueueDao().insert(dbSession, newCeQueueDto("ce-queue-uuid-3").setStatus(CeQueueDto.Status.IN_PROGRESS)); | |||
for (int i = 0; i < 5; i++) { | |||
@@ -118,6 +123,23 @@ public class ActivityStatusActionTest { | |||
assertThat(result.getFailing()).isEqualTo(1); | |||
} | |||
@Test | |||
public void add_pending_time() { | |||
String projectUuid = "project-uuid"; | |||
OrganizationDto organizationDto = db.organizations().insert(); | |||
ComponentDto project = newPrivateProjectDto(organizationDto, projectUuid); | |||
db.components().insertComponent(project); | |||
userSession.logIn().addProjectPermission(UserRole.ADMIN, project); | |||
when(system2.now()).thenReturn(2000L); | |||
insertInQueue(CeQueueDto.Status.PENDING, project, 1000L); | |||
Ce.ActivityStatusWsResponse result = call(projectUuid); | |||
assertThat(result).extracting(Ce.ActivityStatusWsResponse::getPending, Ce.ActivityStatusWsResponse::getFailing, | |||
Ce.ActivityStatusWsResponse::getInProgress, Ce.ActivityStatusWsResponse::getPendingTime) | |||
.containsOnly(1, 0, 0, 1000L); | |||
} | |||
@Test | |||
public void empty_status() { | |||
Ce.ActivityStatusWsResponse result = call(); | |||
@@ -171,9 +193,17 @@ public class ActivityStatusActionTest { | |||
} | |||
private void insertInQueue(CeQueueDto.Status status, @Nullable ComponentDto componentDto) { | |||
dbClient.ceQueueDao().insert(dbSession, newCeQueueDto(Uuids.createFast()) | |||
insertInQueue(status, componentDto, null); | |||
} | |||
private void insertInQueue(CeQueueDto.Status status, @Nullable ComponentDto componentDto, @Nullable Long createdAt) { | |||
CeQueueDto ceQueueDto = newCeQueueDto(Uuids.createFast()) | |||
.setStatus(status) | |||
.setComponent(componentDto)); | |||
.setComponent(componentDto); | |||
if (createdAt != null) { | |||
ceQueueDto.setCreatedAt(createdAt); | |||
} | |||
dbClient.ceQueueDao().insert(dbSession, ceQueueDto); | |||
db.commit(); | |||
} | |||
@@ -49,6 +49,7 @@ message ActivityStatusWsResponse { | |||
optional int32 pending = 1; | |||
optional int32 failing = 2; | |||
optional int32 inProgress = 3; | |||
optional int64 pendingTime = 4; | |||
} | |||
// GET api/ce/analysis_status |