diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 9580dea8..4851aa7b 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -9,12 +9,12 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 0 - name: Gradle Wrapper Verification - uses: gradle/wrapper-validation-action@55e685c48d84285a5b0418cd094606e199cca3b6 # v1.0.5 + uses: gradle/wrapper-validation-action@55e685c48d84285a5b0418cd094606e199cca3b6 # v4.1.0 - name: Set up env env: @@ -40,13 +40,13 @@ jobs: echo "GIT_HASH_TAG=$IMAGE_BASE:$GIT_HASH_SHORT" >> "$GITHUB_ENV" - name: Login to Docker Hub - uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a # v2.1.0 + uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Setup JDK - uses: actions/setup-java@1df8dbefe2a8cbc99770194893dd902763bee34b # v3.9.0 + uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b # v4.5.0 with: distribution: "temurin" java-version: 21 @@ -56,12 +56,12 @@ jobs: run: java -Xmx32m --version - name: Gradle Assemble - uses: burrunan/gradle-cache-action@f9ec73cf67dd8ed9a057978212c988945b2f0405 # v1.15 + uses: burrunan/gradle-cache-action@c15634bb25b7284dc084f38dff4e838048b7feaf # v1.22 with: arguments: assemble --info -Pprod - name: Sonar - uses: burrunan/gradle-cache-action@f9ec73cf67dd8ed9a057978212c988945b2f0405 # v1.15 + uses: burrunan/gradle-cache-action@c15634bb25b7284dc084f38dff4e838048b7feaf # v1.22 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} @@ -69,7 +69,7 @@ jobs: arguments: check sonar -Dsonar.host.url=https://sonarcloud.io -Dsonar.organization=wolfiabot -Dsonar.login=${{ env.SONAR_TOKEN }} - name: Gradle BootJar - uses: burrunan/gradle-cache-action@f9ec73cf67dd8ed9a057978212c988945b2f0405 # v1.15 + uses: burrunan/gradle-cache-action@c15634bb25b7284dc084f38dff4e838048b7feaf # v1.22 with: arguments: bootJar --info -Pprod diff --git a/DEVELOPING.md b/DEVELOPING.md index 3a9fe71e..ae950d97 100644 --- a/DEVELOPING.md +++ b/DEVELOPING.md @@ -41,7 +41,7 @@ development. #### PostgreSQL This project uses the [PostgreSQL](https://www.postgresql.org/) relational database to store and query important data. -The currently used version can be found in the [databases' Dockerfile](docker/database/Dockerfile). +The currently used version can be found in the [poggres repo](https://github.com/CapybaraLabs/poggres). Installing it is optional, running the development `docker-compose` is recommended instead: ```shell script docker-compose -f docker/dev/docker-compose.yaml up -d @@ -94,11 +94,11 @@ We also use the [Bulma](https://bulma.io/) CSS framework, together with a [Bulma ##### PostgreSQL [PostgreSQL](https://www.postgresql.org/) is the main database. -We deploy a customized [Docker image](docker/database/Dockerfile) that contains init scripts to set up required database +We deploy a customized [Docker image](https://github.com/CapybaraLabs/poggres) that contains init scripts to set up required database extensions as well as backup scripts to back up the data to [Backblaze B2](https://www.backblaze.com/b2). ##### Flyway & jOOQ -[Database schema migrations](src/main/resources/db/migrations) are handled by [Flyway](https://flywaydb.org/). +[Database schema migrations](src/main/resources/db/migration) are handled by [Flyway](https://flywaydb.org/). [jOOQ](https://www.jooq.org/) is used for database querying. diff --git a/build.gradle b/build.gradle index 2485342f..7296a00d 100644 --- a/build.gradle +++ b/build.gradle @@ -31,6 +31,7 @@ buildscript { dependencies { classpath "org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion" classpath "gradle.plugin.org.flywaydb:gradle-plugin-publishing:$flywayVersion" + classpath "org.flywaydb:flyway-database-postgresql:$flywayVersion" classpath "gradle.plugin.com.gorylenko.gradle-git-properties:gradle-git-properties:$gradleGitVersion" classpath "org.ajoberstar.grgit:grgit-gradle:$grGitVersion" @@ -192,7 +193,6 @@ allprojects { dependencies { globalPlatforms platform("org.springframework.boot:spring-boot-dependencies:$springBootVersion") - globalPlatforms platform("io.prometheus:simpleclient_bom:$prometheusVersion") globalPlatforms platform("io.sentry:sentry-bom:$sentryVersion") } } @@ -286,16 +286,16 @@ dependencies { implementation(group: "io.netty", name: "netty-transport-native-epoll", classifier: "linux-x86_64") implementation(group: "io.netty", name: "netty-transport-native-kqueue", classifier: "osx-x86_64") - implementation "io.prometheus:simpleclient" - implementation "io.prometheus:simpleclient_hotspot" - implementation "io.prometheus:simpleclient_logback" - implementation "io.prometheus:simpleclient_common" - implementation "io.prometheus:simpleclient_caffeine" - implementation "space.npstr:prometheus_extensions:$promExtVersion" + // not part of v1.3.2 BOM for some reason + implementation "io.prometheus:prometheus-metrics-instrumentation-caffeine:$prometheusClientVersion" + implementation "io.prometheus:prometheus-metrics-instrumentation-jvm" + implementation "space.npstr:prometheus_extensions:$prometheusExtensionsVersion" + implementation "io.micrometer:micrometer-registry-prometheus" implementation "org.postgresql:postgresql" implementation "com.zaxxer:HikariCP" implementation "org.flywaydb:flyway-core:$flywayVersion" + implementation "org.flywaydb:flyway-database-postgresql:$flywayVersion" implementation "net.ttddyy:datasource-proxy:$dsProxyVersion" implementation "org.jooq:jooq:$jooqVersion" @@ -314,9 +314,11 @@ dependencies { implementation "org.springframework.boot:spring-boot-starter-web" implementation "org.springframework.boot:spring-boot-starter-undertow" + implementation "org.springframework.boot:spring-boot-starter-jdbc" implementation "org.springframework.boot:spring-boot-starter-security" implementation "org.springframework.boot:spring-boot-starter-data-jpa" implementation "org.springframework.boot:spring-boot-starter-oauth2-client" + implementation "org.springframework.boot:spring-boot-starter-actuator" implementation "org.springframework.session:spring-session-data-redis" implementation "org.jetbrains.kotlin:kotlin-reflect" implementation "com.fasterxml.jackson.module:jackson-module-kotlin" @@ -440,7 +442,7 @@ class StopCodegenDbContainer extends DockerStopContainer { } } -def migrationsInput = fileTree('src/main/resources/db/migrations') +def migrationsInput = fileTree('src/main/resources/db/migration') def migrationsOutput = fileTree('build/classes/generated/java/space/npstr/wolfia/db/gen') flyway { @@ -464,7 +466,7 @@ flyway { } url = "$codegenJdbcUrl" - locations = ['filesystem:src/main/resources/db/migrations'] + locations = ['filesystem:src/main/resources/db/migration'] configurations = ['flywayMigration'] } diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 9a1f5e9d..8a23b585 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -3,4 +3,7 @@ repositories { } dependencies { implementation "com.bmuschko:gradle-docker-plugin:$dockerPluginVersion" + + // https://stackoverflow.com/questions/78638699/bootjar-task-fails-with-gradle-8-5-and-spring-boot-3-3-0-caused-by-spring-boot + implementation("org.apache.commons:commons-compress:$apacheCompressVersion") } diff --git a/buildscript-gradle.lockfile b/buildscript-gradle.lockfile index 2f3d0bee..7c1fc0b1 100644 --- a/buildscript-gradle.lockfile +++ b/buildscript-gradle.lockfile @@ -7,6 +7,7 @@ com.fasterxml.jackson.core:jackson-annotations:2.15.2=classpath com.fasterxml.jackson.core:jackson-core:2.15.2=classpath com.fasterxml.jackson.core:jackson-databind:2.15.2=classpath com.fasterxml.jackson.dataformat:jackson-dataformat-toml:2.15.2=classpath +com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2=classpath com.fasterxml.jackson.module:jackson-module-parameter-names:2.15.2=classpath com.fasterxml.jackson:jackson-bom:2.15.2=classpath com.github.ben-manes:gradle-versions-plugin:0.51.0=classpath @@ -15,7 +16,6 @@ com.github.docker-java:docker-java-core:3.2.13=classpath com.github.docker-java:docker-java-transport-httpclient5:3.2.13=classpath com.github.docker-java:docker-java-transport:3.2.13=classpath com.google.code.findbugs:jsr305:3.0.2=classpath -com.google.code.gson:gson:2.10.1=classpath com.google.guava:guava:19.0=classpath com.googlecode.javaewah:JavaEWAH:1.2.3=classpath com.squareup.moshi:moshi-kotlin:1.12.0=classpath @@ -28,7 +28,7 @@ com.sun.istack:istack-commons-runtime:4.0.1=classpath commons-codec:commons-codec:1.17.0=classpath commons-io:commons-io:2.6=classpath gradle.plugin.com.gorylenko.gradle-git-properties:gradle-git-properties:2.2.4=classpath -gradle.plugin.org.flywaydb:gradle-plugin-publishing:9.22.3=classpath +gradle.plugin.org.flywaydb:gradle-plugin-publishing:10.21.0=classpath io.r2dbc:r2dbc-spi:1.0.0.RELEASE=classpath io.spring.gradle:dependency-management-plugin:1.1.6=classpath jakarta.activation:jakarta.activation-api:2.1.0=classpath @@ -40,16 +40,17 @@ nu.studer:gradle-jooq-plugin:9.0=classpath org.ajoberstar.grgit:grgit-core:5.3.0=classpath org.ajoberstar.grgit:grgit-gradle:5.3.0=classpath org.antlr:antlr4-runtime:4.7.2=classpath -org.apache.commons:commons-compress:1.21=classpath +org.apache.commons:commons-compress:1.25.0=classpath org.apache.commons:commons-lang3:3.12.0=classpath -org.apache.httpcomponents.client5:httpclient5:5.2.3=classpath +org.apache.httpcomponents.client5:httpclient5:5.3.1=classpath org.apache.httpcomponents.core5:httpcore5-h2:5.2.4=classpath org.apache.httpcomponents.core5:httpcore5:5.2.4=classpath org.bouncycastle:bcpkix-jdk15on:1.64=classpath org.bouncycastle:bcprov-jdk15on:1.64=classpath org.codehaus.groovy:groovy:3.0.22=classpath org.eclipse.jgit:org.eclipse.jgit:6.10.0.202406032230-r=classpath -org.flywaydb:flyway-core:9.22.3=classpath +org.flywaydb:flyway-core:10.21.0=classpath +org.flywaydb:flyway-database-postgresql:10.21.0=classpath org.fusesource.jansi:jansi:2.4.0=classpath org.glassfish.jaxb:jaxb-core:3.0.2=classpath org.glassfish.jaxb:jaxb-runtime:3.0.2=classpath @@ -95,9 +96,9 @@ org.siouan:frontend-gradle-plugin-jdk11:6.0.0=classpath org.slf4j:slf4j-api:1.7.36=classpath org.sonarsource.scanner.api:sonar-scanner-api:2.16.2.588=classpath org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:5.1.0.4882=classpath -org.springframework.boot:spring-boot-buildpack-platform:3.2.11=classpath -org.springframework.boot:spring-boot-gradle-plugin:3.2.11=classpath -org.springframework.boot:spring-boot-loader-tools:3.2.11=classpath +org.springframework.boot:spring-boot-buildpack-platform:3.3.5=classpath +org.springframework.boot:spring-boot-gradle-plugin:3.3.5=classpath +org.springframework.boot:spring-boot-loader-tools:3.3.5=classpath org.springframework:spring-core:6.1.14=classpath org.springframework:spring-jcl:6.1.14=classpath org.tomlj:tomlj:1.0.0=classpath diff --git a/frontend/yarn.lock b/frontend/yarn.lock index bf95a8e3..514fd6ed 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -608,9 +608,9 @@ callsites@^3.0.0: integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== caniuse-lite@^1.0.30001587, caniuse-lite@^1.0.30001599: - version "1.0.30001613" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001613.tgz#dd84a547458df22c4d2435711a8c957ed88332b8" - integrity sha512-BNjJULJfOONQERivfxte7alLfeLW4QnwHvNW4wEcLEbXfV6VSCYvr+REbf2Sojv8tC1THpjPXBxWgDbq4NtLWg== + version "1.0.30001679" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001679.tgz" + integrity sha512-j2YqID/YwpLnKzCmBOS4tlZdWprXm3ZmQLBH9ZBXFOhoxLA46fwyBvx6toCBWBmnuwUY/qB3kEU6gFx8qgCroA== chalk@^4.0.0: version "4.1.2" diff --git a/gradle.lockfile b/gradle.lockfile index 3ab48b44..ff17536a 100644 --- a/gradle.lockfile +++ b/gradle.lockfile @@ -1,33 +1,24 @@ # This is a Gradle generated file for dependency locking. # Manual edits can break the build and are not advised. # This file is expected to be part of source control. -ch.qos.logback:logback-classic:1.5.6=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -ch.qos.logback:logback-core:1.5.6=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +ch.qos.logback:logback-classic:1.5.11=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +ch.qos.logback:logback-core:1.5.11=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath club.minnced:discord-webhooks:0.8.4=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath club.minnced:opus-java-api:1.1.1=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath club.minnced:opus-java-natives:1.1.1=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath club.minnced:opus-java:1.1.1=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath com.codeborne:selenide-core:7.5.1=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath com.codeborne:selenide:7.5.1=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-annotations:2.15.4=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-annotations:2.17.2=productionRuntimeClasspath,testImplementationDependenciesMetadata -com.fasterxml.jackson.core:jackson-core:2.15.4=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-core:2.17.2=productionRuntimeClasspath,testImplementationDependenciesMetadata -com.fasterxml.jackson.core:jackson-databind:2.15.4=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-databind:2.17.2=productionRuntimeClasspath,testImplementationDependenciesMetadata -com.fasterxml.jackson.dataformat:jackson-dataformat-toml:2.15.4=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson.dataformat:jackson-dataformat-toml:2.17.2=productionRuntimeClasspath,testImplementationDependenciesMetadata -com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.15.4=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.17.2=productionRuntimeClasspath,testImplementationDependenciesMetadata -com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.4=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.2=productionRuntimeClasspath,testImplementationDependenciesMetadata -com.fasterxml.jackson.module:jackson-module-kotlin:2.15.4=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson.module:jackson-module-kotlin:2.17.2=productionRuntimeClasspath,testImplementationDependenciesMetadata -com.fasterxml.jackson.module:jackson-module-parameter-names:2.15.4=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson.module:jackson-module-parameter-names:2.17.2=productionRuntimeClasspath,testImplementationDependenciesMetadata -com.fasterxml.jackson:jackson-bom:2.15.4=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson:jackson-bom:2.17.2=productionRuntimeClasspath,testImplementationDependenciesMetadata -com.fasterxml:classmate:1.6.0=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-annotations:2.17.2=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-core:2.17.2=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-databind:2.17.2=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +com.fasterxml.jackson.dataformat:jackson-dataformat-toml:2.17.2=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.17.2=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.2=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +com.fasterxml.jackson.module:jackson-module-kotlin:2.17.2=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +com.fasterxml.jackson.module:jackson-module-parameter-names:2.17.2=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +com.fasterxml.jackson:jackson-bom:2.17.2=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +com.fasterxml:classmate:1.7.0=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath com.github.ben-manes.caffeine:caffeine:3.1.8=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath com.github.docker-java:docker-java-api:3.3.6=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath com.github.docker-java:docker-java-transport-zerodep:3.3.6=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath @@ -35,7 +26,7 @@ com.github.docker-java:docker-java-transport:3.3.6=testCompileClasspath,testImpl com.github.stephenc.jcip:jcip-annotations:1.0-1=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath com.google.auto.service:auto-service-annotations:1.1.1=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath com.google.code.findbugs:jsr305:3.0.2=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -com.google.code.gson:gson:2.10.1=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +com.google.code.gson:gson:2.10.1=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath com.google.crypto.tink:tink:1.14.1=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath com.google.errorprone:error_prone_annotations:2.21.1=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.errorprone:error_prone_annotations:2.22.0=productionRuntimeClasspath @@ -61,12 +52,15 @@ com.squareup.okio:okio:3.6.0=compileClasspath,implementationDependenciesMetadata com.sun.istack:istack-commons-runtime:4.1.2=jooqGenerator,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath com.sun.xml.bind:jaxb-core:4.0.5=jooqGenerator com.sun.xml.bind:jaxb-impl:4.0.5=jooqGenerator -com.zaxxer:HikariCP:5.0.1=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +com.zaxxer:HikariCP:5.1.0=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath commons-io:commons-io:2.17.0=testRuntimeClasspath dev.failsafe:failsafe:3.3.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath io.lettuce:lettuce-core:6.3.2.RELEASE=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -io.micrometer:micrometer-commons:1.12.11=compileClasspath,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -io.micrometer:micrometer-observation:1.12.11=compileClasspath,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +io.micrometer:micrometer-commons:1.13.6=compileClasspath,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +io.micrometer:micrometer-core:1.13.6=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +io.micrometer:micrometer-jakarta9:1.13.6=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +io.micrometer:micrometer-observation:1.13.6=compileClasspath,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +io.micrometer:micrometer-registry-prometheus:1.13.6=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath io.netty:netty-buffer:4.1.114.Final=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath io.netty:netty-codec:4.1.114.Final=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath io.netty:netty-common:4.1.114.Final=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath @@ -91,15 +85,17 @@ io.opentelemetry:opentelemetry-sdk-metrics:1.42.1=testCompileClasspath,testImple io.opentelemetry:opentelemetry-sdk-trace:1.42.1=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath io.opentelemetry:opentelemetry-sdk:1.42.1=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath io.projectreactor:reactor-core:3.6.11=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -io.prometheus:simpleclient:0.16.0=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -io.prometheus:simpleclient_bom:0.16.0=annotationProcessor,apiDependenciesMetadata,compile,compileClasspath,compileOnlyDependenciesMetadata,developmentOnly,flywayMigration,implementationDependenciesMetadata,intransitiveDependenciesMetadata,jacocoAgent,jacocoAnt,jooqGenerator,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath,kotlinNativeCompilerPluginClasspath,kotlinScriptDef,kotlinScriptDefExtensions,productionRuntimeClasspath,runtimeClasspath,testAndDevelopmentOnly,testAnnotationProcessor,testApiDependenciesMetadata,testCompileClasspath,testCompileOnlyDependenciesMetadata,testImplementationDependenciesMetadata,testIntransitiveDependenciesMetadata,testKotlinScriptDef,testKotlinScriptDefExtensions,testRuntimeClasspath -io.prometheus:simpleclient_caffeine:0.16.0=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -io.prometheus:simpleclient_common:0.16.0=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -io.prometheus:simpleclient_hotspot:0.16.0=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -io.prometheus:simpleclient_logback:0.16.0=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -io.prometheus:simpleclient_tracer_common:0.16.0=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -io.prometheus:simpleclient_tracer_otel:0.16.0=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -io.prometheus:simpleclient_tracer_otel_agent:0.16.0=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +io.prometheus:prometheus-metrics-config:1.3.2=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +io.prometheus:prometheus-metrics-core:1.3.2=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +io.prometheus:prometheus-metrics-exposition-formats:1.2.1=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath +io.prometheus:prometheus-metrics-instrumentation-caffeine:1.3.2=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +io.prometheus:prometheus-metrics-instrumentation-jvm:1.2.1=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +io.prometheus:prometheus-metrics-model:1.3.2=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +io.prometheus:prometheus-metrics-shaded-protobuf:1.2.1=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath +io.prometheus:prometheus-metrics-tracer-common:1.3.2=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +io.prometheus:prometheus-metrics-tracer-initializer:1.3.2=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +io.prometheus:prometheus-metrics-tracer-otel-agent:1.3.2=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +io.prometheus:prometheus-metrics-tracer-otel:1.3.2=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath io.r2dbc:r2dbc-spi:1.0.0.RELEASE=compileClasspath,implementationDependenciesMetadata,jooqGenerator,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath io.sentry:sentry-bom:7.16.0=annotationProcessor,apiDependenciesMetadata,compile,compileClasspath,compileOnlyDependenciesMetadata,developmentOnly,flywayMigration,implementationDependenciesMetadata,intransitiveDependenciesMetadata,jacocoAgent,jacocoAnt,jooqGenerator,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath,kotlinNativeCompilerPluginClasspath,kotlinScriptDef,kotlinScriptDefExtensions,productionRuntimeClasspath,runtimeClasspath,testAndDevelopmentOnly,testAnnotationProcessor,testApiDependenciesMetadata,testCompileClasspath,testCompileOnlyDependenciesMetadata,testImplementationDependenciesMetadata,testIntransitiveDependenciesMetadata,testKotlinScriptDef,testKotlinScriptDefExtensions,testRuntimeClasspath io.sentry:sentry-kotlin-extensions:7.16.0=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath @@ -146,21 +142,23 @@ org.apache.logging.log4j:log4j-to-slf4j:2.23.1=compileClasspath,implementationDe org.apache.tomcat.embed:tomcat-embed-el:10.1.31=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata org.aspectj:aspectjweaver:1.9.22.1=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.assertj:assertj-core:3.24.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.assertj:assertj-core:3.25.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.attoparser:attoparser:2.0.7.RELEASE=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.awaitility:awaitility:4.2.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.checkerframework:checker-qual:3.31.0=flywayMigration,jooqGenerator -org.checkerframework:checker-qual:3.37.0=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +org.checkerframework:checker-qual:3.37.0=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +org.checkerframework:checker-qual:3.42.0=flywayMigration,jooqGenerator,productionRuntimeClasspath org.checkerframework:checker-qual:3.43.0=testImplementationDependenciesMetadata org.eclipse.angus:angus-activation:2.0.2=jooqGenerator,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath -org.flywaydb:flyway-core:9.22.3=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.flywaydb:flyway-core:10.21.0=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.flywaydb:flyway-database-postgresql:10.21.0=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.glassfish.jaxb:jaxb-core:4.0.5=jooqGenerator,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath org.glassfish.jaxb:jaxb-runtime:4.0.5=jooqGenerator,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath org.glassfish.jaxb:txw2:4.0.5=jooqGenerator,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath org.hamcrest:hamcrest-core:2.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.hamcrest:hamcrest:2.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.hdrhistogram:HdrHistogram:2.2.2=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath org.hibernate.common:hibernate-commons-annotations:6.0.6.Final=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath -org.hibernate.orm:hibernate-core:6.4.10.Final=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.hibernate.orm:hibernate-core:6.5.3.Final=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt org.jacoco:org.jacoco.core:0.8.12=jacocoAnt @@ -190,18 +188,18 @@ org.jetbrains.kotlin:kotlin-stdlib-common:1.9.25=compileClasspath,implementation org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.25=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.25=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.jetbrains.kotlin:kotlin-stdlib:1.9.25=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.jetbrains.kotlinx:atomicfu:0.21.0=implementationDependenciesMetadata,testImplementationDependenciesMetadata -org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.7.3=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.7.3=compileClasspath,kotlinBuildToolsApiClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.7.3=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.jetbrains.kotlinx:atomicfu:0.23.1=implementationDependenciesMetadata,testImplementationDependenciesMetadata +org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.8.1=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.8.1=compileClasspath,kotlinBuildToolsApiClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.8.1=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.jetbrains:annotations:13.0=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath org.jetbrains:annotations:17.0.0=testImplementationDependenciesMetadata org.jetbrains:annotations:23.0.0=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.jooq:jooq-codegen:3.19.15=compileClasspath,implementationDependenciesMetadata,jooqGenerator,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.jooq:jooq-meta:3.19.15=compileClasspath,implementationDependenciesMetadata,jooqGenerator,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.jooq:jooq:3.19.15=compileClasspath,implementationDependenciesMetadata,jooqGenerator,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.json:json:20231013=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.jooq:jooq-codegen:3.19.14=compileClasspath,implementationDependenciesMetadata,jooqGenerator,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.jooq:jooq-meta:3.19.14=compileClasspath,implementationDependenciesMetadata,jooqGenerator,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.jooq:jooq:3.19.14=compileClasspath,implementationDependenciesMetadata,jooqGenerator,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.json:json:20240303=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.jspecify:jspecify:1.0.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.junit.jupiter:junit-jupiter-api:5.10.5=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.junit.jupiter:junit-jupiter-engine:5.10.5=testRuntimeClasspath @@ -211,9 +209,10 @@ org.junit.platform:junit-platform-commons:1.10.5=testCompileClasspath,testImplem org.junit.platform:junit-platform-engine:1.10.5=testRuntimeClasspath org.junit.platform:junit-platform-launcher:1.10.5=testRuntimeClasspath org.junit:junit-bom:5.10.5=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.latencyutils:LatencyUtils:2.0.3=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath org.mockito.kotlin:mockito-kotlin:5.4.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.mockito:mockito-core:5.12.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.mockito:mockito-junit-jupiter:5.7.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.mockito:mockito-junit-jupiter:5.11.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.objenesis:objenesis:3.3=testRuntimeClasspath org.openjdk.nashorn:nashorn-core:15.4=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath @@ -226,7 +225,7 @@ org.ow2.asm:asm-util:7.3.1=compileClasspath,implementationDependenciesMetadata,p org.ow2.asm:asm:9.6=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.ow2.asm:asm:9.7=jacocoAnt org.owasp.encoder:encoder:1.2.3=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.postgresql:postgresql:42.6.2=compileClasspath,flywayMigration,implementationDependenciesMetadata,jooqGenerator,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.postgresql:postgresql:42.7.4=compileClasspath,flywayMigration,implementationDependenciesMetadata,jooqGenerator,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.reactivestreams:reactive-streams:1.0.4=compileClasspath,implementationDependenciesMetadata,jooqGenerator,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.seleniumhq.selenium:selenium-api:4.25.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath @@ -250,40 +249,41 @@ org.seleniumhq.selenium:selenium-support:4.25.0=testCompileClasspath,testImpleme org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.slf4j:slf4j-api:2.0.16=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.springframework.boot:spring-boot-autoconfigure:3.2.11=compileOnlyDependenciesMetadata -org.springframework.boot:spring-boot-autoconfigure:3.3.2=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.springframework.boot:spring-boot-configuration-processor:3.2.11=annotationProcessor -org.springframework.boot:spring-boot-dependencies:3.2.11=annotationProcessor,apiDependenciesMetadata,compile,compileClasspath,compileOnlyDependenciesMetadata,developmentOnly,flywayMigration,implementationDependenciesMetadata,intransitiveDependenciesMetadata,jacocoAgent,jacocoAnt,jooqGenerator,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath,kotlinNativeCompilerPluginClasspath,kotlinScriptDef,kotlinScriptDefExtensions,productionRuntimeClasspath,runtimeClasspath,testAndDevelopmentOnly,testAnnotationProcessor,testApiDependenciesMetadata,testCompileClasspath,testCompileOnlyDependenciesMetadata,testImplementationDependenciesMetadata,testIntransitiveDependenciesMetadata,testKotlinScriptDef,testKotlinScriptDefExtensions,testRuntimeClasspath -org.springframework.boot:spring-boot-devtools:3.2.11=compileClasspath,compileOnlyDependenciesMetadata -org.springframework.boot:spring-boot-starter-aop:3.2.11=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-data-jpa:3.2.11=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-jdbc:3.2.11=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-json:3.2.11=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-logging:3.3.2=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-oauth2-client:3.2.11=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-security:3.2.11=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-test:3.2.11=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-undertow:3.2.11=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-web:3.2.11=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.springframework.boot:spring-boot-starter:3.3.2=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.springframework.boot:spring-boot-test-autoconfigure:3.2.11=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.springframework.boot:spring-boot-test:3.2.11=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.springframework.boot:spring-boot:3.2.11=compileOnlyDependenciesMetadata -org.springframework.boot:spring-boot:3.3.2=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.springframework.data:spring-data-commons:3.2.11=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.springframework.data:spring-data-jpa:3.2.11=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.springframework.data:spring-data-keyvalue:3.2.11=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.springframework.data:spring-data-redis:3.2.11=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.springframework.security:spring-security-config:6.2.7=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.springframework.security:spring-security-core:6.2.7=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.springframework.security:spring-security-crypto:6.2.7=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.springframework.security:spring-security-oauth2-client:6.2.7=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.springframework.security:spring-security-oauth2-core:6.2.7=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.springframework.security:spring-security-oauth2-jose:6.2.7=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.springframework.security:spring-security-test:6.2.7=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.springframework.security:spring-security-web:6.2.7=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.springframework.session:spring-session-core:3.2.6=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -org.springframework.session:spring-session-data-redis:3.2.6=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.boot:spring-boot-actuator-autoconfigure:3.3.5=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.boot:spring-boot-actuator:3.3.5=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.boot:spring-boot-autoconfigure:3.3.5=compileClasspath,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.boot:spring-boot-configuration-processor:3.3.5=annotationProcessor +org.springframework.boot:spring-boot-dependencies:3.3.5=annotationProcessor,apiDependenciesMetadata,compile,compileClasspath,compileOnlyDependenciesMetadata,developmentOnly,flywayMigration,implementationDependenciesMetadata,intransitiveDependenciesMetadata,jacocoAgent,jacocoAnt,jooqGenerator,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath,kotlinNativeCompilerPluginClasspath,kotlinScriptDef,kotlinScriptDefExtensions,productionRuntimeClasspath,runtimeClasspath,testAndDevelopmentOnly,testAnnotationProcessor,testApiDependenciesMetadata,testCompileClasspath,testCompileOnlyDependenciesMetadata,testImplementationDependenciesMetadata,testIntransitiveDependenciesMetadata,testKotlinScriptDef,testKotlinScriptDefExtensions,testRuntimeClasspath +org.springframework.boot:spring-boot-devtools:3.3.5=compileClasspath,compileOnlyDependenciesMetadata +org.springframework.boot:spring-boot-starter-actuator:3.3.5=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-aop:3.3.5=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-data-jpa:3.3.5=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-jdbc:3.3.5=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-json:3.3.5=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-logging:3.3.5=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-oauth2-client:3.3.5=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-security:3.3.5=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-test:3.3.5=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-undertow:3.3.5=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-web:3.3.5=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.boot:spring-boot-starter:3.3.5=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.boot:spring-boot-test-autoconfigure:3.3.5=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.boot:spring-boot-test:3.3.5=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.boot:spring-boot:3.3.5=compileClasspath,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.data:spring-data-commons:3.3.5=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.data:spring-data-jpa:3.3.5=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.data:spring-data-keyvalue:3.3.5=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.data:spring-data-redis:3.3.5=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.security:spring-security-config:6.3.4=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.security:spring-security-core:6.3.4=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.security:spring-security-crypto:6.3.4=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.security:spring-security-oauth2-client:6.3.4=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.security:spring-security-oauth2-core:6.3.4=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.security:spring-security-oauth2-jose:6.3.4=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.security:spring-security-test:6.3.4=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.security:spring-security-web:6.3.4=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.session:spring-session-core:3.3.3=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +org.springframework.session:spring-session-data-redis:3.3.3=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.springframework:spring-aop:6.1.14=compileClasspath,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.springframework:spring-aspects:6.1.14=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.springframework:spring-beans:6.1.14=compileClasspath,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath @@ -316,5 +316,5 @@ org.wildfly.client:wildfly-client-config:1.0.1.Final=compileClasspath,implementa org.wildfly.common:wildfly-common:1.5.4.Final=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.xmlunit:xmlunit-core:2.9.1=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath org.yaml:snakeyaml:2.2=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath -space.npstr:prometheus_extensions:1.7.1=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath +space.npstr:prometheus_extensions:1.10.1=compileClasspath,implementationDependenciesMetadata,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath empty= diff --git a/gradle.properties b/gradle.properties index e8c6e8a7..7276997e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -28,8 +28,8 @@ org.gradle.warning.mode=all javaVersion=21 postgresVersion=16 kotlinVersion=[1.9.21, 2.0[ -springBootVersion=[3.2, 3.3[ -flywayVersion=[9.17.0, 10.0[ +springBootVersion=[3.3.5, 3.4[ +flywayVersion=[10.21.0, 12.0[ gradleGitVersion=[2.2.4, 3.0[ grGitVersion=[5.2.0, 6.0[ @@ -46,12 +46,13 @@ theYarnVersion=1.22.19 jdaVersion=[5.2.0, 5.3[ discordWebhooksVersion=[0.8.2, 1.0[ sentryVersion=7.16.0 -orgJsonVersion=20231013 +orgJsonVersion=20240303 jaxbImplVersion=[4.0.2, 5.0[ nashornVersion=[15.4, 18[ -prometheusVersion=[0.16.0, 1.0[ -promExtVersion=[1.6, 1.8[ +# for caffeine metrics +prometheusClientVersion=1.3.2 +prometheusExtensionsVersion=1.10.1 dsProxyVersion=[1.9, 2.0[ jooqVersion=[3.19.2, 3.20[ @@ -60,3 +61,6 @@ togglzVersion=[4.0, 5.0[ selenideVersion=[7.0.3, 8.0[ mockitoKotlinVersion=[5.0.0, 6.0[ + +#https://stackoverflow.com/questions/78638699/bootjar-task-fails-with-gradle-8-5-and-spring-boot-3-3-0-caused-by-spring-boot +apacheCompressVersion=1.26.2 diff --git a/src/main/java/space/npstr/wolfia/Launcher.java b/src/main/java/space/npstr/wolfia/Launcher.java index 9c8cab1a..857c16f4 100644 --- a/src/main/java/space/npstr/wolfia/Launcher.java +++ b/src/main/java/space/npstr/wolfia/Launcher.java @@ -17,7 +17,6 @@ package space.npstr.wolfia; -import io.prometheus.client.CollectorRegistry; import java.util.concurrent.ScheduledThreadPoolExecutor; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDAInfo; @@ -26,11 +25,6 @@ import org.springframework.boot.ApplicationRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration; -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; -import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; -import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; -import org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration; import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; import org.springframework.boot.context.event.ApplicationFailedEvent; import space.npstr.prometheus_extensions.ThreadPoolCollector; @@ -45,22 +39,11 @@ * //general list of todos etc * //todo rename role pm/dm -> rolecard */ -@SpringBootApplication(exclude = { //we handle these ourselves - DataSourceAutoConfiguration.class, - DataSourceTransactionManagerAutoConfiguration.class, - HibernateJpaAutoConfiguration.class, - FlywayAutoConfiguration.class, - R2dbcAutoConfiguration.class, -}) +@SpringBootApplication public class Launcher implements ApplicationRunner { private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(Launcher.class); - static { - // https://github.com/prometheus/client_java/issues/279 - CollectorRegistry.defaultRegistry.clear(); - } - private final ThreadPoolCollector poolMetrics; private final WolfiaConfig wolfiaConfig; @SuppressWarnings({"FieldCanBeLocal", "unused", "squid:S1068"}) //see EagerLoader diff --git a/src/main/java/space/npstr/wolfia/ShutdownHandler.java b/src/main/java/space/npstr/wolfia/ShutdownHandler.java index f6a8e217..3299df69 100644 --- a/src/main/java/space/npstr/wolfia/ShutdownHandler.java +++ b/src/main/java/space/npstr/wolfia/ShutdownHandler.java @@ -17,7 +17,6 @@ package space.npstr.wolfia; -import io.prometheus.client.CollectorRegistry; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; @@ -29,7 +28,6 @@ import org.springframework.context.event.ContextClosedEvent; import org.springframework.stereotype.Component; import space.npstr.wolfia.config.ShardManagerFactory; -import space.npstr.wolfia.db.Database; import space.npstr.wolfia.domain.game.GameRegistry; import space.npstr.wolfia.events.BotStatusLogger; import space.npstr.wolfia.game.tools.ExceptionLoggingExecutor; @@ -49,7 +47,6 @@ public class ShutdownHandler implements ApplicationListener private static final Thread DUMMY_HOOK = new Thread("dummy-hook"); private final BotStatusLogger botStatusLogger; private final ExceptionLoggingExecutor executor; - private final Database database; private final ShardManagerFactory shardManagerFactory; private final GameRegistry gameRegistry; private final Redis redis; @@ -57,12 +54,11 @@ public class ShutdownHandler implements ApplicationListener private boolean shuttingDown = false; - public ShutdownHandler(BotStatusLogger botStatusLogger, ExceptionLoggingExecutor executor, Database database, + public ShutdownHandler(BotStatusLogger botStatusLogger, ExceptionLoggingExecutor executor, ShardManagerFactory shardManagerFactory, GameRegistry gameRegistry, Redis redis, @Qualifier("jdaThreadPool") ScheduledExecutorService jdaThreadPool) { this.botStatusLogger = botStatusLogger; this.executor = executor; - this.database = database; this.shardManagerFactory = shardManagerFactory; this.gameRegistry = gameRegistry; this.redis = redis; @@ -149,16 +145,9 @@ private void shutdown() { Thread.currentThread().interrupt(); } - //shutdown DB connection - log.info("Shutting down database connection"); - database.shutdown(); - //shutdown Redis connection log.info("Shutting down redis connection"); redis.shutdown(); - - //avoid trouble with spring dev tools, see https://github.com/prometheus/client_java/issues/279#issuecomment-335817904 - CollectorRegistry.defaultRegistry.clear(); } public void shutdown(int code) { diff --git a/src/main/java/space/npstr/wolfia/commands/CommandContext.java b/src/main/java/space/npstr/wolfia/commands/CommandContext.java index f920b3ed..1a0c0070 100644 --- a/src/main/java/space/npstr/wolfia/commands/CommandContext.java +++ b/src/main/java/space/npstr/wolfia/commands/CommandContext.java @@ -24,6 +24,7 @@ import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import org.springframework.lang.Nullable; +import space.npstr.wolfia.system.metrics.MetricsService; import space.npstr.wolfia.utils.discord.RestActions; /** @@ -35,6 +36,7 @@ public class CommandContext extends MessageContext { private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CommandContext.class); + private final MetricsService metricsService; //@formatter:off public final String trigger; // the command trigger, e.g. "play", or "p", or "pLaY", whatever the user typed public final String[] args ; // the arguments split by whitespace, excluding prefix and trigger @@ -43,10 +45,11 @@ public class CommandContext extends MessageContext { // private final Histogram.Timer received; // time when we received this command //@formatter:on - CommandContext(MessageReceivedEvent event, String trigger, + CommandContext(MessageReceivedEvent event, MetricsService metricsService, String trigger, String[] args, String rawArgs, BaseCommand command) { - super(event); + super(event, metricsService); + this.metricsService = metricsService; this.trigger = trigger; this.args = args; this.rawArgs = rawArgs; @@ -89,7 +92,7 @@ public GuildCommandContext requireGuild(boolean... answerUser) { Guild g = tc.getGuild(); Member m = this.event.getMember(); if (m != null) { - return new GuildCommandContext(this, g, m, tc); + return new GuildCommandContext(this, metricsService, g, m, tc); } else { log.warn("Uh oh member is unexpectedly null when transforming CommandContext to GuildCommandContext"); } diff --git a/src/main/java/space/npstr/wolfia/commands/CommandContextParser.java b/src/main/java/space/npstr/wolfia/commands/CommandContextParser.java index d7d3c273..822068e7 100644 --- a/src/main/java/space/npstr/wolfia/commands/CommandContextParser.java +++ b/src/main/java/space/npstr/wolfia/commands/CommandContextParser.java @@ -17,16 +17,22 @@ package space.npstr.wolfia.commands; +import java.util.Arrays; +import java.util.regex.Pattern; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import org.springframework.stereotype.Component; import space.npstr.wolfia.config.properties.WolfiaConfig; - -import java.util.Arrays; -import java.util.regex.Pattern; +import space.npstr.wolfia.system.metrics.MetricsService; @Component public class CommandContextParser { + private final MetricsService metricsService; + + public CommandContextParser(MetricsService metricsService) { + this.metricsService = metricsService; + } + /** * @param event the event to be parsed * @return The full context for the triggered command, or null if it's not a command that we know. @@ -61,7 +67,7 @@ public CommandContext parse(CommRegistry commRegistry, MessageReceivedEvent even if (command == null) { return null; } else { - return new CommandContext(event, commandTrigger, + return new CommandContext(event, metricsService, commandTrigger, Arrays.copyOfRange(args, 1, args.length),//exclude args[0] that contains the command trigger input.replaceFirst(Pattern.quote(commandTrigger), "").trim(), command diff --git a/src/main/java/space/npstr/wolfia/commands/CommandHandler.java b/src/main/java/space/npstr/wolfia/commands/CommandHandler.java index db6186a1..df209853 100644 --- a/src/main/java/space/npstr/wolfia/commands/CommandHandler.java +++ b/src/main/java/space/npstr/wolfia/commands/CommandHandler.java @@ -17,7 +17,7 @@ package space.npstr.wolfia.commands; -import io.prometheus.client.Summary; +import io.micrometer.core.instrument.Timer; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -48,13 +48,11 @@ import space.npstr.wolfia.game.Game; import space.npstr.wolfia.game.exceptions.IllegalGameStateException; import space.npstr.wolfia.system.ApplicationInfoProvider; -import space.npstr.wolfia.system.metrics.MetricsRegistry; +import space.npstr.wolfia.system.metrics.MetricsService; import space.npstr.wolfia.utils.UserFriendlyException; import space.npstr.wolfia.utils.discord.RestActions; import space.npstr.wolfia.utils.discord.TextchatUtils; -import static io.prometheus.client.Summary.Timer; - /** * Some architectural notes: * Issued commands will always go through here. It is their own job to find out for which game they have been issued, @@ -70,21 +68,23 @@ public class CommandHandler { private final CommRegistry commRegistry; private final ChannelSettingsService channelSettingsService; private final PrivacyService privacyService; + private final MetricsService metricsService; public CommandHandler(GameRegistry gameRegistry, CommandContextParser commandContextParser, CommRegistry commRegistry, ChannelSettingsService channelSettingsService, - PrivacyService privacyService) { + PrivacyService privacyService, MetricsService metricsService) { this.gameRegistry = gameRegistry; this.commandContextParser = commandContextParser; this.commRegistry = commRegistry; this.channelSettingsService = channelSettingsService; this.privacyService = privacyService; + this.metricsService = metricsService; } @EventListener public void onMessageReceived(MessageReceivedEvent event) { - Timer received = MetricsRegistry.commandRetentionTime.startTimer(); + Timer.Sample received = Timer.start(); //ignore bot accounts generally if (event.getAuthor().isBot()) { return; @@ -176,7 +176,7 @@ private List suggestGameEnabledChannels(CommandContext context) { /** * @param context the parsed input of a user */ - private void handleCommand(CommandContext context, Timer received) { + private void handleCommand(CommandContext context, Timer.Sample received) { try { boolean canCallCommand = context.command instanceof PublicCommand || context.isOwner(); if (!canCallCommand) { @@ -188,9 +188,12 @@ private void handleCommand(CommandContext context, Timer received) { log.info("user {}, channel {}, command {} about to be executed", context.invoker, context.channel, context.msg.getContentRaw()); - received.observeDuration();//retention - try (Summary.Timer ignored = MetricsRegistry.commandProcessTime.labels(context.command.getClass().getSimpleName()).startTimer()) { + received.stop(metricsService.commandRetentionTime()); //retention + Timer.Sample sample = Timer.start(); + try { context.command.execute(context); + } finally { + sample.stop(metricsService.commandProcessTime(context.command.getClass().getSimpleName())); } } catch (UserFriendlyException e) { context.reply("There was a problem executing your command:\n" + e.getMessage()); diff --git a/src/main/java/space/npstr/wolfia/commands/GuildCommandContext.java b/src/main/java/space/npstr/wolfia/commands/GuildCommandContext.java index 789e4c83..c3fd3317 100644 --- a/src/main/java/space/npstr/wolfia/commands/GuildCommandContext.java +++ b/src/main/java/space/npstr/wolfia/commands/GuildCommandContext.java @@ -21,6 +21,7 @@ import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import space.npstr.wolfia.system.metrics.MetricsService; /** * Provides non-null methods for accessing guild entities after an elegant transformation from a CommandContext @@ -48,9 +49,9 @@ public TextChannel getTextChannel() { return this.textChannel; } - public GuildCommandContext(CommandContext context, Guild guild, + public GuildCommandContext(CommandContext context, MetricsService metricsService, Guild guild, Member member, TextChannel textChannel) { - super(context.event, context.trigger, context.args, context.rawArgs, context.command); + super(context.event, metricsService, context.trigger, context.args, context.rawArgs, context.command); this.guild = guild; this.member = member; this.textChannel = textChannel; diff --git a/src/main/java/space/npstr/wolfia/commands/MessageContext.java b/src/main/java/space/npstr/wolfia/commands/MessageContext.java index 153ed057..23f9d660 100644 --- a/src/main/java/space/npstr/wolfia/commands/MessageContext.java +++ b/src/main/java/space/npstr/wolfia/commands/MessageContext.java @@ -17,8 +17,10 @@ package space.npstr.wolfia.commands; -import io.prometheus.client.Collector; +import io.micrometer.core.instrument.Timer; import java.awt.Color; +import java.time.Duration; +import java.time.Instant; import java.util.Optional; import java.util.function.Consumer; import net.dv8tion.jda.api.EmbedBuilder; @@ -34,7 +36,7 @@ import net.dv8tion.jda.api.utils.messages.MessageCreateData; import org.springframework.lang.Nullable; import space.npstr.wolfia.system.ApplicationInfoProvider; -import space.npstr.wolfia.system.metrics.MetricsRegistry; +import space.npstr.wolfia.system.metrics.MetricsService; import space.npstr.wolfia.utils.discord.RestActions; import space.npstr.wolfia.utils.discord.TextchatUtils; @@ -52,16 +54,18 @@ public class MessageContext implements Context { public final Message msg; public final MessageReceivedEvent event; public final JDA jda; + private final MetricsService metricsService; private final ApplicationInfoProvider appInfoProvider; - public MessageContext(MessageReceivedEvent event) { + public MessageContext(MessageReceivedEvent event, MetricsService metricsService) { this.channel = event.getChannel(); this.invoker = event.getAuthor(); this.msg = event.getMessage(); this.event = event; this.jda = event.getJDA(); this.appInfoProvider = new ApplicationInfoProvider(event.getJDA().getShardManager()); + this.metricsService = metricsService; } @@ -178,13 +182,13 @@ public static EmbedBuilder getDefaultEmbedBuilder() { // ******************************************************************************** private void reply0(MessageCreateData message, @Nullable Consumer onSuccess) { - long started = System.nanoTime(); + Timer.Sample sample = Timer.start(); Consumer successWrapper = m -> { - MetricsRegistry.commandResponseTime.observe((System.nanoTime() - started) / Collector.NANOSECONDS_PER_SECOND); - long in = getMessage().getTimeCreated().toInstant().toEpochMilli(); - long out = m.getTimeCreated().toInstant().toEpochMilli(); - MetricsRegistry.commandTotalTime.observe((out - in) / Collector.MILLISECONDS_PER_SECOND); + sample.stop(metricsService.commandResponseTime()); + Instant in = getMessage().getTimeCreated().toInstant(); + Instant out = m.getTimeCreated().toInstant(); + metricsService.commandTotalTime().record(Duration.between(in, out)); if (onSuccess != null) { onSuccess.accept(m); } diff --git a/src/main/java/space/npstr/wolfia/commands/debug/EvalCommand.java b/src/main/java/space/npstr/wolfia/commands/debug/EvalCommand.java index 81f08dc2..53cb1ae5 100644 --- a/src/main/java/space/npstr/wolfia/commands/debug/EvalCommand.java +++ b/src/main/java/space/npstr/wolfia/commands/debug/EvalCommand.java @@ -28,9 +28,9 @@ import net.dv8tion.jda.api.entities.emoji.Emoji; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; +import org.springframework.lang.NonNull; import space.npstr.wolfia.commands.BaseCommand; import space.npstr.wolfia.commands.CommandContext; -import space.npstr.wolfia.db.Database; import space.npstr.wolfia.domain.Command; import space.npstr.wolfia.domain.game.GameRegistry; import space.npstr.wolfia.game.tools.ExceptionLoggingExecutor; @@ -47,7 +47,6 @@ public class EvalCommand implements BaseCommand, ApplicationContextAware { private final ExceptionLoggingExecutor executor; private final GameRegistry gameRegistry; - private final Database database; private ApplicationContext applicationContext; private Future lastTask; @@ -55,10 +54,9 @@ public class EvalCommand implements BaseCommand, ApplicationContextAware { //Thanks Fred & Dinos! private final ScriptEngine engine; - public EvalCommand(ExceptionLoggingExecutor executor, GameRegistry gameRegistry, Database database) { + public EvalCommand(ExceptionLoggingExecutor executor, GameRegistry gameRegistry) { this.executor = executor; this.gameRegistry = gameRegistry; - this.database = database; this.engine = new ScriptEngineManager().getEngineByName("nashorn"); try { this.engine.eval("var imports = new JavaImporter(" @@ -73,7 +71,7 @@ public EvalCommand(ExceptionLoggingExecutor executor, GameRegistry gameRegistry, } @Override - public void setApplicationContext(ApplicationContext applicationContext) { + public void setApplicationContext(@NonNull ApplicationContext applicationContext) { this.applicationContext = applicationContext; } @@ -131,7 +129,6 @@ public boolean execute(CommandContext context) { this.engine.put("guild", guild.orElse(null)); this.engine.put("game", this.gameRegistry.get(context.channel.getIdLong())); this.engine.put("games", this.gameRegistry); - this.engine.put("db", this.database); this.engine.put("app", this.applicationContext); Future future = this.executor.submit(() -> { @@ -154,9 +151,9 @@ public boolean execute(CommandContext context) { if (out == null) { output = ""; } else if (out.toString().contains("\n")) { - output = "EvalCommand: ```\n" + out.toString() + "```"; + output = "EvalCommand: ```\n" + out + "```"; } else { - output = "EvalCommand: `" + out.toString() + "`"; + output = "EvalCommand: `" + out + "`"; } context.msg.addReaction(Emoji.fromUnicode(Emojis.OK_HAND)).queue(null, RestActions.defaultOnFail()); context.reply(String.format("```java%n%s```%n%s%n`%sms`", diff --git a/src/main/java/space/npstr/wolfia/config/MetricsConfiguration.java b/src/main/java/space/npstr/wolfia/config/MetricsConfiguration.java index fa7d243b..555d9f76 100644 --- a/src/main/java/space/npstr/wolfia/config/MetricsConfiguration.java +++ b/src/main/java/space/npstr/wolfia/config/MetricsConfiguration.java @@ -17,8 +17,8 @@ package space.npstr.wolfia.config; -import io.prometheus.client.cache.caffeine.CacheMetricsCollector; -import io.prometheus.client.logback.InstrumentedAppender; +import io.prometheus.metrics.instrumentation.caffeine.CacheMetricsCollector; +import io.prometheus.metrics.model.registry.PrometheusRegistry; import java.util.concurrent.ScheduledExecutorService; import net.dv8tion.jda.api.sharding.ShardManager; import net.ttddyy.dsproxy.listener.SingleQueryCountHolder; @@ -28,20 +28,16 @@ import space.npstr.prometheus_extensions.QueryCountCollector; import space.npstr.prometheus_extensions.ThreadPoolCollector; import space.npstr.prometheus_extensions.jda.JdaMetrics; -import space.npstr.wolfia.system.metrics.MetricsRegistry; @Configuration public class MetricsConfiguration { //caffeine cache metrics @Bean - public CacheMetricsCollector cacheMetrics() { - return new CacheMetricsCollector().register(); - } - - @Bean - public InstrumentedAppender instrumentedAppender() { - return new InstrumentedAppender(); + public CacheMetricsCollector cacheMetrics(PrometheusRegistry registry) { + CacheMetricsCollector cacheMetricsCollector = new CacheMetricsCollector(); + registry.register(cacheMetricsCollector); + return cacheMetricsCollector; } @Bean @@ -50,19 +46,22 @@ public SingleQueryCountHolder queryCountHolder() { } @Bean - public QueryCountCollector queryCountCollector(SingleQueryCountHolder queryCountHolder) { - return new QueryCountCollector(queryCountHolder); + public QueryCountCollector queryCountCollector(SingleQueryCountHolder queryCountHolder, PrometheusRegistry registry) { + return new QueryCountCollector(queryCountHolder, registry); } @Bean - public ThreadPoolCollector threadPoolCollector() { - return new ThreadPoolCollector(); + public ThreadPoolCollector threadPoolCollector(PrometheusRegistry registry) { + return new ThreadPoolCollector(registry); } @Bean - public JdaMetrics jdaMetrics(ShardManager shardManager, @Qualifier("jdaThreadPool") ScheduledExecutorService scheduler, - MetricsRegistry metricsRegistry) { + public JdaMetrics jdaMetrics( + ShardManager shardManager, + @Qualifier("jdaThreadPool") ScheduledExecutorService scheduler, + PrometheusRegistry registry + ) { - return new JdaMetrics(shardManager, scheduler, metricsRegistry.getRegistry()); + return new JdaMetrics(shardManager, scheduler, registry); } } diff --git a/src/main/java/space/npstr/wolfia/config/TogglzConfiguration.java b/src/main/java/space/npstr/wolfia/config/TogglzConfiguration.java index 38f34ad9..b361b1a1 100644 --- a/src/main/java/space/npstr/wolfia/config/TogglzConfiguration.java +++ b/src/main/java/space/npstr/wolfia/config/TogglzConfiguration.java @@ -19,6 +19,7 @@ import java.time.Clock; import java.time.Duration; +import javax.sql.DataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.togglz.core.logging.LoggingStateRepository; @@ -26,7 +27,6 @@ import org.togglz.core.repository.composite.CompositeStateRepository; import org.togglz.core.user.UserProvider; import org.togglz.spring.security.SpringSecurityUserProvider; -import space.npstr.wolfia.db.Database; import space.npstr.wolfia.system.togglz.ExceptionTolerantCachingStateRepo; import space.npstr.wolfia.system.togglz.PostgresJdbcStateRepo; import space.npstr.wolfia.system.togglz.StatusLoggingStateRepo; @@ -36,8 +36,8 @@ public class TogglzConfiguration { @Bean - public StateRepository stateRepository(Database database, Clock clock, StatusLoggingStateRepo statusLoggingStateRepo) { - var jdbcStateRepository = new PostgresJdbcStateRepo(database.getConnection().getDataSource()); + public StateRepository stateRepository(DataSource dataSource, Clock clock, StatusLoggingStateRepo statusLoggingStateRepo) { + var jdbcStateRepository = new PostgresJdbcStateRepo(dataSource); Duration ttl = Duration.ofMinutes(1); Duration stalePeriod = Duration.ofMinutes(1); var cachingJdbcStateRepo = new ExceptionTolerantCachingStateRepo(jdbcStateRepository, diff --git a/src/main/java/space/npstr/wolfia/config/WebApplicationSecurity.java b/src/main/java/space/npstr/wolfia/config/WebApplicationSecurity.java index 8dae5190..1a8f1034 100644 --- a/src/main/java/space/npstr/wolfia/config/WebApplicationSecurity.java +++ b/src/main/java/space/npstr/wolfia/config/WebApplicationSecurity.java @@ -80,6 +80,7 @@ public class WebApplicationSecurity { private static final String[] MACHINE_ENDPOINTS = { "/metrics", + "/health", }; private static final String[] PUBLIC_ENDPOINTS = { "/public/**", diff --git a/src/main/java/space/npstr/wolfia/db/DataSourceProxyPostProcessor.kt b/src/main/java/space/npstr/wolfia/db/DataSourceProxyPostProcessor.kt new file mode 100644 index 00000000..130c9026 --- /dev/null +++ b/src/main/java/space/npstr/wolfia/db/DataSourceProxyPostProcessor.kt @@ -0,0 +1,52 @@ +package space.npstr.wolfia.db + +import java.util.concurrent.TimeUnit.SECONDS +import javax.sql.DataSource +import net.ttddyy.dsproxy.listener.SingleQueryCountHolder +import net.ttddyy.dsproxy.listener.logging.DefaultQueryLogEntryCreator +import net.ttddyy.dsproxy.listener.logging.SLF4JLogLevel.WARN +import net.ttddyy.dsproxy.listener.logging.SLF4JSlowQueryListener +import net.ttddyy.dsproxy.support.ProxyDataSourceBuilder +import org.springframework.beans.factory.config.BeanPostProcessor +import org.springframework.stereotype.Component + +@Component +class DataSourceProxyPostProcessor( + queryCountHolder: SingleQueryCountHolder, +) : BeanPostProcessor { + + private val proxyDataSourceBuilder = ProxyDataSourceBuilder() + .listener(buildSlf4jSlowQueryListener()) + .multiline() + .name("postgres") + .countQuery(queryCountHolder) + + override fun postProcessAfterInitialization(bean: Any, beanName: String): Any? { +// if (bean is HikariDataSource) { +// //TODO does spring boot actuatur do this for us? +// logger().warn("PLONK setting metrics factory over {}", bean.metricsTrackerFactory?.javaClass?.simpleName) +// bean.metricsTrackerFactory = PrometheusMetricsTrackerFactory() +// } + + if (bean is DataSource) { + return proxyDataSourceBuilder.dataSource(bean).buildProxy() + } + return bean + } + + private fun buildSlf4jSlowQueryListener(): SLF4JSlowQueryListener { + val listener = SLF4JSlowQueryListener(30, SECONDS).apply { + logLevel = WARN + setLogger("SlowQueryLog") + queryLogEntryCreator = buildMultilineQueryLogEntryCreator() + } + return listener + } + + private fun buildMultilineQueryLogEntryCreator(): DefaultQueryLogEntryCreator { + val entryCreator = DefaultQueryLogEntryCreator() + entryCreator.isMultiline = true + return entryCreator + } + +} diff --git a/src/main/java/space/npstr/wolfia/db/Database.java b/src/main/java/space/npstr/wolfia/db/Database.java deleted file mode 100644 index 400f7a33..00000000 --- a/src/main/java/space/npstr/wolfia/db/Database.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (C) 2016-2023 the original author or authors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package space.npstr.wolfia.db; - -import com.zaxxer.hikari.HikariConfig; -import com.zaxxer.hikari.metrics.prometheus.PrometheusMetricsTrackerFactory; -import java.util.Properties; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; -import javax.annotation.concurrent.ThreadSafe; -import net.ttddyy.dsproxy.listener.QueryCountStrategy; -import net.ttddyy.dsproxy.listener.logging.SLF4JLogLevel; -import net.ttddyy.dsproxy.support.ProxyDataSourceBuilder; -import org.flywaydb.core.api.configuration.FluentConfiguration; -import org.jooq.DSLContext; -import org.jooq.SQLDialect; -import org.jooq.impl.DSL; -import org.springframework.stereotype.Component; -import space.npstr.wolfia.App; -import space.npstr.wolfia.config.properties.DatabaseConfig; -import space.npstr.wolfia.config.properties.WolfiaConfig; - -/** - * Serves lazily initialized database connection and wrapper singletons - */ -@ThreadSafe -@Component -public class Database { - - private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(Database.class); - - private final DatabaseConfig databaseConfig; - private final WolfiaConfig wolfiaConfig; - private final QueryCountStrategy queryCountStrategy; - - private final AtomicReference dbConnection = new AtomicReference<>(); - private final AtomicReference jooq = new AtomicReference<>(); - - public Database(DatabaseConfig databaseConfig, WolfiaConfig wolfiaConfig, - QueryCountStrategy queryCountStrategy) { - - this.databaseConfig = databaseConfig; - this.wolfiaConfig = wolfiaConfig; - this.queryCountStrategy = queryCountStrategy; - } - - public DatabaseConnection getConnection() { - DatabaseConnection singleton = this.dbConnection.get(); - if (singleton == null) { - synchronized (this.dbConnection) { - singleton = this.dbConnection.get(); - if (singleton == null) { - //try connecting to the database in a reasonable timeframe - boolean dbConnected = false; - long dbConnectStarted = System.currentTimeMillis(); - do { - try { - singleton = initDbConn(); - DSL.using(singleton.getDataSource(), SQLDialect.POSTGRES) - .selectOne().execute(); - dbConnected = true; - log.info("Initial db connection succeeded"); - this.dbConnection.set(singleton); - } catch (Exception e) { - log.warn("Failed initial db connection, retrying in a moment", e); - try { - this.dbConnection.wait(1000); - } catch (InterruptedException ignored) { - Thread.currentThread().interrupt(); - } - } - } while (!Thread.interrupted() - && !dbConnected - && System.currentTimeMillis() - dbConnectStarted < 1000 * 60 * 2); // 2 minutes - if (!dbConnected) { - log.error("Failed to init db connection in a reasonable amount of time, exiting."); - System.exit(2); - } - } - } - } - return singleton; - } - - public DSLContext jooq() { - DSLContext singleton = this.jooq.get(); - if (singleton == null) { - synchronized (this.jooq) { - singleton = this.jooq.get(); - if (singleton == null) { - singleton = DSL.using(getConnection().getDataSource(), SQLDialect.POSTGRES); - this.jooq.set(singleton); - } - } - } - return singleton; - } - - - public void shutdown() { - synchronized (this.dbConnection) { - DatabaseConnection conn = this.dbConnection.get(); - if (conn != null) { - conn.shutdown(); - } - } - } - - private DatabaseConnection initDbConn() { - try { - HikariConfig hikariConfig = getHikariConfig(); - hikariConfig.setDataSourceProperties(getDataSourceProps()); - return new DatabaseConnection( - hikariConfig, - new ProxyDataSourceBuilder() - .logSlowQueryBySlf4j(30, TimeUnit.SECONDS, SLF4JLogLevel.WARN, "SlowQueryLog") - .multiline() - .name("postgres") - .countQuery(this.queryCountStrategy), - new FluentConfiguration() - .locations("db/migrations") - ); - } catch (Exception e) { - throw new RuntimeException("Failed to set up database", e); - } - } - - private HikariConfig getHikariConfig() { - HikariConfig hikariConfig = new HikariConfig(); - - //more database connections don't help with performance, so use a default value based on available cores - //http://www.dailymotion.com/video/x2s8uec_oltp-performance-concurrent-mid-tier-connections_tech - hikariConfig.setMaximumPoolSize(Math.max(Runtime.getRuntime().availableProcessors(), 4)); - //timeout the validation query (will be done automatically through Connection.isValid()) - hikariConfig.setValidationTimeout(3000); - // 30 seconds, sometimes we time out after 10 on the new machine, but its not a leak. - hikariConfig.setConnectionTimeout(30L * 1000); - hikariConfig.setAutoCommit(false); - hikariConfig.setDriverClassName("org.postgresql.Driver"); - hikariConfig.setMetricsTrackerFactory(new PrometheusMetricsTrackerFactory()); - - hikariConfig.setJdbcUrl(this.databaseConfig.getJdbcUrl()); - hikariConfig.setPoolName("postgres-DefaultPool"); - - return hikariConfig; - } - - private Properties getDataSourceProps() { - Properties dataSourceProps = new Properties(); - - // allow postgres to cast strings (varchars) more freely to actual column types - // source https://jdbc.postgresql.org/documentation/head/connect.html - dataSourceProps.setProperty("stringtype", "unspecified"); - - String appName = "Wolfia_" + (this.wolfiaConfig.isDebug() ? "DEBUG" : "PROD") + "_" + App.VERSION; - dataSourceProps.setProperty("ApplicationName", appName); - - return dataSourceProps; - } -} diff --git a/src/main/java/space/npstr/wolfia/db/DatabaseConnection.java b/src/main/java/space/npstr/wolfia/db/DatabaseConnection.java deleted file mode 100644 index b70d27e7..00000000 --- a/src/main/java/space/npstr/wolfia/db/DatabaseConnection.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2016-2023 the original author or authors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package space.npstr.wolfia.db; - -import com.zaxxer.hikari.HikariConfig; -import com.zaxxer.hikari.HikariDataSource; -import javax.sql.DataSource; -import net.ttddyy.dsproxy.support.ProxyDataSource; -import net.ttddyy.dsproxy.support.ProxyDataSourceBuilder; -import org.flywaydb.core.Flyway; -import org.flywaydb.core.api.configuration.FluentConfiguration; -import org.jooq.exception.DataAccessException; - -public class DatabaseConnection { - - private final HikariDataSource hikariDataSource; - private final ProxyDataSource proxiedDataSource; - - /** - * @throws DataAccessException if the connection could not be created due to [reasons] - */ - public DatabaseConnection(HikariConfig hikariConfig, - ProxyDataSourceBuilder proxyDataSourceBuilder, - FluentConfiguration flywayConfig) { - - try { - this.hikariDataSource = new HikariDataSource(hikariConfig); - - flywayConfig.dataSource(this.hikariDataSource); - Flyway flyway = new Flyway(flywayConfig); - flyway.migrate(); - - this.proxiedDataSource = proxyDataSourceBuilder - .dataSource(this.hikariDataSource) - .build(); - } catch (Exception e) { - throw new DataAccessException("Failed to create database connection", e); - } - } - - public DataSource getDataSource() { - return this.proxiedDataSource; - } - - public void shutdown() { - this.hikariDataSource.close(); - } -} diff --git a/src/main/java/space/npstr/wolfia/db/HstoreRepository.kt b/src/main/java/space/npstr/wolfia/db/HstoreRepository.kt index 990b6240..c4080706 100644 --- a/src/main/java/space/npstr/wolfia/db/HstoreRepository.kt +++ b/src/main/java/space/npstr/wolfia/db/HstoreRepository.kt @@ -16,6 +16,7 @@ */ package space.npstr.wolfia.db +import org.jooq.DSLContext import org.jooq.Field import org.jooq.impl.DSL import org.springframework.stereotype.Repository @@ -24,14 +25,14 @@ import space.npstr.wolfia.db.gen.tables.records.HstorexRecord @Repository class HstoreRepository( - private val database: Database, + private val jooq: DSLContext, ) { /** * @return the default value if either the hstore or the key inside the hstore doesnt exist. */ fun get(name: String, key: String, defaultValue: String): String { - return database.jooq() + return jooq .select(Tables.HSTOREX.HSTOREX_) .from(Tables.HSTOREX) .where(Tables.HSTOREX.NAME.eq(name)) @@ -47,7 +48,7 @@ class HstoreRepository( fun set(name: String, toAppend: Map): HstorexRecord { val map = HashMap(toAppend) - return database.jooq().transactionResult { config -> + return jooq.transactionResult { config -> config.dsl() .insertInto(Tables.HSTOREX) .columns(Tables.HSTOREX.NAME, Tables.HSTOREX.HSTOREX_) diff --git a/src/main/java/space/npstr/wolfia/domain/ban/BanRepository.kt b/src/main/java/space/npstr/wolfia/domain/ban/BanRepository.kt index 3d0569d5..4b2dc855 100644 --- a/src/main/java/space/npstr/wolfia/domain/ban/BanRepository.kt +++ b/src/main/java/space/npstr/wolfia/domain/ban/BanRepository.kt @@ -16,25 +16,25 @@ */ package space.npstr.wolfia.domain.ban +import org.jooq.DSLContext import org.springframework.stereotype.Repository -import space.npstr.wolfia.db.Database import space.npstr.wolfia.db.gen.Tables import space.npstr.wolfia.game.definitions.Scope @Repository internal class BanRepository( - val database: Database, + private val jooq: DSLContext, ) { fun findOne(userId: Long, scope: Scope): Ban? { - return database.jooq() + return jooq .selectFrom(Tables.DISCORD_USER) .where(Tables.DISCORD_USER.USER_ID.eq(userId).and(Tables.DISCORD_USER.BAN.eq(scope.name))) .fetchOneInto(Ban::class.java) } fun setScope(userId: Long, scope: Scope): Ban { - return database.jooq().transactionResult { config -> + return jooq.transactionResult { config -> config.dsl() .insertInto(Tables.DISCORD_USER) .columns(Tables.DISCORD_USER.USER_ID, Tables.DISCORD_USER.BAN) @@ -47,7 +47,7 @@ internal class BanRepository( } fun findByScope(scope: Scope): List { - return database.jooq() + return jooq .selectFrom(Tables.DISCORD_USER) .where(Tables.DISCORD_USER.BAN.eq(scope.name)) .fetchInto(Ban::class.java) diff --git a/src/main/java/space/npstr/wolfia/domain/oauth2/AuthStateCache.java b/src/main/java/space/npstr/wolfia/domain/oauth2/AuthStateCache.java index 951e8180..864fbf9e 100644 --- a/src/main/java/space/npstr/wolfia/domain/oauth2/AuthStateCache.java +++ b/src/main/java/space/npstr/wolfia/domain/oauth2/AuthStateCache.java @@ -19,13 +19,12 @@ import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; -import io.prometheus.client.cache.caffeine.CacheMetricsCollector; -import org.springframework.stereotype.Component; - -import org.springframework.lang.Nullable; +import io.prometheus.metrics.instrumentation.caffeine.CacheMetricsCollector; import java.time.Duration; import java.util.Optional; import java.util.UUID; +import org.springframework.lang.Nullable; +import org.springframework.stereotype.Component; /** * This component serves two purposes: It secures the OAuth2 flow (see https://discord.com/developers/docs/topics/oauth2#state-and-security) diff --git a/src/main/java/space/npstr/wolfia/domain/oauth2/OAuth2Repository.kt b/src/main/java/space/npstr/wolfia/domain/oauth2/OAuth2Repository.kt index c381ff78..cb2ec447 100644 --- a/src/main/java/space/npstr/wolfia/domain/oauth2/OAuth2Repository.kt +++ b/src/main/java/space/npstr/wolfia/domain/oauth2/OAuth2Repository.kt @@ -16,19 +16,19 @@ */ package space.npstr.wolfia.domain.oauth2 -import org.springframework.stereotype.Repository -import space.npstr.wolfia.db.Database -import space.npstr.wolfia.db.gen.Tables import java.time.Duration import java.time.Instant +import org.jooq.DSLContext +import org.springframework.stereotype.Repository +import space.npstr.wolfia.db.gen.Tables @Repository class OAuth2Repository( - private val database: Database, + private val jooq: DSLContext, ) { fun findOne(userId: Long): OAuth2Data? { - return database.jooq() + return jooq .selectFrom(Tables.OAUTH2) .where(Tables.OAUTH2.USER_ID.eq(userId)) .fetchOneInto(OAuth2Data::class.java) @@ -36,14 +36,14 @@ class OAuth2Repository( fun findAllExpiringIn(duration: Duration): List { val expiresOn = Instant.now().plusSeconds(duration.toSeconds()) - return database.jooq() + return jooq .selectFrom(Tables.OAUTH2) .where(Tables.OAUTH2.EXPIRES.lessThan(expiresOn)) .fetchInto(OAuth2Data::class.java) } fun delete(userId: Long): Int { - return database.jooq().transactionResult { config -> + return jooq.transactionResult { config -> config.dsl() .deleteFrom(Tables.OAUTH2) .where(Tables.OAUTH2.USER_ID.eq(userId)) @@ -53,7 +53,7 @@ class OAuth2Repository( fun save(data: OAuth2Data): OAuth2Data { val scopes = data.scopes().toTypedArray() - return database.jooq().transactionResult { config -> + return jooq.transactionResult { config -> config.dsl() .insertInto(Tables.OAUTH2) .columns(Tables.OAUTH2.USER_ID, Tables.OAUTH2.ACCESS_TOKEN, Tables.OAUTH2.EXPIRES, Tables.OAUTH2.REFRESH_TOKEN, Tables.OAUTH2.SCOPES) diff --git a/src/main/java/space/npstr/wolfia/domain/privacy/PrivacyCommand.java b/src/main/java/space/npstr/wolfia/domain/privacy/PrivacyCommand.java index 311d7404..01fb0cab 100644 --- a/src/main/java/space/npstr/wolfia/domain/privacy/PrivacyCommand.java +++ b/src/main/java/space/npstr/wolfia/domain/privacy/PrivacyCommand.java @@ -26,6 +26,7 @@ import space.npstr.wolfia.domain.Command; import space.npstr.wolfia.domain.Conversation; import space.npstr.wolfia.system.EventWaiter; +import space.npstr.wolfia.system.metrics.MetricsService; import space.npstr.wolfia.utils.discord.Emojis; @Command @@ -40,10 +41,12 @@ public class PrivacyCommand implements BaseCommand, PublicCommand, Conversation private final EventWaiter eventWaiter; private final PrivacyService privacyService; + private final MetricsService metricsService; - public PrivacyCommand(EventWaiter eventWaiter, PrivacyService privacyService) { + public PrivacyCommand(EventWaiter eventWaiter, PrivacyService privacyService, MetricsService metricsService) { this.eventWaiter = eventWaiter; this.privacyService = privacyService; + this.metricsService = metricsService; } @Override @@ -82,7 +85,7 @@ private boolean showConversationOptions(MessageContext context) { } private boolean optionSelected(MessageReceivedEvent event) { - MessageContext context = new MessageContext(event); + MessageContext context = new MessageContext(event, metricsService); String rawContent = context.getMessage().getContentRaw(); if (rawContent.toLowerCase().startsWith(OPTION_READ)) { @@ -142,7 +145,7 @@ private boolean showConversationOptions(MessageContext context) { } private boolean optionSelected(MessageReceivedEvent event) { - MessageContext context = new MessageContext(event); + MessageContext context = new MessageContext(event, metricsService); String rawContent = context.getMessage().getContentRaw(); if (rawContent.toLowerCase().startsWith(OPTION_CONFIRM)) { diff --git a/src/main/java/space/npstr/wolfia/domain/privacy/PrivacyRepository.kt b/src/main/java/space/npstr/wolfia/domain/privacy/PrivacyRepository.kt index 8c46d93b..5a85d45c 100644 --- a/src/main/java/space/npstr/wolfia/domain/privacy/PrivacyRepository.kt +++ b/src/main/java/space/npstr/wolfia/domain/privacy/PrivacyRepository.kt @@ -16,24 +16,24 @@ */ package space.npstr.wolfia.domain.privacy +import org.jooq.DSLContext import org.springframework.stereotype.Repository -import space.npstr.wolfia.db.Database import space.npstr.wolfia.db.gen.Tables @Repository internal class PrivacyRepository( - private val database: Database, + private val jooq: DSLContext, ) { fun findOne(userId: Long): Privacy? { - return database.jooq() + return jooq .selectFrom(Tables.DISCORD_USER) .where(Tables.DISCORD_USER.USER_ID.eq(userId)) .fetchOneInto(Privacy::class.java) } fun setProcessData(userId: Long, processData: Boolean): Privacy { - return database.jooq().transactionResult { config -> + return jooq.transactionResult { config -> config.dsl() .insertInto(Tables.DISCORD_USER) .columns(Tables.DISCORD_USER.USER_ID, Tables.DISCORD_USER.PROCESS_DATA) @@ -46,7 +46,7 @@ internal class PrivacyRepository( } fun findAllDeniedProcessData(): List { - return database.jooq() + return jooq .selectFrom(Tables.DISCORD_USER) .where(Tables.DISCORD_USER.PROCESS_DATA.eq(false)) .fetchInto(Privacy::class.java) diff --git a/src/main/java/space/npstr/wolfia/domain/privacy/PrivacyRequestService.java b/src/main/java/space/npstr/wolfia/domain/privacy/PrivacyRequestService.java index 7da0985b..86858e72 100644 --- a/src/main/java/space/npstr/wolfia/domain/privacy/PrivacyRequestService.java +++ b/src/main/java/space/npstr/wolfia/domain/privacy/PrivacyRequestService.java @@ -19,7 +19,7 @@ import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; -import io.prometheus.client.cache.caffeine.CacheMetricsCollector; +import io.prometheus.metrics.instrumentation.caffeine.CacheMetricsCollector; import java.time.Duration; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/space/npstr/wolfia/domain/room/PrivateRoomQueue.java b/src/main/java/space/npstr/wolfia/domain/room/PrivateRoomQueue.java index 739847d8..e58350ae 100644 --- a/src/main/java/space/npstr/wolfia/domain/room/PrivateRoomQueue.java +++ b/src/main/java/space/npstr/wolfia/domain/room/PrivateRoomQueue.java @@ -28,7 +28,7 @@ import org.slf4j.LoggerFactory; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; -import space.npstr.wolfia.system.metrics.MetricsRegistry; +import space.npstr.wolfia.system.metrics.MetricsService; @Component public class PrivateRoomQueue { @@ -36,12 +36,14 @@ public class PrivateRoomQueue { private static final Logger log = LoggerFactory.getLogger(PrivateRoomQueue.class); private final ShardManager shardManager; + private final MetricsService metricsService; private final List allManagedRooms = new ArrayList<>(); private final LinkedBlockingQueue availablePrivateRoomQueue = new LinkedBlockingQueue<>(); - public PrivateRoomQueue(ShardManager shardManager, PrivateRoomService privateRoomService) { + public PrivateRoomQueue(ShardManager shardManager, MetricsService metricsService, PrivateRoomService privateRoomService) { this.shardManager = shardManager; + this.metricsService = metricsService; List privateRooms = privateRoomService.findAll().stream() .map(pr -> new ManagedPrivateRoom(shardManager, pr, this)) .toList(); @@ -65,7 +67,7 @@ public List getAllManagedRooms() { public ManagedPrivateRoom take() throws InterruptedException { ManagedPrivateRoom room = this.availablePrivateRoomQueue.take(); - MetricsRegistry.availablePrivateRooms.set(this.availableRoomsAmount()); + metricsService.availablePrivateRooms().set(this.availableRoomsAmount()); if (room.isInUse()) { log.warn("Got a room that is still in use: {}", room); } @@ -78,7 +80,7 @@ public Optional poll() { if (room.isInUse()) { log.warn("Got a room that is still in use: {}", room); } - MetricsRegistry.availablePrivateRooms.set(this.availableRoomsAmount()); + metricsService.availablePrivateRooms().set(this.availableRoomsAmount()); } return Optional.ofNullable(room); } @@ -95,14 +97,14 @@ public void putBack(ManagedPrivateRoom room) { } this.availablePrivateRoomQueue.add(room); - MetricsRegistry.availablePrivateRooms.set(this.availableRoomsAmount()); + metricsService.availablePrivateRooms().set(this.availableRoomsAmount()); } public ManagedPrivateRoom add(PrivateRoom privateRoom) { ManagedPrivateRoom managedPrivateRoom = new ManagedPrivateRoom(shardManager, privateRoom, this); this.allManagedRooms.add(managedPrivateRoom); this.availablePrivateRoomQueue.add(managedPrivateRoom); - MetricsRegistry.availablePrivateRooms.set(this.availableRoomsAmount()); + metricsService.availablePrivateRooms().set(this.availableRoomsAmount()); return managedPrivateRoom; } } diff --git a/src/main/java/space/npstr/wolfia/domain/room/PrivateRoomRepository.kt b/src/main/java/space/npstr/wolfia/domain/room/PrivateRoomRepository.kt index fcd6cc42..f4077899 100644 --- a/src/main/java/space/npstr/wolfia/domain/room/PrivateRoomRepository.kt +++ b/src/main/java/space/npstr/wolfia/domain/room/PrivateRoomRepository.kt @@ -16,25 +16,25 @@ */ package space.npstr.wolfia.domain.room +import org.jooq.DSLContext import org.jooq.impl.DSL import org.springframework.stereotype.Repository -import space.npstr.wolfia.db.Database import space.npstr.wolfia.db.gen.Tables @Repository internal class PrivateRoomRepository( - private val database: Database, + private val jooq: DSLContext, ) { fun findOneByGuildId(guildId: Long): PrivateRoom? { - return database.jooq() + return jooq .selectFrom(Tables.PRIVATE_ROOM) .where(Tables.PRIVATE_ROOM.GUILD_ID.eq(guildId)) .fetchOneInto(PrivateRoom::class.java) } fun findAll(): List { - return database.jooq() + return jooq .selectFrom(Tables.PRIVATE_ROOM) .orderBy(Tables.PRIVATE_ROOM.NR.asc()) .fetchInto(PrivateRoom::class.java) @@ -44,7 +44,7 @@ internal class PrivateRoomRepository( // this can probably be written in a single query but why bother, race conditions are not expected for registering fun insert(guildId: Long): PrivateRoom? { val firstFreeNumber = getFirstFreeNumber() - return database.jooq().transactionResult { config -> + return jooq.transactionResult { config -> config.dsl() .insertInto(Tables.PRIVATE_ROOM) .columns(Tables.PRIVATE_ROOM.GUILD_ID, Tables.PRIVATE_ROOM.NR) @@ -63,7 +63,6 @@ internal class PrivateRoomRepository( val a = Tables.PRIVATE_ROOM.`as`("a") val b = Tables.PRIVATE_ROOM.`as`("b") - val jooq = database.jooq() return jooq .select(a.NR.add(1)) .from(a) @@ -79,7 +78,7 @@ internal class PrivateRoomRepository( } private fun numberOneExists(): Boolean { - return database.jooq() + return jooq .select(DSL.value(1)) .from(Tables.PRIVATE_ROOM) .where(Tables.PRIVATE_ROOM.NR.eq(1)) diff --git a/src/main/java/space/npstr/wolfia/domain/settings/ChannelSettingsRepository.kt b/src/main/java/space/npstr/wolfia/domain/settings/ChannelSettingsRepository.kt index 4ce88839..f3674aba 100644 --- a/src/main/java/space/npstr/wolfia/domain/settings/ChannelSettingsRepository.kt +++ b/src/main/java/space/npstr/wolfia/domain/settings/ChannelSettingsRepository.kt @@ -16,9 +16,9 @@ */ package space.npstr.wolfia.domain.settings +import org.jooq.DSLContext import org.jooq.Field import org.springframework.stereotype.Repository -import space.npstr.wolfia.db.Database import space.npstr.wolfia.db.ExtendedPostgresDSL import space.npstr.wolfia.db.gen.Tables @@ -29,11 +29,11 @@ import space.npstr.wolfia.db.gen.Tables */ @Repository class ChannelSettingsRepository( - private val database: Database, + private val jooq: DSLContext, ) { fun findOne(channelId: Long): ChannelSettings? { - return database.jooq() + return jooq .selectFrom(Tables.CHANNEL_SETTINGS) .where(Tables.CHANNEL_SETTINGS.CHANNEL_ID.eq(channelId)) .fetchOneInto(ChannelSettings::class.java) @@ -41,7 +41,7 @@ class ChannelSettingsRepository( //this works since we dont commit the transaction fun findOneOrDefault(channelId: Long): ChannelSettings { - return database.jooq() + return jooq .insertInto(Tables.CHANNEL_SETTINGS) .columns(Tables.CHANNEL_SETTINGS.CHANNEL_ID) .values(channelId) @@ -56,7 +56,7 @@ class ChannelSettingsRepository( return if (channelIds.isEmpty()) { listOf() } else { - var insert = database.jooq() + var insert = jooq .insertInto(Tables.CHANNEL_SETTINGS) .columns(Tables.CHANNEL_SETTINGS.CHANNEL_ID) for (channelId in channelIds) { @@ -95,7 +95,7 @@ class ChannelSettingsRepository( fun addTags(channelId: Long, tags: Collection): ChannelSettings { val tagArray = tags.toTypedArray() - return database.jooq().transactionResult { config -> + return jooq.transactionResult { config -> config.dsl() .insertInto(Tables.CHANNEL_SETTINGS) .columns(Tables.CHANNEL_SETTINGS.CHANNEL_ID, Tables.CHANNEL_SETTINGS.TAGS) @@ -109,7 +109,7 @@ class ChannelSettingsRepository( fun removeTags(channelId: Long, tags: Collection): ChannelSettings { val tagArray = tags.toTypedArray() - return database.jooq().transactionResult { config -> + return jooq.transactionResult { config -> config.dsl() .insertInto(Tables.CHANNEL_SETTINGS) .columns(Tables.CHANNEL_SETTINGS.CHANNEL_ID, Tables.CHANNEL_SETTINGS.TAGS) @@ -122,7 +122,7 @@ class ChannelSettingsRepository( } fun delete(channelId: Long): Int { - return database.jooq().transactionResult { config -> + return jooq.transactionResult { config -> config.dsl() .deleteFrom(Tables.CHANNEL_SETTINGS) .where(Tables.CHANNEL_SETTINGS.CHANNEL_ID.eq(channelId)) @@ -131,7 +131,7 @@ class ChannelSettingsRepository( } private operator fun set(channelId: Long, field: Field, value: F): ChannelSettings { - return database.jooq().transactionResult { config -> + return jooq.transactionResult { config -> config.dsl() .insertInto(Tables.CHANNEL_SETTINGS) .columns(Tables.CHANNEL_SETTINGS.CHANNEL_ID, field) diff --git a/src/main/java/space/npstr/wolfia/domain/settings/GuildSettingsRepository.kt b/src/main/java/space/npstr/wolfia/domain/settings/GuildSettingsRepository.kt index f98240f3..1651937e 100644 --- a/src/main/java/space/npstr/wolfia/domain/settings/GuildSettingsRepository.kt +++ b/src/main/java/space/npstr/wolfia/domain/settings/GuildSettingsRepository.kt @@ -16,24 +16,24 @@ */ package space.npstr.wolfia.domain.settings +import org.jooq.DSLContext import org.springframework.stereotype.Repository -import space.npstr.wolfia.db.Database import space.npstr.wolfia.db.gen.Tables @Repository internal class GuildSettingsRepository( - private val database: Database, + private val jooq: DSLContext, ) { fun findOne(guildId: Long): GuildSettings? { - return database.jooq() + return jooq .selectFrom(Tables.GUILD_SETTINGS) .where(Tables.GUILD_SETTINGS.GUILD_ID.eq(guildId)) .fetchOneInto(GuildSettings::class.java) } fun findOneOrDefault(guildId: Long): GuildSettings { - return database.jooq() + return jooq .insertInto(Tables.GUILD_SETTINGS) .columns(Tables.GUILD_SETTINGS.GUILD_ID) .values(guildId) @@ -44,7 +44,7 @@ internal class GuildSettingsRepository( } fun set(guildId: Long, name: String, iconId: String?): GuildSettings { - return database.jooq().transactionResult { config -> + return jooq.transactionResult { config -> config.dsl() .insertInto(Tables.GUILD_SETTINGS) .columns(Tables.GUILD_SETTINGS.GUILD_ID, Tables.GUILD_SETTINGS.NAME, Tables.GUILD_SETTINGS.ICON_ID) diff --git a/src/main/java/space/npstr/wolfia/domain/setup/GameSetupRepository.kt b/src/main/java/space/npstr/wolfia/domain/setup/GameSetupRepository.kt index 6670f418..ef4f4d7d 100644 --- a/src/main/java/space/npstr/wolfia/domain/setup/GameSetupRepository.kt +++ b/src/main/java/space/npstr/wolfia/domain/setup/GameSetupRepository.kt @@ -17,9 +17,9 @@ package space.npstr.wolfia.domain.setup import java.time.Duration +import org.jooq.DSLContext import org.jooq.Field import org.springframework.stereotype.Repository -import space.npstr.wolfia.db.Database import space.npstr.wolfia.db.ExtendedPostgresDSL import space.npstr.wolfia.db.gen.Tables import space.npstr.wolfia.game.GameInfo.GameMode @@ -27,11 +27,11 @@ import space.npstr.wolfia.game.definitions.Games @Repository internal class GameSetupRepository( - private val database: Database, + private val jooq: DSLContext, ) { fun findOne(channelId: Long): GameSetup? { - return database.jooq() + return jooq .selectFrom(Tables.GAME_SETUP) .where(Tables.GAME_SETUP.CHANNEL_ID.eq(channelId)) .fetchOneInto(GameSetup::class.java) @@ -39,7 +39,7 @@ internal class GameSetupRepository( //this works since we dont commit the transaction fun findOneOrDefault(channelId: Long): GameSetup { - return database.jooq() + return jooq .insertInto(Tables.GAME_SETUP) .columns(Tables.GAME_SETUP.CHANNEL_ID) .values(channelId) @@ -50,7 +50,7 @@ internal class GameSetupRepository( } fun findAutoOutSetupsWhereUserIsInned(userId: Long): List { - return database.jooq() + return jooq .select( Tables.GAME_SETUP.CHANNEL_ID, Tables.GAME_SETUP.INNED_USERS, @@ -79,7 +79,7 @@ internal class GameSetupRepository( fun inUsers(channelId: Long, userIds: Collection): GameSetup { val userIdsArray = userIds.toTypedArray() - return database.jooq().transactionResult { config -> + return jooq.transactionResult { config -> config.dsl() .insertInto(Tables.GAME_SETUP) .columns(Tables.GAME_SETUP.CHANNEL_ID, Tables.GAME_SETUP.INNED_USERS) @@ -93,7 +93,7 @@ internal class GameSetupRepository( fun outUsers(channelId: Long, userIds: Collection): GameSetup { val userIdsArray = userIds.toTypedArray() - return database.jooq().transactionResult { config -> + return jooq.transactionResult { config -> config.dsl() .insertInto(Tables.GAME_SETUP) .columns(Tables.GAME_SETUP.CHANNEL_ID, Tables.GAME_SETUP.INNED_USERS) @@ -106,7 +106,7 @@ internal class GameSetupRepository( } fun delete(channelId: Long): Int { - return database.jooq().transactionResult { config -> + return jooq.transactionResult { config -> config.dsl() .deleteFrom(Tables.GAME_SETUP) .where(Tables.GAME_SETUP.CHANNEL_ID.eq(channelId)) @@ -115,7 +115,7 @@ internal class GameSetupRepository( } private fun set(channelId: Long, field: Field, value: F): GameSetup { - return database.jooq().transactionResult { config -> + return jooq.transactionResult { config -> config.dsl() .insertInto(Tables.GAME_SETUP) .columns(Tables.GAME_SETUP.CHANNEL_ID, field) diff --git a/src/main/java/space/npstr/wolfia/domain/staff/StaffCommand.java b/src/main/java/space/npstr/wolfia/domain/staff/StaffCommand.java index 3365ca55..f28b7b0b 100644 --- a/src/main/java/space/npstr/wolfia/domain/staff/StaffCommand.java +++ b/src/main/java/space/npstr/wolfia/domain/staff/StaffCommand.java @@ -27,6 +27,7 @@ import space.npstr.wolfia.domain.Command; import space.npstr.wolfia.domain.Conversation; import space.npstr.wolfia.system.EventWaiter; +import space.npstr.wolfia.system.metrics.MetricsService; import space.npstr.wolfia.utils.discord.Emojis; @Command @@ -38,13 +39,15 @@ public class StaffCommand implements BaseCommand, Conversation, PublicCommand { private final StaffService staffService; private final EventWaiter eventWaiter; + private final MetricsService metricsService; private final StaffProfileConversation staffProfileConversation; private final StaffRoleConversation staffRoleConversation; - public StaffCommand(StaffService staffService, EventWaiter eventWaiter) { + public StaffCommand(StaffService staffService, EventWaiter eventWaiter, MetricsService metricsService) { this.staffService = staffService; this.eventWaiter = eventWaiter; - this.staffProfileConversation = new StaffProfileConversation(staffService, eventWaiter); + this.metricsService = metricsService; + this.staffProfileConversation = new StaffProfileConversation(staffService, eventWaiter, metricsService); this.staffRoleConversation = new StaffRoleConversation(eventWaiter); } @@ -94,7 +97,7 @@ private boolean showConversationOptions(MessageContext context) { } private boolean optionSelected(MessageReceivedEvent event) { - MessageContext context = new MessageContext(event); + MessageContext context = new MessageContext(event, metricsService); String rawContent = context.getMessage().getContentRaw(); if (rawContent.toLowerCase().startsWith(OPTION_PROFILE)) { diff --git a/src/main/java/space/npstr/wolfia/domain/staff/StaffProfileConversation.java b/src/main/java/space/npstr/wolfia/domain/staff/StaffProfileConversation.java index 6a498721..75024065 100644 --- a/src/main/java/space/npstr/wolfia/domain/staff/StaffProfileConversation.java +++ b/src/main/java/space/npstr/wolfia/domain/staff/StaffProfileConversation.java @@ -28,6 +28,7 @@ import space.npstr.wolfia.commands.MessageContext; import space.npstr.wolfia.domain.Conversation; import space.npstr.wolfia.system.EventWaiter; +import space.npstr.wolfia.system.metrics.MetricsService; import space.npstr.wolfia.utils.discord.Emojis; /** @@ -48,10 +49,12 @@ class StaffProfileConversation implements Conversation { private final StaffService staffService; private final EventWaiter eventWaiter; + private final MetricsService metricsService; - StaffProfileConversation(StaffService staffService, EventWaiter eventWaiter) { + StaffProfileConversation(StaffService staffService, EventWaiter eventWaiter, MetricsService metricsService) { this.staffService = staffService; this.eventWaiter = eventWaiter; + this.metricsService = metricsService; } @Override @@ -124,7 +127,7 @@ private boolean show(MessageContext context, StaffMember staffMember, String pla } private boolean optionSelected(MessageReceivedEvent event, StaffMember staffMember) { - MessageContext context = new MessageContext(event); + MessageContext context = new MessageContext(event, metricsService); String rawContent = context.getMessage().getContentRaw(); if (rawContent.toLowerCase().startsWith(OPTION_ENABLE)) { @@ -172,7 +175,7 @@ private boolean optionSelected(MessageReceivedEvent event, StaffMember staffMemb } private boolean setSlogan(MessageReceivedEvent event, StaffMember staffMember) { - MessageContext context = new MessageContext(event); + MessageContext context = new MessageContext(event, metricsService); String slogan = context.getMessage().getContentRaw(); return setSlogan(context, slogan, staffMember); @@ -188,7 +191,7 @@ private boolean setSlogan(MessageContext context, String slogan, StaffMember sta } private boolean setLink(MessageReceivedEvent event, StaffMember staffMember) { - MessageContext context = new MessageContext(event); + MessageContext context = new MessageContext(event, metricsService); String link = context.getMessage().getContentRaw(); return setLink(context, link, staffMember); diff --git a/src/main/java/space/npstr/wolfia/domain/staff/StaffRepository.kt b/src/main/java/space/npstr/wolfia/domain/staff/StaffRepository.kt index d56b5b2d..b5b83faa 100644 --- a/src/main/java/space/npstr/wolfia/domain/staff/StaffRepository.kt +++ b/src/main/java/space/npstr/wolfia/domain/staff/StaffRepository.kt @@ -17,9 +17,9 @@ package space.npstr.wolfia.domain.staff import java.net.URI +import org.jooq.DSLContext import org.jooq.impl.DSL import org.springframework.stereotype.Repository -import space.npstr.wolfia.db.Database import space.npstr.wolfia.db.gen.Tables import space.npstr.wolfia.db.gen.enums.StaffFunction import space.npstr.wolfia.db.gen.tables.records.StaffMemberRecord @@ -29,24 +29,24 @@ import space.npstr.wolfia.db.gen.tables.records.StaffMemberRecord */ @Repository internal class StaffRepository( - private val database: Database, + private val jooq: DSLContext, ) { fun getStaffMember(userId: Long): StaffMemberRecord? { - return database.jooq() + return jooq .selectFrom(Tables.STAFF_MEMBER) .where(Tables.STAFF_MEMBER.USER_ID.eq(userId)) .fetchOne() } fun fetchAllStaffMembers(): List { - return database.jooq() + return jooq .selectFrom(Tables.STAFF_MEMBER) .fetch() } fun updateOrCreateStaffMemberFunction(userId: Long, staffFunction: StaffFunction): StaffMemberRecord { - return database.jooq().transactionResult { config -> + return jooq.transactionResult { config -> config.dsl() .insertInto(Tables.STAFF_MEMBER) .columns(Tables.STAFF_MEMBER.USER_ID, Tables.STAFF_MEMBER.FUNCTION) @@ -59,7 +59,7 @@ internal class StaffRepository( } fun updateSlogan(userId: Long, slogan: String?): StaffMemberRecord? { - return database.jooq().transactionResult { config -> + return jooq.transactionResult { config -> config.dsl() .update(Tables.STAFF_MEMBER) .set(Tables.STAFF_MEMBER.SLOGAN, slogan) @@ -70,7 +70,7 @@ internal class StaffRepository( } fun updateLink(userId: Long, link: URI?): StaffMemberRecord? { - return database.jooq().transactionResult { config -> + return jooq.transactionResult { config -> config.dsl() .update(Tables.STAFF_MEMBER) .set(Tables.STAFF_MEMBER.LINK, link) @@ -81,7 +81,7 @@ internal class StaffRepository( } fun updateEnabled(userId: Long, enabled: Boolean): StaffMemberRecord? { - return database.jooq().transactionResult { config -> + return jooq.transactionResult { config -> config.dsl() .update(Tables.STAFF_MEMBER) .set(Tables.STAFF_MEMBER.ENABLED, enabled) @@ -92,7 +92,7 @@ internal class StaffRepository( } fun updateAllActive(activeStaff: Collection) { - database.jooq().transaction { config -> + jooq.transaction { config -> config.dsl() .update(Tables.STAFF_MEMBER) .set(Tables.STAFF_MEMBER.ACTIVE, true) diff --git a/src/main/java/space/npstr/wolfia/domain/stats/StatsRepository.kt b/src/main/java/space/npstr/wolfia/domain/stats/StatsRepository.kt index d8b44e28..3a22262c 100644 --- a/src/main/java/space/npstr/wolfia/domain/stats/StatsRepository.kt +++ b/src/main/java/space/npstr/wolfia/domain/stats/StatsRepository.kt @@ -18,13 +18,12 @@ package space.npstr.wolfia.domain.stats import java.math.BigDecimal import java.time.Instant -import okio.use +import org.jooq.DSLContext import org.jooq.Record3 import org.jooq.Record8 import org.jooq.RecordMapper import org.jooq.impl.DSL import org.springframework.stereotype.Repository -import space.npstr.wolfia.db.Database import space.npstr.wolfia.db.gen.Tables import space.npstr.wolfia.db.gen.tables.records.StatsActionRecord import space.npstr.wolfia.db.gen.tables.records.StatsPlayerRecord @@ -37,16 +36,18 @@ import space.npstr.wolfia.game.definitions.Alignments import space.npstr.wolfia.game.definitions.Games import space.npstr.wolfia.game.definitions.Phase import space.npstr.wolfia.game.definitions.Roles -import space.npstr.wolfia.system.metrics.MetricsRegistry +import space.npstr.wolfia.system.metrics.MetricsService +import space.npstr.wolfia.system.metrics.time @Repository class StatsRepository internal constructor( - private val database: Database, + private val jooq: DSLContext, + private val metricsService: MetricsService, ) { fun fetchAveragePlayerSize(): BigDecimal { - return MetricsRegistry.queryTime.labels("getAveragePlayerSize").startTimer().use { - database.jooq() + return metricsService.queryTime("getAveragePlayerSize").time { + jooq .select(DSL.avg(Tables.STATS_GAME.PLAYER_SIZE)) .from(Tables.STATS_GAME) .fetchOne()?.component1() ?: BigDecimal.ZERO // SQL AVG may return null for empty sets @@ -54,8 +55,8 @@ class StatsRepository internal constructor( } fun fetchAveragePlayerSizeInGuild(guildId: Long): BigDecimal { - return MetricsRegistry.queryTime.labels("getAveragePlayerSizeInGuild").startTimer().use { - database.jooq() + return metricsService.queryTime("getAveragePlayerSizeInGuild").time { + jooq .select(DSL.avg(Tables.STATS_GAME.PLAYER_SIZE)) .from(Tables.STATS_GAME) .where(Tables.STATS_GAME.GUILD_ID.eq(guildId)) @@ -64,8 +65,8 @@ class StatsRepository internal constructor( } fun fetchDistinctPlayerSizes(): Set { - return MetricsRegistry.queryTime.labels("getDistinctPlayerSizes").startTimer().use { - database.jooq() + return metricsService.queryTime("getDistinctPlayerSizes").time { + jooq .selectDistinct(Tables.STATS_GAME.PLAYER_SIZE) .from(Tables.STATS_GAME) .fetch() @@ -74,8 +75,8 @@ class StatsRepository internal constructor( } fun fetchDistinctPlayerSizesInGuild(guildId: Long): Set { - return MetricsRegistry.queryTime.labels("getDistinctPlayerSizesInGuild").startTimer().use { - database.jooq() + return metricsService.queryTime("getDistinctPlayerSizesInGuild").time { + jooq .selectDistinct(Tables.STATS_GAME.PLAYER_SIZE) .from(Tables.STATS_GAME) .where(Tables.STATS_GAME.GUILD_ID.eq(guildId)) @@ -85,8 +86,8 @@ class StatsRepository internal constructor( } fun countAlignmentWins(alignment: Alignments): Int { - return MetricsRegistry.queryTime.labels("countAlignmentWins").startTimer().use { - database.jooq() + return metricsService.queryTime("countAlignmentWins").time { + jooq .select(DSL.count()) .from(Tables.STATS_GAME) .innerJoin(Tables.STATS_TEAM) @@ -100,8 +101,8 @@ class StatsRepository internal constructor( } fun countAlignmentWinsInGuild(alignment: Alignments, guildId: Long): Int { - return MetricsRegistry.queryTime.labels("countAlignmentWinsInGuild").startTimer().use { - database.jooq() + return metricsService.queryTime("countAlignmentWinsInGuild").time { + jooq .select(DSL.count()) .from(Tables.STATS_GAME) .innerJoin(Tables.STATS_TEAM) @@ -115,8 +116,8 @@ class StatsRepository internal constructor( } fun countAlignmentWinsForPlayerSize(alignment: Alignments, playerSize: Int): Int { - return MetricsRegistry.queryTime.labels("countAlignmentWinsForPlayerSize").startTimer().use { - database.jooq() + return metricsService.queryTime("countAlignmentWinsForPlayerSize").time { + jooq .select(DSL.count()) .from(Tables.STATS_GAME) .innerJoin(Tables.STATS_TEAM) @@ -130,8 +131,8 @@ class StatsRepository internal constructor( } fun countAlignmentWinsForPlayerSizeInGuild(alignment: Alignments, playerSize: Int, guildId: Long): Int { - return MetricsRegistry.queryTime.labels("countAlignmentWinsForPlayerSizeInGuild").startTimer().use { - database.jooq() + return metricsService.queryTime("countAlignmentWinsForPlayerSizeInGuild").time { + jooq .select(DSL.count()) .from(Tables.STATS_GAME) .innerJoin(Tables.STATS_TEAM) @@ -146,8 +147,8 @@ class StatsRepository internal constructor( } fun fetchGeneralUserStats(userId: Long): List { - return MetricsRegistry.queryTime.labels("getGeneralUserStats").startTimer().use { - database.jooq() + return metricsService.queryTime("getGeneralUserStats").time { + jooq .select( Tables.STATS_PLAYER.TOTAL_POSTLENGTH, Tables.STATS_PLAYER.TOTAL_POSTS, @@ -170,8 +171,8 @@ class StatsRepository internal constructor( } fun fetchUserShots(userId: Long): List { - return MetricsRegistry.queryTime.labels("getUserShots").startTimer().use { - database.jooq() + return metricsService.queryTime("getUserShots").time { + jooq .select(Tables.STATS_PLAYER.ALIGNMENT) .from(Tables.STATS_ACTION) .innerJoin(Tables.STATS_PLAYER).on(Tables.STATS_PLAYER.USER_ID.eq(Tables.STATS_ACTION.TARGET)) @@ -190,12 +191,12 @@ class StatsRepository internal constructor( } fun findGameStats(gameId: Long): GameStats? { - return MetricsRegistry.queryTime.labels("findGameStats").startTimer().use { - val dsl = database.jooq() + return metricsService.queryTime("findGameStats").time { + val dsl = jooq val gameRecord = dsl.selectFrom(Tables.STATS_GAME) .where(Tables.STATS_GAME.GAME_ID.eq(gameId)) .fetchOne() - ?: return@use null + ?: return@time null val teams = dsl.selectFrom(Tables.STATS_TEAM) .where(Tables.STATS_TEAM.GAME_ID.eq(gameId)) @@ -211,7 +212,7 @@ class StatsRepository internal constructor( .where(Tables.STATS_ACTION.GAME_ID.eq(gameId)) .fetch(actionMapper()) - return@use GameStats( + return@time GameStats( gameRecord.gameId, gameRecord.channelId, gameRecord.channelName, @@ -255,8 +256,8 @@ class StatsRepository internal constructor( } fun insertGameStats(insertGameStats: InsertGameStats): GameStats { - return MetricsRegistry.queryTime.labels("insertGameStats").startTimer().use { - database.jooq().transactionResult { config -> + return metricsService.queryTime("insertGameStats").time { + jooq.transactionResult { config -> val context = config.dsl() val gameId = context .insertInto(Tables.STATS_GAME) @@ -322,8 +323,8 @@ class StatsRepository internal constructor( } fun fetchAllGameStatsOfUser(userId: Long): List { - return MetricsRegistry.queryTime.labels("getAllGameStatsOfUser").startTimer().use { - database.jooq() + return metricsService.queryTime("getAllGameStatsOfUser").time { + jooq .select( Tables.STATS_GAME.GAME_ID, Tables.STATS_GAME.START_TIME, @@ -358,8 +359,8 @@ class StatsRepository internal constructor( } fun fetchAllActionStatsOfUser(userId: Long): Map> { - return MetricsRegistry.queryTime.labels("getAllActionStatsOfUser").startTimer().use { - database.jooq() + return metricsService.queryTime("getAllActionStatsOfUser").time { + jooq .select( Tables.STATS_GAME.GAME_ID, Tables.STATS_ACTION.ACTION_TYPE, @@ -382,8 +383,8 @@ class StatsRepository internal constructor( } fun nullAllPlayerNicknamesofUser(userId: Long): Int { - return MetricsRegistry.queryTime.labels("nullAllPlayerNicknamesofUser").startTimer().use { - database.jooq().transactionResult { config -> + return metricsService.queryTime("nullAllPlayerNicknamesofUser").time { + jooq.transactionResult { config -> config.dsl() .update(Tables.STATS_PLAYER) .set(Tables.STATS_PLAYER.NICKNAME, DSL.`val`(null, Tables.STATS_PLAYER.NICKNAME)) diff --git a/src/main/java/space/npstr/wolfia/game/Game.java b/src/main/java/space/npstr/wolfia/game/Game.java index 38920928..cfcdf8a0 100644 --- a/src/main/java/space/npstr/wolfia/game/Game.java +++ b/src/main/java/space/npstr/wolfia/game/Game.java @@ -64,7 +64,6 @@ import space.npstr.wolfia.game.exceptions.IllegalGameStateException; import space.npstr.wolfia.game.tools.ExceptionLoggingExecutor; import space.npstr.wolfia.game.tools.NiceEmbedBuilder; -import space.npstr.wolfia.system.metrics.MetricsRegistry; import space.npstr.wolfia.utils.UserFriendlyException; import space.npstr.wolfia.utils.discord.RestActions; import space.npstr.wolfia.utils.discord.RoleAndPermissionUtils; @@ -668,9 +667,11 @@ protected boolean isGameOver(boolean... wwFlair) { .findFirst() .ifPresent(t -> t.setWinner(true)); } - MetricsRegistry.gamesPlayed - .labels(this.insertGameStats.getGameType().name(), this.insertGameStats.getGameMode().name()) - .inc(); + resources.getMetricsService().gamesPlayed( + this.insertGameStats.getGameType(), + this.insertGameStats.getGameMode() + ) + .increment(); try { this.gameStats = resources.getStatsService().recordGameStats(this.insertGameStats); diff --git a/src/main/java/space/npstr/wolfia/game/GameResources.java b/src/main/java/space/npstr/wolfia/game/GameResources.java index e56a768d..791b59b2 100644 --- a/src/main/java/space/npstr/wolfia/game/GameResources.java +++ b/src/main/java/space/npstr/wolfia/game/GameResources.java @@ -27,6 +27,7 @@ import space.npstr.wolfia.domain.settings.ChannelSettingsService; import space.npstr.wolfia.domain.stats.StatsService; import space.npstr.wolfia.game.tools.ExceptionLoggingExecutor; +import space.npstr.wolfia.system.metrics.MetricsService; /** * Bundle a bunch of injected dependencies for games. @@ -43,10 +44,12 @@ public class GameResources { private final StatsService statsService; private final GameRegistry gameRegistry; private final OAuth2Service oAuth2Service; + private final MetricsService metricsService; public GameResources(WolfiaConfig wolfiaConfig, PrivateRoomQueue privateRoomQueue, ExceptionLoggingExecutor executor, ShardManager shardManager, ChannelSettingsService channelSettingsService, UserCache userCache, - StatsService statsService, GameRegistry gameRegistry, OAuth2Service oAuth2Service) { + StatsService statsService, GameRegistry gameRegistry, OAuth2Service oAuth2Service, + MetricsService metricsService) { this.wolfiaConfig = wolfiaConfig; this.privateRoomQueue = privateRoomQueue; @@ -57,6 +60,7 @@ public GameResources(WolfiaConfig wolfiaConfig, PrivateRoomQueue privateRoomQueu this.statsService = statsService; this.gameRegistry = gameRegistry; this.oAuth2Service = oAuth2Service; + this.metricsService = metricsService; } public WolfiaConfig getWolfiaConfig() { @@ -94,4 +98,8 @@ public GameRegistry getGameRegistry() { public OAuth2Service getoAuth2Service() { return this.oAuth2Service; } + + public MetricsService getMetricsService() { + return metricsService; + } } diff --git a/src/main/java/space/npstr/wolfia/system/metrics/MetricsExtensions.kt b/src/main/java/space/npstr/wolfia/system/metrics/MetricsExtensions.kt new file mode 100644 index 00000000..a17c95ac --- /dev/null +++ b/src/main/java/space/npstr/wolfia/system/metrics/MetricsExtensions.kt @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2016-2024 the original author or authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package space.npstr.wolfia.system.metrics + +import io.micrometer.core.instrument.Timer + +fun Timer.time(block: () -> T): T { + return Timer.start().let { + try { + block.invoke() + } finally { + it.stop(this) + } + } +} diff --git a/src/main/java/space/npstr/wolfia/system/metrics/MetricsRegistry.java b/src/main/java/space/npstr/wolfia/system/metrics/MetricsRegistry.java deleted file mode 100644 index 33256000..00000000 --- a/src/main/java/space/npstr/wolfia/system/metrics/MetricsRegistry.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2016-2023 the original author or authors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package space.npstr.wolfia.system.metrics; - -import ch.qos.logback.classic.LoggerContext; -import io.prometheus.client.CollectorRegistry; -import io.prometheus.client.Counter; -import io.prometheus.client.Gauge; -import io.prometheus.client.Summary; -import io.prometheus.client.hotspot.DefaultExports; -import io.prometheus.client.logback.InstrumentedAppender; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; -import space.npstr.prometheus_extensions.QueryCountCollector; -import space.npstr.prometheus_extensions.ThreadPoolCollector; - -/** - * Initializes and registers various metrics collectors - */ -@Component -public class MetricsRegistry { - - public MetricsRegistry(InstrumentedAppender prometheusAppender, ThreadPoolCollector poolMetrics, - QueryCountCollector queryMetrics) { - //log metrics - LoggerContext factory = (LoggerContext) LoggerFactory.getILoggerFactory(); - ch.qos.logback.classic.Logger root = factory.getLogger(Logger.ROOT_LOGGER_NAME); - prometheusAppender.setContext(root.getLoggerContext()); - prometheusAppender.start(); - root.addAppender(prometheusAppender); - - //jvm (hotspot) metrics - DefaultExports.initialize(); - - poolMetrics.register(); - queryMetrics.register(); - } - - public CollectorRegistry getRegistry() { - return CollectorRegistry.defaultRegistry; - } - - public static final Summary queryTime = Summary.build() - .name("query_time_seconds") - .help("Time queries take") - .labelNames("name") //identifier of the query, for example "activeUsers" - .register(); - - public static final Counter gamesPlayed = Counter.build() - .name("games_played_total") - .help("Games Played") - .labelNames("type", "mode") - .register(); - - public static final Summary commandRetentionTime = Summary.build() - .name("command_retention_seconds") - .help("Time it takes from receiving a command till processing is started") - .register(); - - public static final Summary commandProcessTime = Summary.build() - .name("command_process_seconds") - .help("Time the pure processing takes") - .labelNames("command") //simple class name of the command - .register(); - - /** - * basically measurement of discord latency, however, ratelimiting by the library is not accounted for (getting - * ratelimited in a channel happens rather fast when users spam) - */ - public static final Summary commandResponseTime = Summary.build() - .name("command_response_seconds") - .help("Time it takes from replying till the user actually receives the answer") - .register(); - - public static final Summary commandTotalTime = Summary.build() - .name("command_total_seconds") - .help("Total time it takes from discord creation timestamp of the trigger message till" - + " discord creation timestamp of the answer message") - .register(); - - public static final Gauge availablePrivateRooms = Gauge.build() - .name("private_rooms_available") - .help("Amount of available private rooms") - .register(); -} diff --git a/src/main/java/space/npstr/wolfia/system/metrics/MetricsService.java b/src/main/java/space/npstr/wolfia/system/metrics/MetricsService.java new file mode 100644 index 00000000..ffb0857e --- /dev/null +++ b/src/main/java/space/npstr/wolfia/system/metrics/MetricsService.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2016-2023 the original author or authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package space.npstr.wolfia.system.metrics; + +import io.micrometer.core.instrument.Counter; +import io.micrometer.core.instrument.Gauge; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Tags; +import io.micrometer.core.instrument.Timer; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; +import org.springframework.stereotype.Service; +import space.npstr.wolfia.game.GameInfo; +import space.npstr.wolfia.game.definitions.Games; + +/** + * Initializes and registers various metrics collectors + */ +@Service +public class MetricsService { + + private final MeterRegistry meterRegistry; + + private final Map> cache = new ConcurrentHashMap<>(); + + public MetricsService(MeterRegistry meterRegistry) { + this.meterRegistry = meterRegistry; + } + + private AtomicInteger gauge(String name, Tags tags, Consumer> registrar) { + return cache + .computeIfAbsent(name, __ -> new ConcurrentHashMap<>()) + .computeIfAbsent(tags, __ -> { + AtomicInteger atomicInteger = new AtomicInteger(); + registrar.accept(Gauge.builder(name, atomicInteger, AtomicInteger::get).tags(tags)); + return atomicInteger; + }); + } + + public Timer queryTime(String name) { + return Timer.builder("query.time") + .description("Time queries take") + .tag("name", name) //identifier of the query, for example "activeUsers" + .register(meterRegistry); + } + + public Counter gamesPlayed(Games type, GameInfo.GameMode mode) { + return Counter.builder("games.played") + .description("Games Played") + .tag("type", type.name()) + .tag("mode", mode.name()) + .register(meterRegistry); + } + + public Timer commandRetentionTime() { + return Timer.builder("command.retention") + .description("Time it takes from receiving a command till processing is started") + .register(meterRegistry); + } + + public Timer commandProcessTime(String command) { + return Timer.builder("command.process") + .description("Time the pure processing takes") + .tag("command", command) //simple class name of the command + .register(meterRegistry); + } + + /** + * basically measurement of discord latency, however, ratelimiting by the library is not accounted for (getting + * ratelimited in a channel happens rather fast when users spam) + */ + public Timer commandResponseTime() { + return Timer.builder("command.response") + .description("Time it takes from replying till the user actually receives the answer") + .register(meterRegistry); + } + + public Timer commandTotalTime() { + return Timer.builder("command.total.time") + .description("Total time it takes from discord creation timestamp of the trigger message till" + + " discord creation timestamp of the answer message") + .register(meterRegistry); + } + + public AtomicInteger availablePrivateRooms() { + return gauge("private.rooms.available", Tags.empty(), builder -> builder + .description("Amount of available private rooms") + .register(meterRegistry) + ); + } +} diff --git a/src/main/java/space/npstr/wolfia/webapi/MetricsEndpoint.kt b/src/main/java/space/npstr/wolfia/webapi/MetricsEndpoint.kt deleted file mode 100644 index 69f14f6d..00000000 --- a/src/main/java/space/npstr/wolfia/webapi/MetricsEndpoint.kt +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2016-2023 the original author or authors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package space.npstr.wolfia.webapi - -import io.prometheus.client.CollectorRegistry -import io.prometheus.client.exporter.common.TextFormat -import jakarta.servlet.http.HttpServletRequest -import java.io.StringWriter -import java.io.Writer -import org.springframework.http.HttpHeaders -import org.springframework.http.HttpStatus -import org.springframework.http.ResponseEntity -import org.springframework.web.bind.annotation.GetMapping -import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.bind.annotation.RequestParam -import org.springframework.web.bind.annotation.RestController -import space.npstr.wolfia.system.logger -import space.npstr.wolfia.system.metrics.MetricsRegistry - -/** - * Expose Prometheus metrics. Some code copied from Prometheus' own MetricsServlet. - */ -@RestController -@RequestMapping("/metrics") -class MetricsEndpoint( - metricsRegistry: MetricsRegistry, -) { - - private val registry: CollectorRegistry = metricsRegistry.registry - - @GetMapping(produces = [TextFormat.CONTENT_TYPE_004]) - fun getMetrics( - @RequestParam(name = "name[]", required = false) includedParam: Array?, - ): ResponseEntity { - - return try { - ResponseEntity(buildAnswer(includedParam), HttpStatus.OK) - } catch (e: Exception) { - logger().error("Wait what, metrics endpoint blew up", e) - ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR) - } - } - - @RequestMapping("**") - fun catchAll(request: HttpServletRequest): ResponseEntity { - val method = request.method - val path = request.servletPath - val acceptHeaders = Iterable { request.getHeaders(HttpHeaders.ACCEPT).asIterator() } - val acceptableMediaTypes = java.lang.String.join(", ", acceptHeaders) - val contentType = request.getHeader(HttpHeaders.CONTENT_TYPE) - logger().info( - "Catch all triggered: {} {} {}: {} {}: {}", - method, path, HttpHeaders.ACCEPT, acceptableMediaTypes, HttpHeaders.CONTENT_TYPE, contentType, - ) - return ResponseEntity.notFound().build() - } - - private fun buildAnswer(includedParam: Array?): String { - val params = includedParam?.let { setOf(*it) } ?: emptySet() - val writer: Writer = StringWriter() - writer.use { - TextFormat.write004(writer, registry.filteredMetricFamilySamples(params)) - writer.flush() - } - return writer.toString() - } -} diff --git a/src/main/resources/db/migrations/V10__StaffMember.sql b/src/main/resources/db/migration/V10__StaffMember.sql similarity index 100% rename from src/main/resources/db/migrations/V10__StaffMember.sql rename to src/main/resources/db/migration/V10__StaffMember.sql diff --git a/src/main/resources/db/migrations/V11__OAuth2Scope_Guilds.sql b/src/main/resources/db/migration/V11__OAuth2Scope_Guilds.sql similarity index 100% rename from src/main/resources/db/migrations/V11__OAuth2Scope_Guilds.sql rename to src/main/resources/db/migration/V11__OAuth2Scope_Guilds.sql diff --git a/src/main/resources/db/migrations/V12__GameChannels.sql b/src/main/resources/db/migration/V12__GameChannels.sql similarity index 100% rename from src/main/resources/db/migrations/V12__GameChannels.sql rename to src/main/resources/db/migration/V12__GameChannels.sql diff --git a/src/main/resources/db/migrations/V13__DiscordUser.sql b/src/main/resources/db/migration/V13__DiscordUser.sql similarity index 100% rename from src/main/resources/db/migrations/V13__DiscordUser.sql rename to src/main/resources/db/migration/V13__DiscordUser.sql diff --git a/src/main/resources/db/migrations/V1__Initial.sql b/src/main/resources/db/migration/V1__Initial.sql similarity index 100% rename from src/main/resources/db/migrations/V1__Initial.sql rename to src/main/resources/db/migration/V1__Initial.sql diff --git a/src/main/resources/db/migrations/V2__AppendArrayDistinct.sql b/src/main/resources/db/migration/V2__AppendArrayDistinct.sql similarity index 100% rename from src/main/resources/db/migrations/V2__AppendArrayDistinct.sql rename to src/main/resources/db/migration/V2__AppendArrayDistinct.sql diff --git a/src/main/resources/db/migrations/V3__GuildSettings.sql b/src/main/resources/db/migration/V3__GuildSettings.sql similarity index 100% rename from src/main/resources/db/migrations/V3__GuildSettings.sql rename to src/main/resources/db/migration/V3__GuildSettings.sql diff --git a/src/main/resources/db/migrations/V4__Drop_CachedUser.sql b/src/main/resources/db/migration/V4__Drop_CachedUser.sql similarity index 100% rename from src/main/resources/db/migrations/V4__Drop_CachedUser.sql rename to src/main/resources/db/migration/V4__Drop_CachedUser.sql diff --git a/src/main/resources/db/migrations/V5__Nullable_Settings.sql b/src/main/resources/db/migration/V5__Nullable_Settings.sql similarity index 100% rename from src/main/resources/db/migrations/V5__Nullable_Settings.sql rename to src/main/resources/db/migration/V5__Nullable_Settings.sql diff --git a/src/main/resources/db/migrations/V6__GameSetup.sql b/src/main/resources/db/migration/V6__GameSetup.sql similarity index 100% rename from src/main/resources/db/migrations/V6__GameSetup.sql rename to src/main/resources/db/migration/V6__GameSetup.sql diff --git a/src/main/resources/db/migrations/V7__PrivateRooms.sql b/src/main/resources/db/migration/V7__PrivateRooms.sql similarity index 100% rename from src/main/resources/db/migrations/V7__PrivateRooms.sql rename to src/main/resources/db/migration/V7__PrivateRooms.sql diff --git a/src/main/resources/db/migrations/V8__Oauth2.sql b/src/main/resources/db/migration/V8__Oauth2.sql similarity index 100% rename from src/main/resources/db/migrations/V8__Oauth2.sql rename to src/main/resources/db/migration/V8__Oauth2.sql diff --git a/src/main/resources/db/migrations/V9__AutoOut.sql b/src/main/resources/db/migration/V9__AutoOut.sql similarity index 100% rename from src/main/resources/db/migrations/V9__AutoOut.sql rename to src/main/resources/db/migration/V9__AutoOut.sql diff --git a/src/main/resources/wolfia.yaml b/src/main/resources/wolfia.yaml index 316bb3a9..f01ce0fb 100644 --- a/src/main/resources/wolfia.yaml +++ b/src/main/resources/wolfia.yaml @@ -5,9 +5,6 @@ wolfia: debug: true # Some things are different. Set to false to properly run the bot. -database: - jdbc-url: "jdbc:postgresql://localhost:5442/wolfia?user=wolfia&password=wolfia" # From the docker/dev/docker-compose file - oauth2: base-redirect-url: "/" # URL that should be redirected to after a successful authentication (usually the root). @@ -53,6 +50,20 @@ spring: data: redis: url: "redis://localhost:6389/0" + datasource: + # From the docker/dev/docker-compose file + url: "jdbc:postgresql://localhost:5442/wolfia?user=wolfia&password=wolfia" + hikari: + maximum-pool-size: 8 + validation-timeout: 3000 + # 30 seconds, sometimes we time out after 10 on the new machine, but its not a leak. + connection-timeout: 30_000 + auto-commit: false + pool-name: "postgres-DefaultPool" + data-source-properties: + # allow postgres to cast strings (varchars) more freely to actual column types + # source https://jdbc.postgresql.org/documentation/head/connect.html + stringtype: "unspecified" togglz: enabled: true @@ -85,3 +96,25 @@ sentry: - "dev.capybaralabs" logging: minimum-event-level: warn + +management: + prometheus: + metrics: + export: + enabled: true + endpoint: + health: + enabled: true + show-details: always + prometheus: + enabled: true + endpoints: + enabled-by-default: false + web: + exposure: + include: + - health + - prometheus + base-path: / + path-mapping: + prometheus: metrics diff --git a/src/test/java/space/npstr/wolfia/ApplicationTest.java b/src/test/java/space/npstr/wolfia/ApplicationTest.java index 1739513c..78c9f2ef 100644 --- a/src/test/java/space/npstr/wolfia/ApplicationTest.java +++ b/src/test/java/space/npstr/wolfia/ApplicationTest.java @@ -17,10 +17,8 @@ package space.npstr.wolfia; -import io.prometheus.client.CollectorRegistry; import java.time.Clock; import net.dv8tion.jda.api.sharding.ShardManager; -import org.junit.jupiter.api.AfterAll; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; @@ -75,13 +73,4 @@ public abstract class ApplicationTest extends PostgresAndRedisContainers { @Autowired protected TestRestTemplate restTemplate; - - /** - * Some static metrics are giving trouble when the application context is restarted between tests. - */ - @AfterAll - static void clearCollectorRegistry() { - CollectorRegistry.defaultRegistry.clear(); - } - } diff --git a/src/test/java/space/npstr/wolfia/LauncherTest.java b/src/test/java/space/npstr/wolfia/LauncherTest.java index 7b1a535f..6f66e4d8 100644 --- a/src/test/java/space/npstr/wolfia/LauncherTest.java +++ b/src/test/java/space/npstr/wolfia/LauncherTest.java @@ -26,7 +26,6 @@ import space.npstr.prometheus_extensions.jda.JdaMetrics; import space.npstr.wolfia.commands.CommRegistry; import space.npstr.wolfia.commands.CommandHandler; -import space.npstr.wolfia.db.Database; import space.npstr.wolfia.domain.oauth2.OAuth2Refresher; import space.npstr.wolfia.domain.setup.lastactive.AutoOuter; import space.npstr.wolfia.game.GameResources; @@ -57,7 +56,6 @@ void applicationContextLoads() { assertThatContainsBean("commRegistry", CommRegistry.class); assertThatContainsBean("shardManager", ShardManager.class); assertThatContainsBean("gameResources", GameResources.class); - assertThatContainsBean("database", Database.class); assertThatContainsBean("shutdownHandler", ShutdownHandler.class); assertThatContainsBean("jdaMetrics", JdaMetrics.class); assertThatContainsBean("OAuth2Refresher", OAuth2Refresher.class); diff --git a/src/test/java/space/npstr/wolfia/PostgresAndRedisContainers.java b/src/test/java/space/npstr/wolfia/PostgresAndRedisContainers.java index 22641eb7..d1836738 100644 --- a/src/test/java/space/npstr/wolfia/PostgresAndRedisContainers.java +++ b/src/test/java/space/npstr/wolfia/PostgresAndRedisContainers.java @@ -46,7 +46,7 @@ public abstract class PostgresAndRedisContainers { String host = DB.getHost(); int port = DB.getMappedPort(5432); String jdbcUrl = "jdbc:postgresql://" + host + ":" + port + "/wolfia_test?user=wolfia_test"; - System.setProperty("database.jdbcUrl", jdbcUrl); + System.setProperty("spring.datasource.url", jdbcUrl); } diff --git a/src/test/java/space/npstr/wolfia/domain/ban/BanServiceTest.java b/src/test/java/space/npstr/wolfia/domain/ban/BanServiceTest.java index d5d8c522..93b9ca35 100644 --- a/src/test/java/space/npstr/wolfia/domain/ban/BanServiceTest.java +++ b/src/test/java/space/npstr/wolfia/domain/ban/BanServiceTest.java @@ -20,11 +20,11 @@ import java.util.List; import java.util.function.Consumer; +import org.jooq.DSLContext; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import space.npstr.wolfia.ApplicationTest; -import space.npstr.wolfia.db.Database; import static org.assertj.core.api.Assertions.assertThat; import static space.npstr.wolfia.TestUtil.uniqueLong; @@ -36,12 +36,12 @@ class BanServiceTest extends ApplicationTest { private BanService banService; @Autowired - private Database database; + private DSLContext jooq; @BeforeEach void setup() { - this.database.jooq().transactionResult(config -> config.dsl() + this.jooq.transactionResult(config -> config.dsl() .deleteFrom(DISCORD_USER) .execute() ); diff --git a/src/test/java/space/npstr/wolfia/domain/oauth2/AuthStateCacheTest.java b/src/test/java/space/npstr/wolfia/domain/oauth2/AuthStateCacheTest.java index 4f1d5b6a..fea92489 100644 --- a/src/test/java/space/npstr/wolfia/domain/oauth2/AuthStateCacheTest.java +++ b/src/test/java/space/npstr/wolfia/domain/oauth2/AuthStateCacheTest.java @@ -17,7 +17,7 @@ package space.npstr.wolfia.domain.oauth2; -import io.prometheus.client.cache.caffeine.CacheMetricsCollector; +import io.prometheus.metrics.instrumentation.caffeine.CacheMetricsCollector; import java.util.Optional; import org.junit.jupiter.api.Test; diff --git a/src/test/java/space/npstr/wolfia/domain/oauth2/OAuth2RepositoryTest.java b/src/test/java/space/npstr/wolfia/domain/oauth2/OAuth2RepositoryTest.java index 0067f063..49ae32f4 100644 --- a/src/test/java/space/npstr/wolfia/domain/oauth2/OAuth2RepositoryTest.java +++ b/src/test/java/space/npstr/wolfia/domain/oauth2/OAuth2RepositoryTest.java @@ -24,12 +24,12 @@ import java.util.List; import java.util.Set; import java.util.function.Consumer; +import org.jooq.DSLContext; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import space.npstr.wolfia.ApplicationTest; -import space.npstr.wolfia.db.Database; import space.npstr.wolfia.db.type.OAuth2Scope; import static java.time.OffsetDateTime.now; @@ -54,12 +54,12 @@ public static Consumer isOAuth2Data(OAuth2Data data) { private OAuth2Repository repository; @Autowired - private Database database; + private DSLContext jooq; @BeforeEach @AfterEach void cleanDbTable() { - this.database.jooq().transactionResult(config -> config.dsl() + this.jooq.transactionResult(config -> config.dsl() .deleteFrom(OAUTH2) .execute() ); diff --git a/src/test/java/space/npstr/wolfia/domain/room/PrivateRoomQueueTest.java b/src/test/java/space/npstr/wolfia/domain/room/PrivateRoomQueueTest.java index 727ce97e..27681576 100644 --- a/src/test/java/space/npstr/wolfia/domain/room/PrivateRoomQueueTest.java +++ b/src/test/java/space/npstr/wolfia/domain/room/PrivateRoomQueueTest.java @@ -27,6 +27,7 @@ import org.junit.jupiter.api.Timeout; import org.springframework.beans.factory.annotation.Autowired; import space.npstr.wolfia.ApplicationTest; +import space.npstr.wolfia.system.metrics.MetricsService; import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Durations.ONE_HUNDRED_MILLISECONDS; @@ -45,6 +46,9 @@ class PrivateRoomQueueTest extends ApplicationTest { @Autowired private ShardManager shardManager; + @Autowired + private MetricsService metricsService; + @Test void queueShouldInitializeFromService() { PrivateRoomService service = mock(PrivateRoomService.class); @@ -52,7 +56,7 @@ void queueShouldInitializeFromService() { PrivateRoom privateRoom2 = new PrivateRoom(uniqueLong(), 1); when(service.findAll()).thenReturn(List.of(privateRoom1, privateRoom2)); - var queue = new PrivateRoomQueue(shardManager, service); + var queue = new PrivateRoomQueue(shardManager, metricsService, service); verify(service).findAll(); List rooms = queue.getAllManagedRooms(); diff --git a/src/test/java/space/npstr/wolfia/domain/room/PrivateRoomRepositoryTest.java b/src/test/java/space/npstr/wolfia/domain/room/PrivateRoomRepositoryTest.java index 2c55ab44..87ce7f9c 100644 --- a/src/test/java/space/npstr/wolfia/domain/room/PrivateRoomRepositoryTest.java +++ b/src/test/java/space/npstr/wolfia/domain/room/PrivateRoomRepositoryTest.java @@ -17,12 +17,12 @@ package space.npstr.wolfia.domain.room; +import org.jooq.DSLContext; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import space.npstr.wolfia.ApplicationTest; -import space.npstr.wolfia.db.Database; import static org.assertj.core.api.Assertions.assertThat; import static space.npstr.wolfia.TestUtil.uniqueLong; @@ -34,12 +34,12 @@ class PrivateRoomRepositoryTest extends ApplicationTest { private PrivateRoomRepository repository; @Autowired - private Database database; + private DSLContext jooq; @BeforeEach @AfterEach void cleanDbTable() { - this.database.jooq().transactionResult(config -> config.dsl() + this.jooq.transactionResult(config -> config.dsl() .deleteFrom(PRIVATE_ROOM) .execute() ); @@ -146,7 +146,7 @@ private void insertAndVerify(int expectedNumber) { private long preparePrivateRoom(int number) { long guildId = uniqueLong(); - this.database.jooq().transactionResult(config -> config.dsl() + this.jooq.transactionResult(config -> config.dsl() .insertInto(PRIVATE_ROOM) .columns(PRIVATE_ROOM.GUILD_ID, PRIVATE_ROOM.NR) .values(guildId, number) diff --git a/src/test/java/space/npstr/wolfia/domain/room/PrivateRoomServiceTest.java b/src/test/java/space/npstr/wolfia/domain/room/PrivateRoomServiceTest.java index b179d7cd..883e38ac 100644 --- a/src/test/java/space/npstr/wolfia/domain/room/PrivateRoomServiceTest.java +++ b/src/test/java/space/npstr/wolfia/domain/room/PrivateRoomServiceTest.java @@ -20,12 +20,12 @@ import java.util.List; import java.util.Optional; import java.util.function.Consumer; +import org.jooq.DSLContext; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import space.npstr.wolfia.ApplicationTest; -import space.npstr.wolfia.db.Database; import static org.assertj.core.api.Assertions.assertThat; import static space.npstr.wolfia.TestUtil.uniqueLong; @@ -40,12 +40,12 @@ class PrivateRoomServiceTest extends ApplicationTest { private PrivateRoomRepository repository; @Autowired - private Database database; + private DSLContext jooq; @BeforeEach @AfterEach void cleanDbTable() { - this.database.jooq().transactionResult(config -> config.dsl() + this.jooq.transactionResult(config -> config.dsl() .deleteFrom(PRIVATE_ROOM) .execute() ); diff --git a/src/test/java/space/npstr/wolfia/domain/staff/StaffRepositoryTest.java b/src/test/java/space/npstr/wolfia/domain/staff/StaffRepositoryTest.java index 247cb09e..7c2a99e1 100644 --- a/src/test/java/space/npstr/wolfia/domain/staff/StaffRepositoryTest.java +++ b/src/test/java/space/npstr/wolfia/domain/staff/StaffRepositoryTest.java @@ -20,10 +20,10 @@ import java.net.URI; import java.util.Collections; import java.util.List; +import org.jooq.DSLContext; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import space.npstr.wolfia.ApplicationTest; -import space.npstr.wolfia.db.Database; import space.npstr.wolfia.db.gen.enums.StaffFunction; import space.npstr.wolfia.db.gen.tables.records.StaffMemberRecord; @@ -37,7 +37,7 @@ class StaffRepositoryTest extends ApplicationTest { private StaffRepository repo; @Autowired - private Database database; + private DSLContext jooq; @Test @@ -62,7 +62,7 @@ void givenExistingRecord_whenGetStaffMember_returnExistingRecord() { @Test void givenNoRecords_whenFetchAllStaffMembers_shouldBeEmpty() { - database.jooq().transactionResult(config -> config.dsl() + jooq.transactionResult(config -> config.dsl() .deleteFrom(STAFF_MEMBER) .execute() ); @@ -75,7 +75,7 @@ void givenNoRecords_whenFetchAllStaffMembers_shouldBeEmpty() { @Test void givenSomeRecords_whenFetchAllStaffMembers_shoulContainRecords() { - database.jooq().transactionResult(config -> config.dsl() + jooq.transactionResult(config -> config.dsl() .deleteFrom(STAFF_MEMBER) .execute() ); diff --git a/src/test/java/space/npstr/wolfia/domain/staff/StaffServiceTest.java b/src/test/java/space/npstr/wolfia/domain/staff/StaffServiceTest.java index d3998a9a..1ba34412 100644 --- a/src/test/java/space/npstr/wolfia/domain/staff/StaffServiceTest.java +++ b/src/test/java/space/npstr/wolfia/domain/staff/StaffServiceTest.java @@ -26,12 +26,12 @@ import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.sharding.ShardManager; +import org.jooq.DSLContext; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import space.npstr.wolfia.App; import space.npstr.wolfia.ApplicationTest; -import space.npstr.wolfia.db.Database; import space.npstr.wolfia.db.gen.enums.StaffFunction; import space.npstr.wolfia.domain.UserCache; @@ -46,7 +46,7 @@ class StaffServiceTest extends ApplicationTest { @Autowired - private Database database; + private DSLContext jooq; @Autowired private StaffService staffService; @@ -63,7 +63,7 @@ class StaffServiceTest extends ApplicationTest { @BeforeEach void setup() { - this.database.jooq().transactionResult(config -> config.dsl() + this.jooq.transactionResult(config -> config.dsl() .deleteFrom(STAFF_MEMBER) .execute() ); diff --git a/src/test/resources/wolfia-test.yaml b/src/test/resources/wolfia-test.yaml index 2574739b..5b5da9bd 100644 --- a/src/test/resources/wolfia-test.yaml +++ b/src/test/resources/wolfia-test.yaml @@ -1,4 +1,8 @@ spring: + flyway: + # Togglz creates its repos before Flyway has had a chance to run + baseline-on-migrate: true + baseline-version: 0 security: oauth2: client: diff --git a/wolfia-secrets.example.yaml b/wolfia-secrets.example.yaml index 3b30f8a7..8d54430c 100644 --- a/wolfia-secrets.example.yaml +++ b/wolfia-secrets.example.yaml @@ -4,8 +4,6 @@ wolfia: discordToken: "" # Discord bot token. From Discord's Developer console: https://discord.com/developers/applications. Make sure to enable the Server Members intent: https://cdn.discordapp.com/attachments/439855192763269135/816787436440911872/unknown.png #botstatus-webhook: "" # Webhook url to post the bot status in. Optional. -#database.jdbcUrl: "" # Postgres database url. Only needs to be set when NOT running with the docker/dev/docker-compose file. - oauth2: clientId: "" # From Discord's Developer console: https://discord.com/developers/applications clientSecret: "" # From Discord's Developer console: https://discord.com/developers/applications @@ -14,7 +12,8 @@ oauth2: sentry.dsn: "" # Error aggregation service. See https://sentry.io spring: - #redis.url: "" # Redis database url. Only needs to be set when NOT running with the docker/dev/docker-compose file. + #datasource.url: "" # Postgres database url. Only needs to be set when NOT running with the docker/dev/docker-compose file. + #data.redis.url: "" # Redis database url. Only needs to be set when NOT running with the docker/dev/docker-compose file. security: oauth2: client: