Intégration de l'utilitaire "Database Manager" qui permet de gérer la base de donnée.

L'application vérifie maintenant la version de la base de donnée avant de démarrer, et peut la mettre à jour automatiquement.
This commit is contained in:
FyloZ 2021-03-06 17:27:10 -05:00
parent 4e74d51bc6
commit 96eb029a25
8 changed files with 150 additions and 15 deletions

2
.gitignore vendored
View File

@ -8,7 +8,7 @@
gradle/
build/
logs/
workdir/
data/
dokka/
dist/

View File

@ -30,7 +30,7 @@ dependencies {
implementation("org.apache.pdfbox:pdfbox:2.0.4")
implementation("com.atlassian.commonmark:commonmark:0.13.1")
implementation("commons-io:commons-io:2.6")
implementation("dev.fyloz.colorrecipesexplorer:database-manager:1.0")
implementation("dev.fyloz.colorrecipesexplorer:database-manager:1.0.1")
implementation("org.springframework.boot:spring-boot-starter-data-jpa:2.3.4.RELEASE")
implementation("org.springframework.boot:spring-boot-starter-jdbc:2.3.4.RELEASE")

View File

@ -2,15 +2,20 @@ package dev.fyloz.trial.colorrecipesexplorer
import dev.fyloz.trial.colorrecipesexplorer.config.properties.CREProperties
import dev.fyloz.trial.colorrecipesexplorer.config.properties.MaterialTypeProperties
import org.slf4j.Logger
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.boot.jdbc.DataSourceBuilder
import org.springframework.boot.runApplication
import org.springframework.context.annotation.Bean
import javax.sql.DataSource
@SpringBootApplication(exclude = [LiquibaseAutoConfiguration::class])
@EnableConfigurationProperties(MaterialTypeProperties::class, CREProperties::class)
@EnableConfigurationProperties(MaterialTypeProperties::class, CREProperties::class, DatabaseUpdaterProperties::class)
class ColorRecipesExplorerApplication
fun main(args: Array<String>) {
runApplication<ColorRecipesExplorerApplication>(*args)
runApplication<ColorRecipesExplorerApplication>()
}

View File

@ -0,0 +1,126 @@
package dev.fyloz.trial.colorrecipesexplorer
import dev.fyloz.colorrecipesexplorer.databasemanager.CreDatabase
import dev.fyloz.colorrecipesexplorer.databasemanager.databaseContext
import dev.fyloz.colorrecipesexplorer.databasemanager.databaseUpdaterProperties
import org.slf4j.Logger
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.jdbc.DataSourceBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.core.env.Environment
import javax.sql.DataSource
const val SUPPORTED_DATABASE_VERSION = 2
const val ENV_VAR_ENABLE_DATABASE_UPDATE_NAME = "CRE_ENABLE_DB_UPDATE"
val DATABASE_NAME_REGEX = Regex("(\\w+)$")
@Configuration
class DataSourceConfiguration {
@Bean(name = ["dataSource"])
@ConfigurationProperties(prefix = "spring.datasource")
fun customDataSource(
logger: Logger,
environment: Environment,
databaseUpdaterProperties: DatabaseUpdaterProperties
): DataSource {
val databaseUrl: String = environment.getProperty("spring.datasource.url")!!
runDatabaseVersionCheck(logger, databaseUrl, databaseUpdaterProperties)
return DataSourceBuilder
.create()
.url(databaseUrl) // Hikari won't start without that
.build()
}
}
/**
* Runs a database version check. If the database's version is not supported and the environment variable 'CRE_ENABLE_DB_UPDATE' is:
* - 1: The database will be updated.
* - Any other value: The application will not start.
*/
fun runDatabaseVersionCheck(logger: Logger, databaseUrl: String, databaseUpdaterProperties: DatabaseUpdaterProperties) {
logger.info("Verifying database's version before starting...")
if (":h2:" in databaseUrl) {
logger.warn("H2 is not supported by the database manager")
return
}
val databaseUpdateEnabled = System.getenv(ENV_VAR_ENABLE_DATABASE_UPDATE_NAME) == "1"
val database = getDatabase(databaseUrl, databaseUpdaterProperties, logger)
val version = database.version
if (version != SUPPORTED_DATABASE_VERSION) {
if (!databaseUpdateEnabled) {
database.close()
throwUnsupportedDatabaseVersion(version, logger)
} else runDatabaseUpdate(logger, database)
} else {
logger.info("The database is up to date!")
if (databaseUpdateEnabled) {
logger.warn("The database is up to date but the environment variable '$ENV_VAR_ENABLE_DATABASE_UPDATE_NAME' is set to '1'. Set it to '0' to prevent any possible data loss.")
}
}
database.close()
}
/** Updates the given [database]. */
fun runDatabaseUpdate(logger: Logger, database: CreDatabase) {
logger.info("The environment variable '$ENV_VAR_ENABLE_DATABASE_UPDATE_NAME' is set to '1'; The database will be updated.")
database.update()
}
fun getDatabase(
databaseUrl: String,
databaseUpdaterProperties: DatabaseUpdaterProperties,
logger: Logger
): CreDatabase {
val databaseName =
(DATABASE_NAME_REGEX.find(databaseUrl) ?: throw DatabaseVersioningException.InvalidUrl(databaseUrl)).value
return CreDatabase(
databaseContext(
properties = databaseUpdaterProperties(
targetVersion = SUPPORTED_DATABASE_VERSION,
url = databaseUrl.removeSuffix(databaseName),
dbName = databaseName,
username = databaseUpdaterProperties.username,
password = databaseUpdaterProperties.password
),
logger
)
)
}
fun throwUnsupportedDatabaseVersion(version: Int, logger: Logger) {
if (version > SUPPORTED_DATABASE_VERSION) {
logger.error("Version $version of the database is not supported; Only version $SUPPORTED_DATABASE_VERSION is currently supported; Update this application to use the database.")
} else {
logger.error(
"""Version $version of the database is not supported; Only version $SUPPORTED_DATABASE_VERSION is currently supported.
|You can update the database to the supported version by either:
| - Setting the environment variable '$ENV_VAR_ENABLE_DATABASE_UPDATE_NAME' to '1' to update the database automatically
| - Updating the database manually with the database manager utility (https://git.fyloz.dev/color-recipes-explorer/database-manager)
|
|Don't forget to backup the database before upgrading to prevent any data loss.
""".trimMargin()
)
}
throw DatabaseVersioningException.UnsupportedDatabaseVersion(version)
}
@ConfigurationProperties(prefix = "database-updater")
class DatabaseUpdaterProperties {
var username: String = ""
var password: String = ""
}
sealed class DatabaseVersioningException(message: String) : Exception(message) {
class InvalidUrl(url: String) : DatabaseVersioningException("Invalid database url: $url")
class UnsupportedDatabaseVersion(version: Int) :
DatabaseVersioningException("Unsupported database version: $version; Only version $SUPPORTED_DATABASE_VERSION is currently supported")
}

View File

@ -1,7 +1,6 @@
spring.datasource.url=jdbc:h2:mem:cre
#spring.datasource.url=jdbc:h2:file:./workdir/recipes
spring.datasource.username=sa
spring.datasource.password=LWK4Y7TvEbNyhu1yCoG3
spring.datasource.password=password
spring.jpa.hibernate.ddl-auto=update
spring.h2.console.path=/dbconsole
spring.h2.console.enabled=true

View File

@ -1,4 +1,4 @@
spring.datasource.url=jdbc:mysql://172.20.0.2/cre
spring.datasource.url=jdbc:mysql://172.66.1.1/cre
spring.datasource.username=root
spring.datasource.password=pass
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

View File

@ -1,7 +1,7 @@
# PORT
server.port=9090
# CRE
cre.server.upload-directory=./workdir
cre.server.upload-directory=data
cre.server.password-file=passwords.txt
cre.server.url-use-port=true
cre.server.url-use-https=false
@ -10,10 +10,8 @@ cre.security.jwt-duration=18000000
# Root user
cre.security.root.id=9999
cre.security.root.password=password
# Common user
#cre.security.common.id=9998
#cre.security.common.password=common
# TYPES DE PRODUIT PAR DÉFAUT
# Default material types
entities.material-types.systemTypes[0].name=Aucun
entities.material-types.systemTypes[0].prefix=
entities.material-types.systemTypes[0].usepercentages=false
@ -21,9 +19,14 @@ entities.material-types.systemTypes[1].name=Base
entities.material-types.systemTypes[1].prefix=BAS
entities.material-types.systemTypes[1].usepercentages=false
entities.material-types.baseName=Base
# Database manager
database-updater.username=root
database-updater.password=pass
# DEBUG
spring.jpa.show-sql=true
# NE PAS MODIFIER
# Do not modify
spring.messages.fallback-to-system-locale=true
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=15MB
@ -31,4 +34,5 @@ spring.jpa.hibernate.ddl-auto=none
spring.jpa.open-in-view=true
server.http2.enabled=true
server.error.whitelabel.enabled=false
spring.h2.console.enabled=false
spring.profiles.active=@spring.profiles.active@

View File

@ -1,10 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<statusListener class="ch.qos.logback.core.status.NopStatusListener"/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>
%black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable
%black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{36}): %msg%n%throwable
</Pattern>
</layout>
</appender>
@ -20,7 +21,7 @@
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>
%d{dd-MM-yyyy HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%M - %msg%n
%d{dd-MM-yyyy HH:mm:ss.SSS} [%thread] %-5level %logger.%M - %msg%n
</Pattern>
</encoder>