diff --git a/jdbc/hibernate-slo/Dockerfile b/jdbc/hibernate-slo/Dockerfile new file mode 100644 index 0000000..57b2153 --- /dev/null +++ b/jdbc/hibernate-slo/Dockerfile @@ -0,0 +1,11 @@ +FROM maven:3.8.4-openjdk-17 AS build +WORKDIR /app +COPY pom.xml . +RUN mvn dependency:resolve +COPY src ./src +RUN mvn package -DskipTests + +FROM openjdk:17 AS run +WORKDIR /app +COPY --from=build /app/target/hibernate-slo-1.1.0-SNAPSHOT.jar /app/app.jar +ENTRYPOINT ["java", "-jar", "app.jar"] \ No newline at end of file diff --git a/jdbc/hibernate-slo/configs/grafana/provisioning/dashboards/dashboard.yml b/jdbc/hibernate-slo/configs/grafana/provisioning/dashboards/dashboard.yml new file mode 100644 index 0000000..c678414 --- /dev/null +++ b/jdbc/hibernate-slo/configs/grafana/provisioning/dashboards/dashboard.yml @@ -0,0 +1,6 @@ +apiVersion: 1 + +providers: + - name: 'SLO' + options: + path: /etc/grafana/provisioning/dashboards diff --git a/jdbc/hibernate-slo/configs/grafana/provisioning/dashboards/slo.json b/jdbc/hibernate-slo/configs/grafana/provisioning/dashboards/slo.json new file mode 100644 index 0000000..69d76bf --- /dev/null +++ b/jdbc/hibernate-slo/configs/grafana/provisioning/dashboards/slo.json @@ -0,0 +1,646 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 12, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "builder", + "expr": "rate(oks[$__rate_interval]) > 0", + "hide": false, + "legendFormat": "({{sdk}}-{{sdkVersion}}) {{jobName}} OK", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "builder", + "expr": "rate(not_oks[$__rate_interval]) > 0", + "hide": false, + "legendFormat": "({{sdk}}-{{sdkVersion}}) {{jobName}} not OK", + "range": true, + "refId": "C" + } + ], + "title": "SLO Requests RPS", + "transformations": [], + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMin": 0, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 14, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "builder", + "expr": "histogram_quantile(1, rate(attempts_bucket[$__rate_interval]))", + "hide": false, + "legendFormat": "{{sdk}}-{{sdkVersion}} {{jobName}}-{{status}}", + "range": true, + "refId": "A" + } + ], + "title": "Attempts", + "transformations": [], + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 9 + }, + "id": 7, + "panels": [], + "title": "Latencies", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 10 + }, + "id": 4, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "9.3.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "builder", + "expr": "latency{jobName=\"read\", status=\"ok\"} > 0", + "legendFormat": "{{sdk}}-{{sdkVersion}}-p{{quantile}}", + "range": true, + "refId": "A" + } + ], + "title": "Read Latencies (OK)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 10 + }, + "id": 5, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "builder", + "expr": "latency{jobName=\"write\", status=\"ok\"} > 0", + "legendFormat": "{{sdk}}-{{sdkVersion}}-p{{quantile}}", + "range": true, + "refId": "A" + } + ], + "title": "Write Latencies (OK)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 18 + }, + "id": 10, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "builder", + "expr": "latency{jobName=\"read\", status=\"err\"} > 0", + "legendFormat": "{{sdk}}-{{sdkVersion}}-p{{quantile}}", + "range": true, + "refId": "A" + } + ], + "title": "Read Latencies (NOT OK)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 18 + }, + "id": 11, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "builder", + "expr": "latency{jobName=\"write\", status=\"err\"} > 0", + "legendFormat": "{{sdk}}-{{sdkVersion}}-p{{quantile}}", + "range": true, + "refId": "A" + } + ], + "title": "Write Latencies (NOT OK)", + "type": "timeseries" + } + ], + "refresh": "", + "revision": 1, + "schemaVersion": 38, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "filters": [], + "hide": 0, + "label": "", + "name": "filter", + "skipUrlSync": false, + "type": "adhoc" + } + ] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "SLO", + "uid": "7CzMl5t4k", + "version": 1, + "weekStart": "" +} diff --git a/jdbc/hibernate-slo/configs/grafana/provisioning/datasources/datasource.yml b/jdbc/hibernate-slo/configs/grafana/provisioning/datasources/datasource.yml new file mode 100644 index 0000000..0b62b9c --- /dev/null +++ b/jdbc/hibernate-slo/configs/grafana/provisioning/datasources/datasource.yml @@ -0,0 +1,11 @@ +apiVersion: 1 + +datasources: + - name: prometheus + type: prometheus + access: proxy + orgId: 1 + url: http://prometheus:9090 + basicAuth: false + isDefault: true + editable: true diff --git a/jdbc/hibernate-slo/configs/prometheus/prometheus.yml b/jdbc/hibernate-slo/configs/prometheus/prometheus.yml new file mode 100644 index 0000000..281b390 --- /dev/null +++ b/jdbc/hibernate-slo/configs/prometheus/prometheus.yml @@ -0,0 +1,8 @@ +global: + scrape_interval: 1s + evaluation_interval: 1s + +scrape_configs: + - job_name: 'slo' + static_configs: + - targets: ['prometheus-pushgateway:9091'] diff --git a/jdbc/hibernate-slo/docker-compose.yml b/jdbc/hibernate-slo/docker-compose.yml new file mode 100644 index 0000000..59ff8b5 --- /dev/null +++ b/jdbc/hibernate-slo/docker-compose.yml @@ -0,0 +1,90 @@ +version: '2.1' + +networks: + monitor-net: + driver: bridge + +services: + prometheus: + image: prom/prometheus:v2.44.0 + container_name: prometheus + user: "$UID:$GID" + volumes: + - ./configs/prometheus:/etc/prometheus + - ../data/prometheus:/prometheus + command: + - '--config.file=/etc/prometheus/prometheus.yml' + - '--storage.tsdb.path=/prometheus' + - '--storage.tsdb.retention.time=200h' + - '--web.enable-lifecycle' + restart: unless-stopped + ports: + - "9090:9090" + networks: + - monitor-net + + prometheus-pushgateway: + image: prom/pushgateway:v1.6.0 + container_name: prometheus-pushgateway + ports: + - "9091:9091" + networks: + - monitor-net + + grafana: + image: grafana/grafana:9.5.3 + container_name: grafana + user: "$UID:$GID" + volumes: + - ./configs/grafana/provisioning:/etc/grafana/provisioning + - ../data/grafana:/var/lib/grafana + environment: + - GF_SECURITY_ADMIN_USER=admin + - GF_SECURITY_ADMIN_PASSWORD=password + restart: unless-stopped + ports: + - "3000:3000" + networks: + - monitor-net + +# slo-create: +# build: +# context: ../.. +# dockerfile: slo/src/Dockerfile +# command: +# - 'create' +# - 'http://ydb:2136' +# - '/local' +# - '--table-name' +# - 'slo-dotnet' +# - '--min-partitions-count' +# - '6' +# - '--max-partitions-count' +# - '1000' +# - '--partition-size' +# - '1' +# - '--initial-data-count' +# - '1000' +# networks: +# - monitor-net +# depends_on: +# ydb: +# condition: service_healthy +# +# slo-run: +# build: +# context: ../.. +# dockerfile: slo/src/Dockerfile +# command: +# - 'run' +# - 'http://ydb:2136' +# - '/local' +# - '--prom-pgw' +# - 'http://prometheus-pushgateway:9091' +# - '--table-name' +# - 'slo-dotnet' +# networks: +# - monitor-net +# depends_on: +# slo-create: +# condition: service_completed_successfully diff --git a/jdbc/hibernate-slo/pom.xml b/jdbc/hibernate-slo/pom.xml new file mode 100644 index 0000000..500a117 --- /dev/null +++ b/jdbc/hibernate-slo/pom.xml @@ -0,0 +1,129 @@ + + + 4.0.0 + + tech.ydb.jdbc.examples + ydb-jdbc-examples + 1.1.0-SNAPSHOT + + tech.ydb.slo + hibernate-slo + 0.0.1-SNAPSHOT + hibernate-slo + hibernate-slo + + + + org.springframework.boot + spring-boot-dependencies + 3.3.3 + import + pom + + + + + 17 + 17 + 17 + 2.0.20 + 0.9.5 + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.jetbrains.kotlin + kotlin-reflect + + + org.jetbrains.kotlin + kotlin-stdlib + + + tech.ydb.jdbc + ydb-jdbc-driver + + + org.springframework.retry + spring-retry + + + tech.ydb.dialects + hibernate-ydb-dialect + ${hibernate.ydb.dialect.version} + + + tech.ydb.dialects + flyway-ydb-dialect + 1.0.0-RC0 + + + org.flywaydb + flyway-core + + + io.prometheus + prometheus-metrics-core + 1.3.1 + + + io.prometheus + prometheus-metrics-config + 1.3.1 + + + io.prometheus + prometheus-metrics-exporter-pushgateway + 1.3.1 + + + + + src/main/kotlin + + + org.springframework.boot + spring-boot-maven-plugin + + + org.jetbrains.kotlin + kotlin-maven-plugin + + + compile + compile + + compile + + + + + + -Xjsr305=strict + + + spring + jpa + + 17 + + + + org.jetbrains.kotlin + kotlin-maven-allopen + ${kotlin.version} + + + org.jetbrains.kotlin + kotlin-maven-noarg + ${kotlin.version} + + + + + + diff --git a/jdbc/hibernate-slo/src/main/kotlin/tech/ydb/slo/hibernate/HibernateApplication.kt b/jdbc/hibernate-slo/src/main/kotlin/tech/ydb/slo/hibernate/HibernateApplication.kt new file mode 100644 index 0000000..2ac2ad5 --- /dev/null +++ b/jdbc/hibernate-slo/src/main/kotlin/tech/ydb/slo/hibernate/HibernateApplication.kt @@ -0,0 +1,75 @@ +package tech.ydb.slo.hibernate + +import io.prometheus.metrics.core.metrics.Counter +import io.prometheus.metrics.exporter.pushgateway.PushGateway +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.CommandLineRunner +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication +import tech.ydb.slo.hibernate.service.SloService +import java.time.Duration +import java.time.Instant +import java.util.concurrent.Executors + + +@SpringBootApplication +class HibernateApplication : CommandLineRunner { + + @Autowired + private lateinit var sloService: SloService + + override fun run(vararg args: String) { + if (args.isNotEmpty() && args[0] == "create") { + return // Flyway created slo table + } + + val pushGateway = PushGateway.builder() + .job("hibernate-slo") + .address("prometheus-pushgateway:9091") + .build() + + val okCount = Counter.builder().name("oks") + .labelNames("jobName", "sdk", "sdkVersion") + .help("Count of OK") + .register() + val notOkCount = Counter.builder().name("not_oks") + .labelNames("jobName", "sdk", "sdkVersion") + .help("Count of not OK") + .register() + + val workersRead = Executors.newFixedThreadPool(3) + val workersWrite = Executors.newFixedThreadPool(1) + + val startTime = Instant.now() + + while (Instant.now() < startTime.plus(Duration.ofSeconds(10))) { + workersRead.submit { + try { + sloService.find() + okCount.labelValues("read", "TODO", "TODO").inc() + } catch (e: Exception) { + notOkCount.labelValues("read", "TODO", "TODO").inc() + println(e) + } + pushGateway.push() + } + + workersWrite.submit { + try { + sloService.save() + okCount.labelValues("write", "TODO", "TODO").inc() + } catch (e: Exception) { + notOkCount.labelValues("write", "TODO", "TODO").inc() + println(e) + } + pushGateway.push() + } + } + + pushGateway.delete() + } +} + +fun main(args: Array) { + runApplication(*args) +} diff --git a/jdbc/hibernate-slo/src/main/kotlin/tech/ydb/slo/hibernate/entity/SloEntity.kt b/jdbc/hibernate-slo/src/main/kotlin/tech/ydb/slo/hibernate/entity/SloEntity.kt new file mode 100644 index 0000000..43a4ab6 --- /dev/null +++ b/jdbc/hibernate-slo/src/main/kotlin/tech/ydb/slo/hibernate/entity/SloEntity.kt @@ -0,0 +1,31 @@ +package tech.ydb.slo.hibernate.entity + +import jakarta.annotation.Nonnull +import jakarta.persistence.Column +import jakarta.persistence.Entity +import jakarta.persistence.Id +import jakarta.persistence.Table +import java.time.Instant + +/** + * @author Kirill Kurdyukov + */ +@Entity +@Table(name = "slo-hibernate") +class SloEntity { + + @Id + var id: Int = 0 + + @Nonnull + @Column(name = "payload_str") + lateinit var payloadStr: String + + @Nonnull + @Column(name = "payload_double") + var payloadDouble: Double = 0.0 + + @Nonnull + @Column(name = "payload_timestamp") + lateinit var payloadTimestamp: Instant +} \ No newline at end of file diff --git a/jdbc/hibernate-slo/src/main/kotlin/tech/ydb/slo/hibernate/repository/SloEntityRepository.kt b/jdbc/hibernate-slo/src/main/kotlin/tech/ydb/slo/hibernate/repository/SloEntityRepository.kt new file mode 100644 index 0000000..adf3a2b --- /dev/null +++ b/jdbc/hibernate-slo/src/main/kotlin/tech/ydb/slo/hibernate/repository/SloEntityRepository.kt @@ -0,0 +1,10 @@ +package tech.ydb.slo.hibernate.repository + +import org.springframework.data.repository.CrudRepository +import tech.ydb.slo.hibernate.entity.SloEntity + + +/** + * @author Kirill Kurdyukov + */ +interface SloEntityRepository : CrudRepository \ No newline at end of file diff --git a/jdbc/hibernate-slo/src/main/kotlin/tech/ydb/slo/hibernate/retry/YdbRetryable.kt b/jdbc/hibernate-slo/src/main/kotlin/tech/ydb/slo/hibernate/retry/YdbRetryable.kt new file mode 100644 index 0000000..ff31cad --- /dev/null +++ b/jdbc/hibernate-slo/src/main/kotlin/tech/ydb/slo/hibernate/retry/YdbRetryable.kt @@ -0,0 +1,19 @@ +package tech.ydb.slo.hibernate.retry + +import org.springframework.retry.annotation.Backoff +import org.springframework.retry.annotation.Retryable +import java.sql.SQLRecoverableException + +@Target( + AnnotationTarget.FUNCTION, + AnnotationTarget.PROPERTY_GETTER, + AnnotationTarget.PROPERTY_SETTER, + AnnotationTarget.CLASS +) +@Retention(AnnotationRetention.RUNTIME) +@Retryable( + retryFor = [SQLRecoverableException::class], + maxAttempts = 5, + backoff = Backoff(delay = 100, multiplier = 2.0, maxDelay = 5000, random = true), +) +annotation class YdbRetryable \ No newline at end of file diff --git a/jdbc/hibernate-slo/src/main/kotlin/tech/ydb/slo/hibernate/service/SloService.kt b/jdbc/hibernate-slo/src/main/kotlin/tech/ydb/slo/hibernate/service/SloService.kt new file mode 100644 index 0000000..b49bd3d --- /dev/null +++ b/jdbc/hibernate-slo/src/main/kotlin/tech/ydb/slo/hibernate/service/SloService.kt @@ -0,0 +1,37 @@ +package tech.ydb.slo.hibernate.service + +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.stereotype.Service +import tech.ydb.slo.hibernate.entity.SloEntity +import tech.ydb.slo.hibernate.repository.SloEntityRepository +import tech.ydb.slo.hibernate.retry.YdbRetryable +import java.time.Instant +import java.util.Optional +import java.util.UUID +import java.util.concurrent.ThreadLocalRandom +import java.util.concurrent.atomic.AtomicInteger + +/** + * @author Kirill Kurdyukov + */ +@Service +class SloService { + private val id = AtomicInteger(1) + + @Autowired + private lateinit var sloEntityRepository: SloEntityRepository + + @YdbRetryable + fun save() = sloEntityRepository.save( + SloEntity().apply { + id = this@SloService.id.getAndIncrement() + payloadStr = UUID.randomUUID().toString() + payloadDouble = ThreadLocalRandom.current().nextDouble() + payloadTimestamp = Instant.now() + } + ) + + @YdbRetryable + fun find(): Optional = + sloEntityRepository.findById(ThreadLocalRandom.current().nextInt(id.get())) +} \ No newline at end of file diff --git a/jdbc/hibernate-slo/src/main/resources/application.properties b/jdbc/hibernate-slo/src/main/resources/application.properties new file mode 100644 index 0000000..24114da --- /dev/null +++ b/jdbc/hibernate-slo/src/main/resources/application.properties @@ -0,0 +1,5 @@ +spring.application.name=hibernate +spring.datasource.url=jdbc:ydb:grpc://database-sample-grpc:2135/root/database-sample +spring.jpa.properties.hibernate.dialect=tech.ydb.hibernate.dialect.YdbDialect + +spring.datasource.driver-class-name=tech.ydb.jdbc.YdbDriver diff --git a/jdbc/hibernate-slo/src/main/resources/db/migration/V1__create_table.sql b/jdbc/hibernate-slo/src/main/resources/db/migration/V1__create_table.sql new file mode 100644 index 0000000..50f4960 --- /dev/null +++ b/jdbc/hibernate-slo/src/main/resources/db/migration/V1__create_table.sql @@ -0,0 +1,8 @@ +CREATE TABLE `slo-hibernate` +( + id Int32, + payload_str Text, + payload_double Double, + payload_timestamp Timestamp, + PRIMARY KEY (id) +) \ No newline at end of file diff --git a/jdbc/pom.xml b/jdbc/pom.xml index 335d86d..25dcac6 100644 --- a/jdbc/pom.xml +++ b/jdbc/pom.xml @@ -51,6 +51,7 @@ spring-flyway-app spring-liquibase-app shedlock + hibernate-slo