3 * Copyright (C) 2009-2024 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.server.platform.db.migration.step;
22 import java.util.List;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25 import org.sonar.core.platform.Container;
26 import org.sonar.core.util.logs.Profiler;
27 import org.sonar.server.platform.db.migration.MutableDatabaseMigrationState;
28 import org.sonar.server.platform.db.migration.history.MigrationHistory;
29 import org.sonar.server.telemetry.TelemetryDbMigrationSuccessProvider;
30 import org.sonar.server.telemetry.TelemetryDbMigrationStepsProvider;
31 import org.sonar.server.telemetry.TelemetryDbMigrationTotalTimeProvider;
33 import static com.google.common.base.Preconditions.checkState;
35 public class MigrationStepsExecutorImpl implements MigrationStepsExecutor {
36 private static final Logger LOGGER = LoggerFactory.getLogger("DbMigrations");
37 private static final String GLOBAL_START_MESSAGE = "Executing {} DB migrations...";
38 private static final String GLOBAL_END_MESSAGE = "Executed {}/{} DB migrations: {}";
39 private static final String STEP_START_PATTERN = "{}/{} {}...";
40 private static final String STEP_STOP_PATTERN = "{}/{} {}: {}";
42 private final Container migrationContainer;
43 private final MigrationHistory migrationHistory;
44 private final MutableDatabaseMigrationState databaseMigrationState;
45 private final TelemetryDbMigrationTotalTimeProvider telemetryDbMigrationTotalTimeProvider;
46 private final TelemetryDbMigrationStepsProvider telemetryDbMigrationStepsProvider;
47 private final TelemetryDbMigrationSuccessProvider telemetryDbMigrationSuccessProvider;
49 public MigrationStepsExecutorImpl(Container migrationContainer, MigrationHistory migrationHistory, MutableDatabaseMigrationState databaseMigrationState,
50 TelemetryDbMigrationTotalTimeProvider telemetryDbMigrationTotalTimeProvider, TelemetryDbMigrationStepsProvider telemetryDbMigrationStepsProvider,
51 TelemetryDbMigrationSuccessProvider telemetryDbMigrationSuccessProvider) {
52 this.migrationContainer = migrationContainer;
53 this.migrationHistory = migrationHistory;
54 this.databaseMigrationState = databaseMigrationState;
55 this.telemetryDbMigrationTotalTimeProvider = telemetryDbMigrationTotalTimeProvider;
56 this.telemetryDbMigrationStepsProvider = telemetryDbMigrationStepsProvider;
57 this.telemetryDbMigrationSuccessProvider = telemetryDbMigrationSuccessProvider;
61 public void execute(List<RegisteredMigrationStep> steps, MigrationStatusListener listener) {
62 Profiler globalProfiler = Profiler.create(LOGGER);
63 globalProfiler.startInfo(GLOBAL_START_MESSAGE, databaseMigrationState.getTotalMigrations());
64 boolean allStepsExecuted = false;
66 for (RegisteredMigrationStep step : steps) {
68 listener.onMigrationStepCompleted();
70 allStepsExecuted = true;
72 long dbMigrationDuration = 0L;
73 if (allStepsExecuted) {
74 dbMigrationDuration = globalProfiler.stopInfo(GLOBAL_END_MESSAGE,
75 databaseMigrationState.getCompletedMigrations(),
76 databaseMigrationState.getTotalMigrations(),
79 dbMigrationDuration = globalProfiler.stopError(GLOBAL_END_MESSAGE,
80 databaseMigrationState.getCompletedMigrations(),
81 databaseMigrationState.getTotalMigrations(),
84 telemetryDbMigrationTotalTimeProvider.setDbMigrationTotalTime(dbMigrationDuration);
85 telemetryDbMigrationStepsProvider.setDbMigrationCompletedSteps(databaseMigrationState.getCompletedMigrations());
86 telemetryDbMigrationSuccessProvider.setDbMigrationSuccess(allStepsExecuted);
90 private void execute(RegisteredMigrationStep step) {
91 MigrationStep migrationStep = migrationContainer.getComponentByType(step.getStepClass());
92 checkState(migrationStep != null, "Can not find instance of " + step.getStepClass());
94 execute(step, migrationStep);
97 private void execute(RegisteredMigrationStep step, MigrationStep migrationStep) {
98 Profiler stepProfiler = Profiler.create(LOGGER);
99 stepProfiler.startInfo(STEP_START_PATTERN,
100 databaseMigrationState.getCompletedMigrations() + 1,
101 databaseMigrationState.getTotalMigrations(),
103 boolean done = false;
105 migrationStep.execute();
106 migrationHistory.done(step);
108 } catch (Exception e) {
109 throw new MigrationStepExecutionException(step, e);
112 stepProfiler.stopInfo(STEP_STOP_PATTERN,
113 databaseMigrationState.getCompletedMigrations() + 1,
114 databaseMigrationState.getTotalMigrations(),
118 stepProfiler.stopError(STEP_STOP_PATTERN,
119 databaseMigrationState.getCompletedMigrations() + 1,
120 databaseMigrationState.getTotalMigrations(),