View Javadoc
1   package de.dlr.shepard.common.neo4j;
2   
3   import ac.simons.neo4j.migrations.core.Migrations;
4   import ac.simons.neo4j.migrations.core.MigrationsConfig;
5   import ac.simons.neo4j.migrations.core.MigrationsConfig.VersionSortOrder;
6   import ac.simons.neo4j.migrations.core.MigrationsException;
7   import io.quarkus.logging.Log;
8   import jakarta.annotation.Nullable;
9   import java.nio.file.Paths;
10  import org.eclipse.microprofile.config.ConfigProvider;
11  import org.neo4j.driver.AuthTokens;
12  import org.neo4j.driver.Driver;
13  import org.neo4j.driver.GraphDatabase;
14  import org.neo4j.driver.exceptions.ServiceUnavailableException;
15  
16  public class MigrationsRunner {
17  
18    private final Migrations migrations;
19    private final Driver driver;
20  
21    public MigrationsRunner() {
22      this(null);
23    }
24  
25    public MigrationsRunner(@Nullable String targetVersion) {
26      String username = ConfigProvider.getConfig().getValue("neo4j.username", String.class);
27      String password = ConfigProvider.getConfig().getValue("neo4j.password", String.class);
28      String host = "neo4j://" + ConfigProvider.getConfig().getValue("neo4j.host", String.class);
29      driver = GraphDatabase.driver(host, AuthTokens.basic(username, password));
30  
31      // This is a workaround to make all migrations available in a dockerized quarkus jar.
32      // See https://gitlab.com/dlr-shepard/shepard/-/issues/146 for more information
33      var localPath = this.getClass().getClassLoader().getResource("neo4j/migrations").toString();
34      var dockerPath = Paths.get("/deployments/neo4j/migrations").toAbsolutePath().toString();
35      var isDocker = localPath.startsWith("jar");
36      var locationsToScan = isDocker ? dockerPath : localPath;
37  
38      var config = MigrationsConfig.builder()
39        .withTransactionMode(MigrationsConfig.TransactionMode.PER_STATEMENT)
40        .withPackagesToScan("de.dlr.shepard.common.neo4j.migrations")
41        .withLocationsToScan("file://" + locationsToScan)
42        .withVersionSortOrder(VersionSortOrder.SEMANTIC)
43        .withTarget(targetVersion)
44        .build();
45  
46      migrations = new Migrations(config, driver);
47    }
48  
49    public void waitForConnection() {
50      while (true) {
51        try {
52          driver.verifyConnectivity();
53          break;
54        } catch (Exception e) {
55          Log.warn("Cannot connect to neo4j database. Retrying...");
56        }
57        try {
58          Thread.sleep(1000);
59        } catch (InterruptedException e) {
60          Log.error("Cannot sleep while waiting for neo4j Connection");
61          Thread.currentThread().interrupt();
62        }
63      }
64    }
65  
66    public void apply() {
67      try {
68        migrations.apply();
69      } catch (ServiceUnavailableException e) {
70        Log.error("Migrations cannot be executed because the neo4j database is not available");
71      } catch (MigrationsException e) {
72        Log.error("An error occurred during the execution of the migrations: ", e);
73      }
74    }
75  }