View Javadoc
1   package de.dlr.shepard.data.timeseries.migration.services;
2   
3   import de.dlr.shepard.common.configuration.feature.toggles.MigrationModeToggle;
4   import de.dlr.shepard.data.timeseries.migration.model.MigrationState;
5   import io.quarkus.logging.Log;
6   import jakarta.enterprise.context.ApplicationScoped;
7   import jakarta.inject.Inject;
8   import java.util.Optional;
9   import org.eclipse.microprofile.config.inject.ConfigProperty;
10  
11  @ApplicationScoped
12  public class TimeseriesMigrationInitService {
13  
14    @ConfigProperty(name = "influx.host")
15    Optional<String> influxHost;
16  
17    @ConfigProperty(name = "influx.username")
18    Optional<String> influxUsername;
19  
20    @ConfigProperty(name = "influx.password")
21    Optional<String> influxPassword;
22  
23    @Inject
24    TimeseriesMigrationService timeseriesMigrationService;
25  
26    /**
27     * @return true if shepard should terminate
28     */
29    public void orchestrateMigrations() {
30      if (MigrationModeToggle.isActive()) {
31        runMigrationsIfNecessary();
32      } else {
33        assertShepardCanRunNormally();
34      }
35    }
36  
37    /**
38     * @return true if shepard should terminate
39     */
40    private void runMigrationsIfNecessary() {
41      MigrationState migrationState = timeseriesMigrationService.getMigrationState();
42  
43      if (migrationState == MigrationState.NotNeeded) {
44        logThatMigrationModeCanBeDisabled();
45        return;
46      }
47      runMigrations();
48    }
49  
50    /**
51     * @return false if shepard should terminate
52     */
53    private boolean assertShepardCanRunNormally() {
54      MigrationState migrationState = timeseriesMigrationService.getMigrationState();
55      if (migrationState == MigrationState.HasErrors) {
56        logThatMigrationStateHasErrors();
57        return false;
58      }
59      if (migrationState == MigrationState.Needed) {
60        logThatMigrationsNeedToBeRun();
61        return false;
62      }
63  
64      if (isInfluxConfigured()) logThatInfluxIsStillConfigured();
65  
66      return true;
67    }
68  
69    private void runMigrations() {
70      Log.info("Running migration from InfluxDB to TimescaleDB.");
71      timeseriesMigrationService.runMigrations();
72  
73      var totalTasks = timeseriesMigrationService.getMigrationTasks(false);
74      var tasksWithErrors = timeseriesMigrationService.getMigrationTasks(true);
75      int tasksWithErrorsCount = tasksWithErrors.size();
76  
77      if (tasksWithErrorsCount == 0) {
78        Log.info("Migrations successfully completed.");
79      } else {
80        Log.errorf(
81          "%d errors occurred during migration of %d containers. " +
82          "You can retrieve the current migration status at <backend-url>/shepard/api/temp/migrations/state",
83          tasksWithErrorsCount,
84          totalTasks.size()
85        );
86      }
87    }
88  
89    private boolean isInfluxConfigured() {
90      return influxHost.isPresent() || influxUsername.isPresent() || influxPassword.isPresent();
91    }
92  
93    private void logThatMigrationModeCanBeDisabled() {
94      Log.warn(
95        "No migration necessary. Please restart shepard without migration mode. Endpoints are deactivated and cannot be used."
96      );
97    }
98  
99    private void logThatMigrationStateHasErrors() {
100     Log.error(
101       "Migrations ran with errors. " +
102       "You can retrieve the current migration status in migration mode at \"<backend-url>/shepard/api/temp/migrations/state\". " +
103       "Please try again after cleaning your TimescaleDB instance and activate the migration mode if it is not active yet."
104     );
105   }
106 
107   private void logThatMigrationsNeedToBeRun() {
108     Log.error(
109       "Can't start the instance without first migrating InfluxDB Data. Enable migration mode to start the migration."
110     );
111   }
112 
113   private void logThatInfluxIsStillConfigured() {
114     Log.warn(
115       "InfluxDB connection is configured but shepard does not support InfluxDB anymore. Feel free to remove the InfluxDB configuration properties."
116     );
117   }
118 }