From: Sébastien Lesaint Date: Tue, 29 Sep 2015 16:51:23 +0000 (+0200) Subject: SONAR-6749 add CeTaskProcessor concept to support process Views tasks X-Git-Tag: 5.2-RC1~139 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=f8f3d6d0b12c37f9346a81ed6895a30a369ff806;p=sonarqube.git SONAR-6749 add CeTaskProcessor concept to support process Views tasks --- diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/container/ReportProcessingModule.java b/server/sonar-server/src/main/java/org/sonar/server/computation/container/ReportProcessingModule.java index 12db121dab1..12d0e0e76f4 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/container/ReportProcessingModule.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/container/ReportProcessingModule.java @@ -21,7 +21,7 @@ package org.sonar.server.computation.container; import org.sonar.core.platform.Module; import org.sonar.server.computation.queue.report.ReportSubmitter; -import org.sonar.server.computation.queue.report.ReportTaskProcessor; +import org.sonar.server.computation.taskprocessor.report.ReportTaskProcessor; import org.sonar.server.computation.step.ComputationStepExecutor; public class ReportProcessingModule extends Module { diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/CeProcessingScheduler.java b/server/sonar-server/src/main/java/org/sonar/server/computation/queue/CeProcessingScheduler.java deleted file mode 100644 index fa82e55a0f1..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/CeProcessingScheduler.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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.queue; - -public interface CeProcessingScheduler { - - void startScheduling(); - -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/CeProcessingSchedulerExecutorService.java b/server/sonar-server/src/main/java/org/sonar/server/computation/queue/CeProcessingSchedulerExecutorService.java deleted file mode 100644 index bed8e1f09f9..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/CeProcessingSchedulerExecutorService.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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.queue; - -import org.sonar.server.util.StoppableScheduledExecutorService; - -/** - * The {@link java.util.concurrent.ExecutorService} responsible for running {@link CeWorkerRunnableImpl}. - */ -public interface CeProcessingSchedulerExecutorService extends StoppableScheduledExecutorService { -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/CeProcessingSchedulerExecutorServiceImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/queue/CeProcessingSchedulerExecutorServiceImpl.java deleted file mode 100644 index e9eb954a6d5..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/CeProcessingSchedulerExecutorServiceImpl.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.queue; - -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import org.sonar.server.util.AbstractStoppableScheduledExecutorServiceImpl; - -public class CeProcessingSchedulerExecutorServiceImpl extends AbstractStoppableScheduledExecutorServiceImpl - implements CeProcessingSchedulerExecutorService { - private static final String THREAD_NAME_PREFIX = "ce-processor-"; - - public CeProcessingSchedulerExecutorServiceImpl() { - super( - Executors.newSingleThreadScheduledExecutor( - new ThreadFactoryBuilder() - .setNameFormat(THREAD_NAME_PREFIX + "%d") - .setPriority(Thread.MIN_PRIORITY) - .build())); - } - -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/CeProcessingSchedulerImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/queue/CeProcessingSchedulerImpl.java deleted file mode 100644 index b9d32e14fb0..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/CeProcessingSchedulerImpl.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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.queue; - -import java.util.concurrent.TimeUnit; - -public class CeProcessingSchedulerImpl implements CeProcessingScheduler { - private final CeProcessingSchedulerExecutorService executorService; - private final CeWorkerRunnable workerRunnable; - - private final long delayBetweenTasks; - private final long delayForFirstStart; - private final TimeUnit timeUnit; - - public CeProcessingSchedulerImpl(CeProcessingSchedulerExecutorService processingExecutorService, CeWorkerRunnable workerRunnable) { - this.executorService = processingExecutorService; - this.workerRunnable = workerRunnable; - - this.delayBetweenTasks = 10; - this.delayForFirstStart = 0; - this.timeUnit = TimeUnit.SECONDS; - } - - @Override - public void startScheduling() { - executorService.scheduleAtFixedRate(workerRunnable, delayForFirstStart, delayBetweenTasks, timeUnit); - } - -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/CeQueueInitializer.java b/server/sonar-server/src/main/java/org/sonar/server/computation/queue/CeQueueInitializer.java index 526eb16f0bd..3f63721405a 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/CeQueueInitializer.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/queue/CeQueueInitializer.java @@ -24,6 +24,7 @@ import org.sonar.api.server.ServerSide; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.server.computation.monitoring.CEQueueStatus; +import org.sonar.server.computation.taskprocessor.CeProcessingScheduler; /** * Cleans-up the queue, initializes JMX counters then schedule diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/CeQueueModule.java b/server/sonar-server/src/main/java/org/sonar/server/computation/queue/CeQueueModule.java index 67c5bc6de63..0af3f348ccf 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/CeQueueModule.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/queue/CeQueueModule.java @@ -29,25 +29,19 @@ public class CeQueueModule extends Module { @Override protected void configureModule() { add( - // queue state - CeQueueImpl.class, + // queue state + CeQueueImpl.class, - // queue monitoring - CEQueueStatusImpl.class, - ComputeEngineQueueMonitor.class, + // queue monitoring + CEQueueStatusImpl.class, + ComputeEngineQueueMonitor.class, - // CE queue processing - CeProcessingSchedulerExecutorServiceImpl.class, - CeWorkerRunnableImpl.class, - CeProcessingSchedulerImpl.class, + // queue cleaning + CeQueueCleaner.class, + CleanReportQueueListener.class, + ReportFiles.class, - // queue cleaning - CeQueueCleaner.class, - CleanReportQueueListener.class, - ReportFiles.class, - - // init queue state and queue processing - CeQueueInitializer.class - ); + // init queue state and queue processing + CeQueueInitializer.class); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/CeWorkerRunnable.java b/server/sonar-server/src/main/java/org/sonar/server/computation/queue/CeWorkerRunnable.java deleted file mode 100644 index 5de95c6be16..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/CeWorkerRunnable.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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.queue; - -/** - * Marker interface of the runnable in charge of polling the {@link CeQueue} and executing {@link CeTask}. - */ -public interface CeWorkerRunnable extends Runnable { -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/CeWorkerRunnableImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/queue/CeWorkerRunnableImpl.java deleted file mode 100644 index 9b46bb3a696..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/CeWorkerRunnableImpl.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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.queue; - -import com.google.common.base.Optional; -import org.sonar.api.utils.log.Logger; -import org.sonar.api.utils.log.Loggers; -import org.sonar.core.util.logs.Profiler; -import org.sonar.db.ce.CeActivityDto; -import org.sonar.server.computation.log.CeLogging; -import org.sonar.server.computation.queue.report.ReportTaskProcessor; - -import static java.lang.String.format; - -public class CeWorkerRunnableImpl implements CeWorkerRunnable { - - private static final Logger LOG = Loggers.get(CeWorkerRunnableImpl.class); - - private final CeQueue queue; - private final ReportTaskProcessor reportTaskProcessor; - private final CeLogging ceLogging; - - public CeWorkerRunnableImpl(CeQueue queue, ReportTaskProcessor reportTaskProcessor, CeLogging ceLogging) { - this.queue = queue; - this.reportTaskProcessor = reportTaskProcessor; - this.ceLogging = ceLogging; - } - - @Override - public void run() { - Optional ceTask = tryAndFindTaskToExecute(); - if (!ceTask.isPresent()) { - return; - } - - executeTask(ceTask.get()); - } - - private Optional tryAndFindTaskToExecute() { - try { - return queue.peek(); - } catch (Exception e) { - LOG.error("Failed to pop the queue of analysis reports", e); - } - return Optional.absent(); - } - - private void executeTask(CeTask task) { - // logging twice: once in sonar.log and once in CE appender - Profiler regularProfiler = startProfiler(task); - ceLogging.initForTask(task); - Profiler ceProfiler = startProfiler(task); - - CeActivityDto.Status status = CeActivityDto.Status.FAILED; - try { - // TODO delegate the message to the related task processor, according to task type - reportTaskProcessor.process(task); - status = CeActivityDto.Status.SUCCESS; - queue.remove(task, status); - } catch (Throwable e) { - LOG.error(format("Failed to execute task %s", task.getUuid()), e); - queue.remove(task, status); - } finally { - // logging twice: once in sonar.log and once in CE appender - stopProfiler(ceProfiler, task, status); - ceLogging.clearForTask(); - stopProfiler(regularProfiler, task, status); - } - } - - private static Profiler startProfiler(CeTask task) { - return Profiler.create(LOG).startInfo("Execute task | project={} | id={}", task.getComponentKey(), task.getUuid()); - } - - private static void stopProfiler(Profiler profiler, CeTask task, CeActivityDto.Status status) { - if (status == CeActivityDto.Status.FAILED) { - profiler.stopError("Executed task | project={} | id={}", task.getComponentKey(), task.getUuid()); - } else { - profiler.stopInfo("Executed task | project={} | id={}", task.getComponentKey(), task.getUuid()); - } - } -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/report/ReportTaskProcessor.java b/server/sonar-server/src/main/java/org/sonar/server/computation/queue/report/ReportTaskProcessor.java deleted file mode 100644 index ed4693f6d42..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/report/ReportTaskProcessor.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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.queue.report; - -import org.sonar.core.platform.ComponentContainer; -import org.sonar.server.computation.step.ComputationStepExecutor; -import org.sonar.server.computation.container.ComputeEngineContainer; -import org.sonar.server.computation.container.ContainerFactory; -import org.sonar.server.computation.queue.CeTask; - -public class ReportTaskProcessor { - - private final ContainerFactory containerFactory; - private final ComponentContainer serverContainer; - - public ReportTaskProcessor(ContainerFactory containerFactory, ComponentContainer serverContainer) { - this.containerFactory = containerFactory; - this.serverContainer = serverContainer; - } - - public void process(CeTask task) { - ComputeEngineContainer ceContainer = containerFactory.create(serverContainer, task); - try { - ceContainer.getComponentByType(ComputationStepExecutor.class).execute(); - } finally { - ceContainer.cleanup(); - } - } -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeProcessingScheduler.java b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeProcessingScheduler.java new file mode 100644 index 00000000000..feaf513508e --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeProcessingScheduler.java @@ -0,0 +1,26 @@ +/* + * 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.taskprocessor; + +public interface CeProcessingScheduler { + + void startScheduling(); + +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeProcessingSchedulerExecutorService.java b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeProcessingSchedulerExecutorService.java new file mode 100644 index 00000000000..3fc101ed7ab --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeProcessingSchedulerExecutorService.java @@ -0,0 +1,28 @@ +/* + * 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.taskprocessor; + +import org.sonar.server.util.StoppableScheduledExecutorService; + +/** + * The {@link java.util.concurrent.ExecutorService} responsible for running {@link CeWorkerRunnableImpl}. + */ +public interface CeProcessingSchedulerExecutorService extends StoppableScheduledExecutorService { +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeProcessingSchedulerExecutorServiceImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeProcessingSchedulerExecutorServiceImpl.java new file mode 100644 index 00000000000..8ea57466439 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeProcessingSchedulerExecutorServiceImpl.java @@ -0,0 +1,40 @@ +/* + * 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.taskprocessor; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import org.sonar.server.util.AbstractStoppableScheduledExecutorServiceImpl; + +public class CeProcessingSchedulerExecutorServiceImpl extends AbstractStoppableScheduledExecutorServiceImpl + implements CeProcessingSchedulerExecutorService { + private static final String THREAD_NAME_PREFIX = "ce-processor-"; + + public CeProcessingSchedulerExecutorServiceImpl() { + super( + Executors.newSingleThreadScheduledExecutor( + new ThreadFactoryBuilder() + .setNameFormat(THREAD_NAME_PREFIX + "%d") + .setPriority(Thread.MIN_PRIORITY) + .build())); + } + +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeProcessingSchedulerImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeProcessingSchedulerImpl.java new file mode 100644 index 00000000000..d9e346a7028 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeProcessingSchedulerImpl.java @@ -0,0 +1,46 @@ +/* + * 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.taskprocessor; + +import java.util.concurrent.TimeUnit; + +public class CeProcessingSchedulerImpl implements CeProcessingScheduler { + private final CeProcessingSchedulerExecutorService executorService; + private final CeWorkerRunnable workerRunnable; + + private final long delayBetweenTasks; + private final long delayForFirstStart; + private final TimeUnit timeUnit; + + public CeProcessingSchedulerImpl(CeProcessingSchedulerExecutorService processingExecutorService, CeWorkerRunnable workerRunnable) { + this.executorService = processingExecutorService; + this.workerRunnable = workerRunnable; + + this.delayBetweenTasks = 10; + this.delayForFirstStart = 0; + this.timeUnit = TimeUnit.SECONDS; + } + + @Override + public void startScheduling() { + executorService.scheduleAtFixedRate(workerRunnable, delayForFirstStart, delayBetweenTasks, timeUnit); + } + +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeTaskProcessor.java b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeTaskProcessor.java new file mode 100644 index 00000000000..16edeb61f1d --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeTaskProcessor.java @@ -0,0 +1,55 @@ +/* + * 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.taskprocessor; + +import java.util.Set; +import org.sonar.server.computation.queue.CeTask; + +/** + * This interface is used to provide the processing code for {@link CeTask}s of one or more type to be called by the + * Compute Engine. + */ +public interface CeTaskProcessor { + + /** + * The {@link CeTask#getType()} for which this {@link CeTaskProcessor} provides the processing code. + *

+ * The match of type is done using {@link String#equals(Object)} and if more than one {@link CeTaskProcessor} declares + * itself had handler for the same {@link CeTask#getType()}, an error will be raised at startup and startup will + * fail. + *

+ *

+ * If an empty {@link Set} is returned, the {@link CeTaskProcessor} will be ignored. + *

+ */ + Set getHandledCeTaskTypes(); + + /** + * Call the processing code for a specific {@link CeTask}. + *

+ * The specified is guaranteed to be non {@code null} and its {@link CeTask#getType()} to be one of the values + * of {@link #getHandledCeTaskTypes()}. + *

+ * + * @throws RuntimeException when thrown, it will be caught and logged by the Compute Engine and the processing of the + * specified {@link CeTask} will be flagged as failed. + */ + void process(CeTask task); +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeTaskProcessorModule.java b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeTaskProcessorModule.java new file mode 100644 index 00000000000..8ae68bd4789 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeTaskProcessorModule.java @@ -0,0 +1,33 @@ +/* + * 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.taskprocessor; + +import org.sonar.core.platform.Module; + +public class CeTaskProcessorModule extends Module { + @Override + protected void configureModule() { + add( + CeTaskProcessorRepositoryImpl.class, + CeWorkerRunnableImpl.class, + CeProcessingSchedulerExecutorServiceImpl.class, + CeProcessingSchedulerImpl.class); + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeTaskProcessorRepository.java b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeTaskProcessorRepository.java new file mode 100644 index 00000000000..be4be617acb --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeTaskProcessorRepository.java @@ -0,0 +1,33 @@ +/* + * 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.taskprocessor; + +import com.google.common.base.Optional; +import org.sonar.server.computation.queue.CeTask; + +public interface CeTaskProcessorRepository { + + /** + * @throws NullPointerException if the specified {@link CeTask} is {@code null} + * @throws IllegalStateException if there is no {@link CeTaskProcessor} for the specified {@link CeTask} in the repository + */ + Optional getForCeTask(CeTask ceTask); + +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeTaskProcessorRepositoryImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeTaskProcessorRepositoryImpl.java new file mode 100644 index 00000000000..4a19ff7ba8b --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeTaskProcessorRepositoryImpl.java @@ -0,0 +1,104 @@ +/* + * 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.taskprocessor; + +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.base.Optional; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import java.util.Collection; +import java.util.Map; +import javax.annotation.Nonnull; +import org.sonar.server.computation.queue.CeTask; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.collect.FluentIterable.from; +import static java.lang.String.CASE_INSENSITIVE_ORDER; +import static java.lang.String.format; + +/** + * {@link CeTaskProcessorRepository} implementation which provides access to the {@link CeTaskProcessor} existing in the + * PicoContainer the current object belongs to. + */ +public class CeTaskProcessorRepositoryImpl implements CeTaskProcessorRepository { + private static final Joiner COMMA_JOINER = Joiner.on(", "); + + private final Map taskProcessorByCeTaskType; + + public CeTaskProcessorRepositoryImpl(CeTaskProcessor[] taskProcessors) { + this.taskProcessorByCeTaskType = indexTaskProcessors(taskProcessors); + } + + @Override + public Optional getForCeTask(CeTask ceTask) { + return Optional.fromNullable(taskProcessorByCeTaskType.get(ceTask.getType())); + } + + private static Map indexTaskProcessors(CeTaskProcessor[] taskProcessors) { + Multimap permissiveIndex = buildPermissiveCeTaskProcessorIndex(taskProcessors); + checkUniqueHandlerPerCeTaskType(permissiveIndex); + return ImmutableMap.copyOf(Maps.transformValues(permissiveIndex.asMap(), CeTaskProcessorCollectionToFirstElement.INSTANCE)); + } + + private static Multimap buildPermissiveCeTaskProcessorIndex(CeTaskProcessor[] taskProcessors) { + Multimap permissiveIndex = ArrayListMultimap.create(taskProcessors.length, 1); + for (CeTaskProcessor taskProcessor : taskProcessors) { + for (String ceTaskType : taskProcessor.getHandledCeTaskTypes()) { + permissiveIndex.put(ceTaskType, taskProcessor); + } + } + return permissiveIndex; + } + + private static void checkUniqueHandlerPerCeTaskType(Multimap permissiveIndex) { + for (Map.Entry> entry : permissiveIndex.asMap().entrySet()) { + checkArgument( + entry.getValue().size() == 1, + format( + "There can be only one CeTaskProcessor instance registered as the processor for CeTask type %s. " + + "More than one found. Please fix your configuration: %s", + entry.getKey(), + COMMA_JOINER.join(from(entry.getValue()).transform(ToClassName.INSTANCE).toSortedList(CASE_INSENSITIVE_ORDER)))); + } + } + + private enum ToClassName implements Function { + INSTANCE; + + @Override + @Nonnull + public String apply(@Nonnull Object input) { + return input.getClass().getName(); + } + } + + private enum CeTaskProcessorCollectionToFirstElement implements Function, CeTaskProcessor> { + INSTANCE; + + @Override + @Nonnull + public CeTaskProcessor apply(@Nonnull Collection input) { + return input.iterator().next(); + } + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeWorkerRunnable.java b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeWorkerRunnable.java new file mode 100644 index 00000000000..2df1a66743e --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeWorkerRunnable.java @@ -0,0 +1,29 @@ +/* + * 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.taskprocessor; + +import org.sonar.server.computation.queue.CeQueue; +import org.sonar.server.computation.queue.CeTask; + +/** + * Marker interface of the runnable in charge of polling the {@link CeQueue} and executing {@link CeTask}. + */ +public interface CeWorkerRunnable extends Runnable { +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeWorkerRunnableImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeWorkerRunnableImpl.java new file mode 100644 index 00000000000..e20b6ac647e --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/CeWorkerRunnableImpl.java @@ -0,0 +1,107 @@ +/* + * 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.taskprocessor; + +import com.google.common.base.Optional; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; +import org.sonar.core.util.logs.Profiler; +import org.sonar.db.ce.CeActivityDto; +import org.sonar.server.computation.log.CeLogging; +import org.sonar.server.computation.queue.CeQueue; +import org.sonar.server.computation.queue.CeTask; + +import static java.lang.String.format; + +public class CeWorkerRunnableImpl implements CeWorkerRunnable { + + private static final Logger LOG = Loggers.get(CeWorkerRunnableImpl.class); + + private final CeQueue queue; + private final CeLogging ceLogging; + private final CeTaskProcessorRepository taskProcessorRepository; + + public CeWorkerRunnableImpl(CeQueue queue, CeLogging ceLogging, CeTaskProcessorRepository taskProcessorRepository) { + this.queue = queue; + this.ceLogging = ceLogging; + this.taskProcessorRepository = taskProcessorRepository; + } + + @Override + public void run() { + Optional ceTask = tryAndFindTaskToExecute(); + if (!ceTask.isPresent()) { + return; + } + + executeTask(ceTask.get()); + } + + private Optional tryAndFindTaskToExecute() { + try { + return queue.peek(); + } catch (Exception e) { + LOG.error("Failed to pop the queue of analysis reports", e); + } + return Optional.absent(); + } + + private void executeTask(CeTask task) { + // logging twice: once in sonar.log and once in CE appender + Profiler regularProfiler = startProfiler(task); + ceLogging.initForTask(task); + Profiler ceProfiler = startProfiler(task); + + CeActivityDto.Status status = CeActivityDto.Status.FAILED; + try { + // TODO delegate the message to the related task processor, according to task type + Optional taskProcessor = taskProcessorRepository.getForCeTask(task); + if (taskProcessor.isPresent()) { + taskProcessor.get().process(task); + status = CeActivityDto.Status.SUCCESS; + } else { + LOG.error("No CeTaskProcessor is defined for task of type {}. Plugin configuration may have changed", task.getType()); + status = CeActivityDto.Status.FAILED; + } + queue.remove(task, status); + } catch (Throwable e) { + LOG.error(format("Failed to execute task %s", task.getUuid()), e); + queue.remove(task, status); + } finally { + // logging twice: once in sonar.log and once in CE appender + stopProfiler(ceProfiler, task, status); + ceLogging.clearForTask(); + stopProfiler(regularProfiler, task, status); + } + } + + private static Profiler startProfiler(CeTask task) { + return Profiler.create(LOG).startInfo("Execute task | project={} | id={}", task.getComponentKey(), task.getUuid()); + } + + private static void stopProfiler(Profiler profiler, CeTask task, CeActivityDto.Status status) { + if (status == CeActivityDto.Status.FAILED) { + profiler.stopError("Executed task | project={} | id={}", task.getComponentKey(), task.getUuid()); + } else { + profiler.stopInfo("Executed task | project={} | id={}", task.getComponentKey(), task.getUuid()); + } + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/package-info.java new file mode 100644 index 00000000000..58194f63cf3 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/package-info.java @@ -0,0 +1,24 @@ +/* + * 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. + */ + +@ParametersAreNonnullByDefault +package org.sonar.server.computation.taskprocessor; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/report/ReportTaskProcessor.java b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/report/ReportTaskProcessor.java new file mode 100644 index 00000000000..e0b1dcd60e0 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/report/ReportTaskProcessor.java @@ -0,0 +1,58 @@ +/* + * 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.taskprocessor.report; + +import java.util.Collections; +import java.util.Set; +import org.sonar.core.platform.ComponentContainer; +import org.sonar.db.ce.CeTaskTypes; +import org.sonar.server.computation.taskprocessor.CeTaskProcessor; +import org.sonar.server.computation.step.ComputationStepExecutor; +import org.sonar.server.computation.container.ComputeEngineContainer; +import org.sonar.server.computation.container.ContainerFactory; +import org.sonar.server.computation.queue.CeTask; + +public class ReportTaskProcessor implements CeTaskProcessor { + + private static final Set HANDLED_TYPES = Collections.singleton(CeTaskTypes.REPORT); + + private final ContainerFactory containerFactory; + private final ComponentContainer serverContainer; + + public ReportTaskProcessor(ContainerFactory containerFactory, ComponentContainer serverContainer) { + this.containerFactory = containerFactory; + this.serverContainer = serverContainer; + } + + @Override + public Set getHandledCeTaskTypes() { + return HANDLED_TYPES; + } + + @Override + public void process(CeTask task) { + ComputeEngineContainer ceContainer = containerFactory.create(serverContainer, task); + try { + ceContainer.getComponentByType(ComputationStepExecutor.class).execute(); + } finally { + ceContainer.cleanup(); + } + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/report/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/report/package-info.java new file mode 100644 index 00000000000..c21d764b8cf --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/report/package-info.java @@ -0,0 +1,24 @@ +/* + * 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. + */ + +@ParametersAreNonnullByDefault +package org.sonar.server.computation.taskprocessor.report; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java index 1af4c400a59..f21981e8380 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java @@ -64,6 +64,7 @@ import org.sonar.server.component.ws.ResourcesWs; import org.sonar.server.computation.CeModule; import org.sonar.server.computation.container.ReportProcessingModule; import org.sonar.server.computation.queue.CeQueueModule; +import org.sonar.server.computation.taskprocessor.CeTaskProcessorModule; import org.sonar.server.computation.ws.CeWsModule; import org.sonar.server.config.ws.PropertiesWs; import org.sonar.server.dashboard.template.GlobalDefaultDashboard; @@ -701,6 +702,7 @@ public class PlatformLevel4 extends PlatformLevel { // Compute engine CeModule.class, CeQueueModule.class, + CeTaskProcessorModule.class, CeWsModule.class, ReportProcessingModule.class, diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/queue/CeProcessingSchedulerImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/queue/CeProcessingSchedulerImplTest.java deleted file mode 100644 index b76640dd572..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/queue/CeProcessingSchedulerImplTest.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.queue; - -import java.util.concurrent.TimeUnit; -import org.junit.Test; - -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.same; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; - -public class CeProcessingSchedulerImplTest { - private CeProcessingSchedulerExecutorService processingExecutorService = mock(CeProcessingSchedulerExecutorService.class); - private CeWorkerRunnable workerRunnable = mock(CeWorkerRunnable.class); - private CeProcessingSchedulerImpl underTest = new CeProcessingSchedulerImpl(processingExecutorService, workerRunnable); - - @Test - public void startScheduling_schedules_CeWorkerRunnable_at_fixed_rate_run_head_of_queue() { - underTest.startScheduling(); - - verify(processingExecutorService).scheduleAtFixedRate(same(workerRunnable), eq(0L), eq(10L), eq(TimeUnit.SECONDS)); - verifyNoMoreInteractions(processingExecutorService); - } - -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/queue/CeQueueInitializerTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/queue/CeQueueInitializerTest.java index 9c09fe0610b..2fdb02bfb39 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/queue/CeQueueInitializerTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/queue/CeQueueInitializerTest.java @@ -34,6 +34,7 @@ import org.sonar.db.ce.CeTaskTypes; import org.sonar.server.computation.queue.report.ReportFiles; import org.sonar.server.computation.monitoring.CEQueueStatus; import org.sonar.server.computation.monitoring.CEQueueStatusImpl; +import org.sonar.server.computation.taskprocessor.CeProcessingScheduler; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.any; diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/queue/CeWorkerRunnableImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/queue/CeWorkerRunnableImplTest.java deleted file mode 100644 index aae8a538d64..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/queue/CeWorkerRunnableImplTest.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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.queue; - -import com.google.common.base.Optional; -import org.junit.Test; -import org.mockito.InOrder; -import org.mockito.Mockito; -import org.sonar.db.ce.CeActivityDto; -import org.sonar.db.ce.CeTaskTypes; -import org.sonar.server.computation.queue.report.ReportTaskProcessor; -import org.sonar.server.computation.log.CeLogging; - -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; - -public class CeWorkerRunnableImplTest { - - CeQueue queue = mock(CeQueueImpl.class); - ReportTaskProcessor taskProcessor = mock(ReportTaskProcessor.class); - CeLogging ceLogging = mock(CeLogging.class); - CeWorkerRunnable underTest = new CeWorkerRunnableImpl(queue, taskProcessor, ceLogging); - - @Test - public void no_pending_tasks_in_queue() throws Exception { - when(queue.peek()).thenReturn(Optional.absent()); - - underTest.run(); - - verifyZeroInteractions(taskProcessor, ceLogging); - } - - @Test - public void peek_and_process_task() throws Exception { - 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(); - - InOrder inOrder = Mockito.inOrder(ceLogging, taskProcessor, queue); - inOrder.verify(ceLogging).initForTask(task); - inOrder.verify(taskProcessor).process(task); - inOrder.verify(queue).remove(task, CeActivityDto.Status.SUCCESS); - inOrder.verify(ceLogging).clearForTask(); - } - - @Test - public void fail_to_process_task() throws Exception { - 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); - - underTest.run(); - - InOrder inOrder = Mockito.inOrder(ceLogging, taskProcessor, queue); - inOrder.verify(ceLogging).initForTask(task); - inOrder.verify(taskProcessor).process(task); - inOrder.verify(queue).remove(task, CeActivityDto.Status.FAILED); - inOrder.verify(ceLogging).clearForTask(); - } -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/taskprocessor/CeProcessingSchedulerImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/taskprocessor/CeProcessingSchedulerImplTest.java new file mode 100644 index 00000000000..9dfa6da2453 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/taskprocessor/CeProcessingSchedulerImplTest.java @@ -0,0 +1,44 @@ +/* + * 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.taskprocessor; + +import java.util.concurrent.TimeUnit; +import org.junit.Test; + +import static org.mockito.Matchers.eq; +import static org.mockito.Matchers.same; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +public class CeProcessingSchedulerImplTest { + private CeProcessingSchedulerExecutorService processingExecutorService = mock(CeProcessingSchedulerExecutorService.class); + private CeWorkerRunnable workerRunnable = mock(CeWorkerRunnable.class); + private CeProcessingSchedulerImpl underTest = new CeProcessingSchedulerImpl(processingExecutorService, workerRunnable); + + @Test + public void startScheduling_schedules_CeWorkerRunnable_at_fixed_rate_run_head_of_queue() { + underTest.startScheduling(); + + verify(processingExecutorService).scheduleAtFixedRate(same(workerRunnable), eq(0L), eq(10L), eq(TimeUnit.SECONDS)); + verifyNoMoreInteractions(processingExecutorService); + } + +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/taskprocessor/CeTaskProcessorRepositoryImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/taskprocessor/CeTaskProcessorRepositoryImplTest.java new file mode 100644 index 00000000000..6b865959f86 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/taskprocessor/CeTaskProcessorRepositoryImplTest.java @@ -0,0 +1,145 @@ +/* + * 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.taskprocessor; + +import com.google.common.collect.ImmutableSet; +import java.util.Set; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.server.computation.queue.CeTask; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.guava.api.Assertions.assertThat; + +public class CeTaskProcessorRepositoryImplTest { + private static final String SOME_CE_TASK_TYPE = "some type"; + private static final String SOME_COMPONENT_KEY = "key"; + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Test + public void constructor_accepts_empty_array_argument() { + new CeTaskProcessorRepositoryImpl(new CeTaskProcessor[] {}); + } + + @Test + public void constructor_throws_IAE_if_two_TaskProcessor_handle_the_same_CeTask_type() { + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage( + "There can be only one CeTaskProcessor instance registered as the processor for CeTask type " + SOME_CE_TASK_TYPE + ". " + + "More than one found. Please fix your configuration: " + SomeProcessor1.class.getName() + ", " + SomeProcessor2.class.getName()); + + new CeTaskProcessorRepositoryImpl(new CeTaskProcessor[] { + new SomeProcessor1(SOME_CE_TASK_TYPE), + new SomeProcessor2(SOME_CE_TASK_TYPE) + }); + } + + @Test + public void constructor_throws_IAE_if_multiple_TaskProcessor_overlap_their_supported_CeTask_type() { + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage( + "There can be only one CeTaskProcessor instance registered as the processor for CeTask type " + SOME_CE_TASK_TYPE + ". " + + "More than one found. Please fix your configuration: " + SomeProcessor1.class.getName() + ", " + SomeProcessor2.class.getName()); + + new CeTaskProcessorRepositoryImpl(new CeTaskProcessor[] { + new SomeProcessor2(SOME_CE_TASK_TYPE + "_2", SOME_CE_TASK_TYPE), + new SomeProcessor1(SOME_CE_TASK_TYPE, SOME_CE_TASK_TYPE + "_3") + }); + } + + @Test + public void getForTask_returns_absent_if_repository_is_empty() { + CeTaskProcessorRepositoryImpl underTest = new CeTaskProcessorRepositoryImpl(new CeTaskProcessor[] {}); + + assertThat(underTest.getForCeTask(createCeTask(SOME_CE_TASK_TYPE, SOME_COMPONENT_KEY))).isAbsent(); + } + + @Test + public void getForTask_returns_absent_if_repository_does_not_contain_matching_TaskProcessor() { + CeTaskProcessorRepositoryImpl underTest = new CeTaskProcessorRepositoryImpl(new CeTaskProcessor[] { + createCeTaskProcessor(SOME_CE_TASK_TYPE + "_1"), + createCeTaskProcessor(SOME_CE_TASK_TYPE + "_2", SOME_CE_TASK_TYPE + "_3"), + }); + + assertThat(underTest.getForCeTask(createCeTask(SOME_CE_TASK_TYPE, SOME_COMPONENT_KEY))).isAbsent(); + } + + @Test + public void getForTask_returns_TaskProcessor_based_on_CeTask_type_only() { + CeTaskProcessor taskProcessor = createCeTaskProcessor(SOME_CE_TASK_TYPE); + CeTaskProcessorRepositoryImpl underTest = new CeTaskProcessorRepositoryImpl(new CeTaskProcessor[] {taskProcessor}); + + assertThat(underTest.getForCeTask(createCeTask(SOME_CE_TASK_TYPE, SOME_COMPONENT_KEY)).get()).isSameAs(taskProcessor); + assertThat(underTest.getForCeTask(createCeTask(SOME_CE_TASK_TYPE, SOME_COMPONENT_KEY + "2")).get()).isSameAs(taskProcessor); + } + + @Test + public void getForTask_returns_TaskProcessor_even_if_it_is_not_specific() { + CeTaskProcessor taskProcessor = createCeTaskProcessor(SOME_CE_TASK_TYPE + "_1", SOME_CE_TASK_TYPE, SOME_CE_TASK_TYPE + "_3"); + CeTaskProcessorRepositoryImpl underTest = new CeTaskProcessorRepositoryImpl(new CeTaskProcessor[] {taskProcessor}); + + assertThat(underTest.getForCeTask(createCeTask(SOME_CE_TASK_TYPE, SOME_COMPONENT_KEY)).get()).isSameAs(taskProcessor); + } + + private CeTaskProcessor createCeTaskProcessor(final String... ceTaskTypes) { + return new HandleTypeOnlyTaskProcessor(ceTaskTypes); + } + + private static CeTask createCeTask(String ceTaskType, String key) { + return new CeTask.Builder() + .setType(ceTaskType) + .setUuid("task_uuid_" + key) + .setComponentKey(key).setComponentUuid("uuid_" + key).setComponentName("name_" + key) + .build(); + } + + private static class HandleTypeOnlyTaskProcessor implements CeTaskProcessor { + private final String[] ceTaskTypes; + + public HandleTypeOnlyTaskProcessor(String... ceTaskTypes) { + this.ceTaskTypes = ceTaskTypes; + } + + @Override + public Set getHandledCeTaskTypes() { + return ImmutableSet.copyOf(ceTaskTypes); + } + + @Override + public void process(CeTask task) { + throw new UnsupportedOperationException("Process is not implemented"); + } + } + + private static class SomeProcessor1 extends HandleTypeOnlyTaskProcessor { + public SomeProcessor1(String... ceTaskTypes) { + super(ceTaskTypes); + } + } + + private static class SomeProcessor2 extends HandleTypeOnlyTaskProcessor { + public SomeProcessor2(String... ceTaskTypes) { + super(ceTaskTypes); + } + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/taskprocessor/CeTaskProcessorRepositoryRule.java b/server/sonar-server/src/test/java/org/sonar/server/computation/taskprocessor/CeTaskProcessorRepositoryRule.java new file mode 100644 index 00000000000..02932ed07b2 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/taskprocessor/CeTaskProcessorRepositoryRule.java @@ -0,0 +1,77 @@ +/* + * 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.taskprocessor; + +import com.google.common.base.Optional; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import org.junit.rules.ExternalResource; +import org.sonar.server.computation.queue.CeTask; + +import static com.google.common.base.Preconditions.checkState; +import static java.util.Objects.requireNonNull; + +/** + * A {@link org.junit.Rule} that implements the {@link CeTaskProcessorRepository} interface and + * requires consumer to explicitly define if a specific Task type has an associated {@link CeTaskProcessor} or not. + */ +public class CeTaskProcessorRepositoryRule extends ExternalResource implements CeTaskProcessorRepository { + + private final Map index = new HashMap<>(); + + @Override + protected void after() { + index.clear(); + } + + public CeTaskProcessorRepositoryRule setNoProcessorForTask(String taskType) { + index.put(requireNonNull(taskType), NoCeTaskProcessor.INSTANCE); + return this; + } + + public CeTaskProcessorRepositoryRule setProcessorForTask(String taskType, CeTaskProcessor taskProcessor) { + index.put(requireNonNull(taskType), requireNonNull(taskProcessor)); + return this; + } + + @Override + public Optional getForCeTask(CeTask ceTask) { + CeTaskProcessor taskProcessor = index.get(ceTask.getType()); + checkState(taskProcessor != null, "CeTaskProcessor was not set in rule for task %s", ceTask); + return taskProcessor instanceof NoCeTaskProcessor ? Optional.absent() : Optional.of(taskProcessor); + } + + private enum NoCeTaskProcessor implements CeTaskProcessor { + INSTANCE; + + private static final String UOE_MESSAGE = "NoCeTaskProcessor does not implement any method since it not supposed to be ever used"; + + @Override + public Set getHandledCeTaskTypes() { + throw new UnsupportedOperationException(UOE_MESSAGE); + } + + @Override + public void process(CeTask task) { + throw new UnsupportedOperationException(UOE_MESSAGE); + } + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/taskprocessor/CeWorkerRunnableImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/taskprocessor/CeWorkerRunnableImplTest.java new file mode 100644 index 00000000000..a95d8365421 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/taskprocessor/CeWorkerRunnableImplTest.java @@ -0,0 +1,101 @@ +/* + * 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.taskprocessor; + +import com.google.common.base.Optional; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.InOrder; +import org.mockito.Mockito; +import org.sonar.db.ce.CeActivityDto; +import org.sonar.db.ce.CeTaskTypes; +import org.sonar.server.computation.log.CeLogging; +import org.sonar.server.computation.queue.CeQueue; +import org.sonar.server.computation.queue.CeQueueImpl; +import org.sonar.server.computation.queue.CeTask; +import org.sonar.server.computation.taskprocessor.report.ReportTaskProcessor; + +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; + +public class CeWorkerRunnableImplTest { + + @Rule + public CeTaskProcessorRepositoryRule taskProcessorRepository = new CeTaskProcessorRepositoryRule(); + + CeQueue queue = mock(CeQueueImpl.class); + ReportTaskProcessor taskProcessor = mock(ReportTaskProcessor.class); + CeLogging ceLogging = mock(CeLogging.class); + CeWorkerRunnable underTest = new CeWorkerRunnableImpl(queue, ceLogging, taskProcessorRepository); + InOrder inOrder = Mockito.inOrder(ceLogging, taskProcessor, queue); + + @Test + public void no_pending_tasks_in_queue() throws Exception { + when(queue.peek()).thenReturn(Optional.absent()); + + underTest.run(); + + verifyZeroInteractions(taskProcessor, ceLogging); + } + + @Test + public void fail_when_no_CeTaskProcessor_is_found_in_repository() { + CeTask task = new CeTask.Builder().setUuid("TASK_1").setType(CeTaskTypes.REPORT).setComponentUuid("PROJECT_1").setSubmitterLogin(null).build(); + taskProcessorRepository.setNoProcessorForTask(CeTaskTypes.REPORT); + when(queue.peek()).thenReturn(Optional.of(task)); + + underTest.run(); + + inOrder.verify(ceLogging).initForTask(task); + inOrder.verify(queue).remove(task, CeActivityDto.Status.FAILED); + inOrder.verify(ceLogging).clearForTask(); + } + + @Test + public void peek_and_process_task() throws Exception { + CeTask task = new CeTask.Builder().setUuid("TASK_1").setType(CeTaskTypes.REPORT).setComponentUuid("PROJECT_1").setSubmitterLogin(null).build(); + taskProcessorRepository.setProcessorForTask(task.getType(), taskProcessor); + when(queue.peek()).thenReturn(Optional.of(task)); + + underTest.run(); + + inOrder.verify(ceLogging).initForTask(task); + inOrder.verify(taskProcessor).process(task); + inOrder.verify(queue).remove(task, CeActivityDto.Status.SUCCESS); + inOrder.verify(ceLogging).clearForTask(); + } + + @Test + public void fail_to_process_task() throws Exception { + CeTask task = new CeTask.Builder().setUuid("TASK_1").setType(CeTaskTypes.REPORT).setComponentUuid("PROJECT_1").setSubmitterLogin(null).build(); + when(queue.peek()).thenReturn(Optional.of(task)); + taskProcessorRepository.setProcessorForTask(task.getType(), taskProcessor); + doThrow(new IllegalStateException("simulate exception thrown by TaskProcessor#process")).when(taskProcessor).process(task); + + underTest.run(); + + inOrder.verify(ceLogging).initForTask(task); + inOrder.verify(taskProcessor).process(task); + inOrder.verify(queue).remove(task, CeActivityDto.Status.FAILED); + inOrder.verify(ceLogging).clearForTask(); + } +}