*/
public interface CeQueue {
/**
- * Build an instance of {@link TaskSubmission} required for {@link #submit(TaskSubmission)}. It allows
+ * Build an instance of {@link CeTaskSubmit} required for {@link #submit(CeTaskSubmit)}. It allows
* to enforce that task ids are generated by the queue. It's used also for having access
* to the id before submitting the task to the queue.
*/
- TaskSubmission prepareSubmit();
+ CeTaskSubmit.Builder prepareSubmit();
/**
* Submits a task to the queue. The task is processed asynchronously.
* If submits are paused (see {@link #isSubmitPaused()}, then an
* unchecked exception is thrown.
*/
- CeTask submit(TaskSubmission submission);
+ CeTask submit(CeTaskSubmit submission);
/**
* Peek the oldest task in status {@link org.sonar.db.ce.CeQueueDto.Status#PENDING}.
package org.sonar.server.computation;
import com.google.common.base.Optional;
-import com.google.common.base.Strings;
import java.util.concurrent.atomic.AtomicBoolean;
-import javax.annotation.Nullable;
import org.sonar.api.server.ServerSide;
import org.sonar.api.utils.System2;
import org.sonar.core.util.UuidFactory;
import org.sonar.db.DbSession;
import org.sonar.db.ce.CeActivityDto;
import org.sonar.db.ce.CeQueueDto;
+import org.sonar.db.component.ComponentDto;
import org.sonar.server.computation.monitoring.CEQueueStatus;
-import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static java.lang.String.format;
}
@Override
- public TaskSubmission prepareSubmit() {
- return new TaskSubmissionImpl(uuidFactory.create());
+ public CeTaskSubmit.Builder prepareSubmit() {
+ return new CeTaskSubmit.Builder(uuidFactory.create());
}
@Override
- public CeTask submit(TaskSubmission submission) {
- checkArgument(!Strings.isNullOrEmpty(submission.getUuid()));
- checkArgument(!Strings.isNullOrEmpty(submission.getType()));
- checkArgument(submission instanceof TaskSubmissionImpl);
+ public CeTask submit(CeTaskSubmit submission) {
checkState(!submitPaused.get(), "Compute Engine does not currently accept new tasks");
- CeTask task = new CeTask(submission);
DbSession dbSession = dbClient.openSession(false);
try {
- CeQueueDto dto = createQueueDtoForSubmit(task);
+ CeQueueDto dto = new CeQueueDto();
+ dto.setUuid(submission.getUuid());
+ dto.setTaskType(submission.getType());
+ dto.setComponentUuid(submission.getComponentUuid());
+ dto.setStatus(CeQueueDto.Status.PENDING);
+ dto.setSubmitterLogin(submission.getSubmitterLogin());
+ dto.setStartedAt(null);
dbClient.ceQueueDao().insert(dbSession, dto);
+ CeTask task = loadTask(dbSession, dto);
dbSession.commit();
queueStatus.addReceived();
return task;
+
} finally {
dbClient.closeSession(dbSession);
}
}
- private CeQueueDto createQueueDtoForSubmit(CeTask task) {
- CeQueueDto dto = new CeQueueDto();
- dto.setUuid(task.getUuid());
- dto.setTaskType(task.getType());
- dto.setComponentUuid(task.getComponentUuid());
- dto.setStatus(CeQueueDto.Status.PENDING);
- dto.setSubmitterLogin(task.getSubmitterLogin());
- dto.setStartedAt(null);
- return dto;
- }
-
@Override
public Optional<CeTask> peek() {
if (peekPaused.get()) {
Optional<CeQueueDto> dto = dbClient.ceQueueDao().peek(dbSession);
CeTask task = null;
if (dto.isPresent()) {
+ task = loadTask(dbSession, dto.get());
queueStatus.addInProgress();
- task = new CeTask(dto.get());
}
return Optional.fromNullable(task);
}
}
+ private CeTask loadTask(DbSession dbSession, CeQueueDto dto) {
+ CeTask.Builder builder = new CeTask.Builder();
+ builder.setUuid(dto.getUuid());
+ builder.setType(dto.getTaskType());
+ builder.setSubmitterLogin(dto.getSubmitterLogin());
+ String componentUuid = dto.getComponentUuid();
+ if (componentUuid != null) {
+ builder.setComponentUuid(componentUuid);
+ Optional<ComponentDto> component = dbClient.componentDao().selectByUuid(dbSession, componentUuid);
+ if (component.isPresent()) {
+ builder.setComponentKey(component.get().getKey());
+ builder.setComponentName(component.get().name());
+ }
+ }
+ return builder.build();
+ }
+
@Override
public boolean cancel(String taskUuid) {
DbSession dbSession = dbClient.openSession(false);
}
void cancel(DbSession dbSession, CeQueueDto q) {
+ CeTask task = loadTask(dbSession, q);
CeActivityDto activityDto = new CeActivityDto(q);
activityDto.setStatus(CeActivityDto.Status.CANCELED);
- remove(dbSession, new CeTask(q), q, activityDto);
+ remove(dbSession, task, q, activityDto);
}
@Override
public boolean isPeekPaused() {
return peekPaused.get();
}
-
- private static class TaskSubmissionImpl implements TaskSubmission {
- private final String uuid;
- private String type;
- private String componentUuid;
- private String submitterLogin;
-
- private TaskSubmissionImpl(String uuid) {
- this.uuid = uuid;
- }
-
- @Override
- public String getUuid() {
- return uuid;
- }
-
- @Override
- public String getType() {
- return type;
- }
-
- @Override
- public TaskSubmission setType(@Nullable String s) {
- this.type = s;
- return this;
- }
-
- @Override
- public String getComponentUuid() {
- return componentUuid;
- }
-
- @Override
- public TaskSubmission setComponentUuid(@Nullable String s) {
- this.componentUuid = s;
- return this;
- }
-
- @Override
- public String getSubmitterLogin() {
- return submitterLogin;
- }
-
- @Override
- public TaskSubmission setSubmitterLogin(@Nullable String s) {
- this.submitterLogin = s;
- return this;
- }
- }
}
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
-import org.sonar.db.ce.CeQueueDto;
+import static com.google.common.base.Strings.emptyToNull;
import static java.util.Objects.requireNonNull;
@Immutable
private final String type;
private final String uuid;
private final String componentUuid;
+ private final String componentKey;
+ private final String componentName;
private final String submitterLogin;
- public CeTask(String uuid, String type, @Nullable String componentUuid, @Nullable String submitterLogin) {
- this.uuid = requireNonNull(uuid);
- this.type = requireNonNull(type);
- this.componentUuid = componentUuid;
- this.submitterLogin = submitterLogin;
- }
-
- CeTask(TaskSubmission submit) {
- this(submit.getUuid(), submit.getType(), submit.getComponentUuid(), submit.getSubmitterLogin());
- }
-
- CeTask(CeQueueDto dto) {
- this(dto.getUuid(), dto.getTaskType(), dto.getComponentUuid(), dto.getSubmitterLogin());
+ private CeTask(Builder builder) {
+ this.uuid = requireNonNull(emptyToNull(builder.uuid));
+ this.type = requireNonNull(emptyToNull(builder.type));
+ this.componentUuid = emptyToNull(builder.componentUuid);
+ this.componentKey = emptyToNull(builder.componentKey);
+ this.componentName = emptyToNull(builder.componentName);
+ this.submitterLogin = emptyToNull(builder.submitterLogin);
}
public String getUuid() {
return componentUuid;
}
+ @CheckForNull
+ public String getComponentKey() {
+ return componentKey;
+ }
+
+ @CheckForNull
+ public String getComponentName() {
+ return componentName;
+ }
+
@CheckForNull
public String getSubmitterLogin() {
return submitterLogin;
public int hashCode() {
return uuid.hashCode();
}
+
+ public static final class Builder {
+ private String uuid;
+ private String type;
+ private String componentUuid;
+ private String componentKey;
+ private String componentName;
+ private String submitterLogin;
+
+ public Builder setUuid(String uuid) {
+ this.uuid = uuid;
+ return this;
+ }
+
+ public Builder setType(String type) {
+ this.type = type;
+ return this;
+ }
+
+ public Builder setComponentUuid(String componentUuid) {
+ this.componentUuid = componentUuid;
+ return this;
+ }
+
+ public Builder setComponentKey(@Nullable String s) {
+ this.componentKey = s;
+ return this;
+ }
+
+ public Builder setComponentName(@Nullable String s) {
+ this.componentName = s;
+ return this;
+ }
+
+ public Builder setSubmitterLogin(@Nullable String s) {
+ this.submitterLogin = s;
+ return this;
+ }
+
+ public CeTask build() {
+ return new CeTask(this);
+ }
+ }
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation;
+
+import java.util.Objects;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
+import static com.google.common.base.Strings.emptyToNull;
+
+@Immutable
+public final class CeTaskSubmit {
+
+ private final String uuid;
+ private final String type;
+ private final String componentUuid;
+ private final String submitterLogin;
+
+ private CeTaskSubmit(Builder builder) {
+ this.uuid = Objects.requireNonNull(emptyToNull(builder.uuid));
+ this.type = Objects.requireNonNull(emptyToNull(builder.type));
+ this.componentUuid = emptyToNull(builder.componentUuid);
+ this.submitterLogin = emptyToNull(builder.submitterLogin);
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ @CheckForNull
+ public String getComponentUuid() {
+ return componentUuid;
+ }
+
+ @CheckForNull
+ public String getSubmitterLogin() {
+ return submitterLogin;
+ }
+
+ public static final class Builder {
+ private final String uuid;
+ private String type;
+ private String componentUuid;
+ private String submitterLogin;
+
+ Builder(String uuid) {
+ this.uuid = uuid;
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ public Builder setType(String s) {
+ this.type = s;
+ return this;
+ }
+
+ public Builder setComponentUuid(@Nullable String s) {
+ this.componentUuid = s;
+ return this;
+ }
+
+ public Builder setSubmitterLogin(@Nullable String s) {
+ this.submitterLogin = s;
+ return this;
+ }
+
+ public CeTaskSubmit build() {
+ return new CeTaskSubmit(this);
+ }
+ }
+}
import org.sonar.core.util.logs.Profiler;
import org.sonar.db.ce.CeActivityDto;
+import static java.lang.String.format;
+
public class CeWorkerImpl implements CeWorker {
private static final Logger LOG = Loggers.get(CeWorkerImpl.class);
@Override
public void run() {
- Profiler profiler = Profiler.create(LOG).start();
CeTask task;
try {
Optional<CeTask> taskOpt = queue.peek();
return;
}
+ // TODO delegate the message to the related task processor, according to task type
+ Profiler profiler = Profiler.create(LOG).startInfo(format("Analysis of project %s (report %s)", task.getComponentKey(), task.getUuid()));
try {
reportTaskProcessor.process(task);
queue.remove(task, CeActivityDto.Status.SUCCESS);
} catch (Throwable e) {
- LOG.error(String.format("Failed to process task %s", task.getUuid()), e);
+ LOG.error(format("Failed to process task %s", task.getUuid()), e);
queue.remove(task, CeActivityDto.Status.FAILED);
} finally {
- profiler.stopInfo(String.format("Total thread execution of project %s (report %s)", task.getComponentUuid(), task.getUuid()));
+
+ profiler.stopInfo();
}
}
}
this.settings = settings;
}
- public void save(TaskSubmission taskSubmit, InputStream reportInput) {
- File file = fileForUuid(taskSubmit.getUuid());
+ public void save(String taskUuid, InputStream reportInput) {
+ File file = fileForUuid(taskUuid);
try {
FileUtils.copyInputStreamToFile(reportInput, file);
} catch (Exception e) {
NewComponent newProject = new NewComponent(projectKey, StringUtils.defaultIfBlank(projectName, projectKey));
newProject.setBranch(projectBranch);
newProject.setQualifier(Qualifiers.PROJECT);
- // no need to verify the permission "provisionning" as it's already handled by componentService
+ // no need to verify the permission "provisioning" as it's already handled by componentService
project = componentService.create(newProject);
}
// the report file must be saved before submitting the task
- TaskSubmission submit = queue.prepareSubmit();
- reportFiles.save(submit, reportInput);
+ CeTaskSubmit.Builder submit = queue.prepareSubmit();
+ reportFiles.save(submit.getUuid(), reportInput);
submit.setType(CeTaskTypes.REPORT);
submit.setComponentUuid(project.uuid());
submit.setSubmitterLogin(userSession.getLogin());
- return queue.submit(submit);
+ return queue.submit(submit.build());
}
}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.computation;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-
-public interface TaskSubmission {
-
- String getUuid();
-
- String getType();
-
- TaskSubmission setType(String s);
-
- @CheckForNull
- String getComponentUuid();
-
- TaskSubmission setComponentUuid(@Nullable String s);
-
- @CheckForNull
- String getSubmitterLogin();
-
- TaskSubmission setSubmitterLogin(@Nullable String s);
-
-}
@Test
public void test_submit() {
- TaskSubmission submission = underTest.prepareSubmit();
+ CeTaskSubmit.Builder submission = underTest.prepareSubmit();
submission.setComponentUuid("PROJECT_1");
submission.setType(CeTaskTypes.REPORT);
submission.setSubmitterLogin("rob");
- CeTask task = underTest.submit(submission);
+ CeTask task = underTest.submit(submission.build());
assertThat(task.getUuid()).isEqualTo(submission.getUuid());
assertThat(task.getComponentUuid()).isEqualTo("PROJECT_1");
assertThat(task.getSubmitterLogin()).isEqualTo("rob");
}
private CeTask submit(String reportType, String componentUuid) {
- TaskSubmission submission = underTest.prepareSubmit();
+ CeTaskSubmit.Builder submission = underTest.prepareSubmit();
submission.setType(reportType);
submission.setComponentUuid(componentUuid);
- return underTest.submit(submission);
+ return underTest.submit(submission.build());
}
}
@Test
public void peek_and_process_task() throws Exception {
- CeTask task = new CeTask("TASK_1", CeTaskTypes.REPORT, "PROJECT_1", null);
+ CeTask task = new CeTask.Builder().setUuid("TASK_1").setType(CeTaskTypes.REPORT).setComponentUuid("PROJECT_1").setSubmitterLogin(null).build();
when(queue.peek()).thenReturn(Optional.of(task));
underTest.run();
@Test
public void fail_to_process_task() throws Exception {
- CeTask task = new CeTask("TASK_1", CeTaskTypes.REPORT, "PROJECT_1", null);
+ CeTask task = new CeTask.Builder().setUuid("TASK_1").setType(CeTaskTypes.REPORT).setComponentUuid("PROJECT_1").setSubmitterLogin(null).build();
when(queue.peek()).thenReturn(Optional.of(task));
doThrow(new IllegalStateException()).when(taskProcessor).process(task);
@Test
public void remove_report_file_if_success() {
- CeTask task = new CeTask("TASK_1", CeTaskTypes.REPORT, "PROJECT_1", null);
+ CeTask task = new CeTask.Builder().setUuid("TASK_1").setType(CeTaskTypes.REPORT).setComponentUuid("PROJECT_1").setSubmitterLogin(null).build();
underTest.onRemoved(task, CeActivityDto.Status.SUCCESS);
verify(reportFiles).deleteIfExists("TASK_1");
@Test
public void remove_report_file_if_failure() {
- CeTask task = new CeTask("TASK_1", CeTaskTypes.REPORT, "PROJECT_1", null);
+ CeTask task = new CeTask.Builder().setUuid("TASK_1").setType(CeTaskTypes.REPORT).setComponentUuid("PROJECT_1").setSubmitterLogin(null).build();
underTest.onRemoved(task, CeActivityDto.Status.FAILED);
verify(reportFiles).deleteIfExists("TASK_1");
@Test
public void submit_a_report_on_existing_project() {
- when(queue.prepareSubmit()).thenReturn(new TestTaskSubmission("TASK_1"));
+ when(queue.prepareSubmit()).thenReturn(new CeTaskSubmit.Builder("TASK_1"));
userSession.setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
when(componentService.getNullableByKey("MY_PROJECT")).thenReturn(new ComponentDto().setUuid("P1"));
underTest.submit("MY_PROJECT", null, "My Project", IOUtils.toInputStream("{binary}"));
- verify(queue).submit(argThat(new TypeSafeMatcher<TaskSubmission>() {
+ verify(queue).submit(argThat(new TypeSafeMatcher<CeTaskSubmit>() {
@Override
- protected boolean matchesSafely(TaskSubmission submit) {
+ protected boolean matchesSafely(CeTaskSubmit submit) {
return submit.getType().equals(CeTaskTypes.REPORT) && submit.getComponentUuid().equals("P1") &&
submit.getUuid().equals("TASK_1");
}
@Test
public void provision_project_if_does_not_exist() throws Exception {
- when(queue.prepareSubmit()).thenReturn(new TestTaskSubmission("TASK_1"));
+ when(queue.prepareSubmit()).thenReturn(new CeTaskSubmit.Builder("TASK_1"));
userSession.setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION, GlobalPermissions.PROVISIONING);
when(componentService.getNullableByKey("MY_PROJECT")).thenReturn(null);
when(componentService.create(any(NewComponent.class))).thenReturn(new ComponentDto().setUuid("P1"));
underTest.submit("MY_PROJECT", null, "My Project", IOUtils.toInputStream("{binary}"));
- verify(queue).submit(argThat(new TypeSafeMatcher<TaskSubmission>() {
+ verify(queue).submit(argThat(new TypeSafeMatcher<CeTaskSubmit>() {
@Override
- protected boolean matchesSafely(TaskSubmission submit) {
+ protected boolean matchesSafely(CeTaskSubmit submit) {
return submit.getType().equals(CeTaskTypes.REPORT) && submit.getComponentUuid().equals("P1") &&
submit.getUuid().equals("TASK_1");
}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.computation;
-
-import javax.annotation.Nullable;
-
-public class TestTaskSubmission implements TaskSubmission {
- private final String uuid;
- private String type;
- private String componentUuid;
- private String submitterLogin;
-
- public TestTaskSubmission(String uuid) {
- this.uuid = uuid;
- }
-
- @Override
- public String getUuid() {
- return uuid;
- }
-
- @Override
- public String getType() {
- return type;
- }
-
- @Override
- public TaskSubmission setType(String s) {
- this.type = s;
- return this;
- }
-
- @Override
- public String getComponentUuid() {
- return componentUuid;
- }
-
- @Override
- public TaskSubmission setComponentUuid(@Nullable String s) {
- this.componentUuid = s;
- return this;
- }
-
- @Override
- public String getSubmitterLogin() {
- return submitterLogin;
- }
-
- @Override
- public TaskSubmission setSubmitterLogin(@Nullable String s) {
- this.submitterLogin = s;
- return this;
- }
-}
@Test
public void submit_task_to_the_queue_and_ask_for_immediate_processing() {
- CeTask task = new CeTask("TASK_1", CeTaskTypes.REPORT, "PROJECT_1", "robert");
+ CeTask task = new CeTask.Builder().setUuid("TASK_1").setType(CeTaskTypes.REPORT).setComponentUuid("PROJECT_1").setSubmitterLogin("robert").build();
when(reportSubmitter.submit(eq("my_project"), Matchers.isNull(String.class), eq("My Project"), any(InputStream.class))).thenReturn(task);
TestResponse wsResponse = tester.newRequest()
@Test
public void test_example_json_response() {
- CeTask task = new CeTask("TASK_1", CeTaskTypes.REPORT, "PROJECT_1", "robert");
+ CeTask task = new CeTask.Builder().setUuid("TASK_1").setType(CeTaskTypes.REPORT).setComponentUuid("PROJECT_1").setSubmitterLogin("robert").build();
when(reportSubmitter.submit(eq("my_project"), Matchers.isNull(String.class), eq("My Project"), any(InputStream.class))).thenReturn(task);
TestResponse wsResponse = tester.newRequest()
*/
@Test
public void project_name_is_optional() {
- CeTask task = new CeTask("TASK_1", CeTaskTypes.REPORT, "PROJECT_1", "robert");
+ CeTask task = new CeTask.Builder().setUuid("TASK_1").setType(CeTaskTypes.REPORT).setComponentUuid("PROJECT_1").setSubmitterLogin("robert").build();
when(reportSubmitter.submit(eq("my_project"), Matchers.isNull(String.class), eq("my_project"), any(InputStream.class))).thenReturn(task);
tester.newRequest()