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
28
29 public void orchestrateMigrations() {
30 if (MigrationModeToggle.isActive()) {
31 runMigrationsIfNecessary();
32 } else {
33 assertShepardCanRunNormally();
34 }
35 }
36
37
38
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
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 }