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