Versuche
This commit is contained in:
+3
-1
@@ -38,9 +38,10 @@ COPY frontend/ frontend/
|
|||||||
COPY core/ core/
|
COPY core/ core/
|
||||||
COPY backend/ backend/
|
COPY backend/ backend/
|
||||||
COPY docs/ docs/
|
COPY docs/ docs/
|
||||||
COPY build.gradle.kts ./
|
COPY entries-service/build.gradle.kts ./
|
||||||
|
|
||||||
# Copy entries modules
|
# Copy entries modules
|
||||||
|
COPY backend/services/entries/entries-api/ backend/services/entries/entries-api/
|
||||||
COPY backend/services/entries/entries-service/ backend/services/entries/entries-service/
|
COPY backend/services/entries/entries-service/ backend/services/entries/entries-service/
|
||||||
|
|
||||||
RUN --mount=type=cache,target=/home/gradle/.gradle/caches \
|
RUN --mount=type=cache,target=/home/gradle/.gradle/caches \
|
||||||
@@ -127,5 +128,6 @@ ENTRYPOINT ["tini", "--", "sh", "-c", "\
|
|||||||
echo 'DEBUG mode enabled'; \
|
echo 'DEBUG mode enabled'; \
|
||||||
exec java ${JAVA_OPTS} -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 -jar app.jar; \
|
exec java ${JAVA_OPTS} -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 -jar app.jar; \
|
||||||
else \
|
else \
|
||||||
|
echo 'Starting Entries Service in production mode'; \
|
||||||
exec java ${JAVA_OPTS} -jar app.jar; \
|
exec java ${JAVA_OPTS} -jar app.jar; \
|
||||||
fi"]
|
fi"]
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
plugins {
|
||||||
|
alias(libs.plugins.kotlinMultiplatform)
|
||||||
|
alias(libs.plugins.kotlinSerialization)
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "at.mocode"
|
||||||
|
version = "1.0.0"
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
|
||||||
|
val enableWasm = providers.gradleProperty("enableWasm").orNull == "true"
|
||||||
|
|
||||||
|
// Align the toolchain with a project (see composeApp uses 21)
|
||||||
|
jvmToolchain(21)
|
||||||
|
|
||||||
|
// JVM target for backend usage
|
||||||
|
jvm()
|
||||||
|
|
||||||
|
// JS target for frontend usage (Compose/Browser)
|
||||||
|
js {
|
||||||
|
browser()
|
||||||
|
// no need for binaries.executable() in a library
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optional Wasm target for browser clients
|
||||||
|
if (enableWasm) {
|
||||||
|
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
|
||||||
|
wasmJs {
|
||||||
|
browser()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
commonMain {
|
||||||
|
dependencies {
|
||||||
|
implementation(libs.kotlinx.serialization.json)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
commonTest {
|
||||||
|
dependencies {
|
||||||
|
implementation(libs.kotlin.test)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
package at.mocode.entries.api
|
||||||
|
|
||||||
|
interface EntriesApi {
|
||||||
|
suspend fun healthCheck(): HealthResponse
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
package at.mocode.entries.api
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class EntriesResponse(val status: String, val timestamp: String, val service: String)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class EnhancedEntriesResponse(
|
||||||
|
val status: String,
|
||||||
|
val timestamp: String,
|
||||||
|
val service: String,
|
||||||
|
val circuitBreakerState: String,
|
||||||
|
val responseTime: Long
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class HealthResponse(
|
||||||
|
val status: String,
|
||||||
|
val timestamp: String,
|
||||||
|
val service: String,
|
||||||
|
val healthy: Boolean
|
||||||
|
)
|
||||||
@@ -13,6 +13,7 @@ springBoot {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation(platform(projects.platform.platformBom))
|
implementation(platform(projects.platform.platformBom))
|
||||||
implementation(projects.platform.platformDependencies)
|
implementation(projects.platform.platformDependencies)
|
||||||
|
implementation(projects.backend.services.entries.entriesApi)
|
||||||
implementation(projects.backend.infrastructure.monitoring.monitoringClient)
|
implementation(projects.backend.infrastructure.monitoring.monitoringClient)
|
||||||
|
|
||||||
implementation(libs.bundles.spring.boot.service.complete)
|
implementation(libs.bundles.spring.boot.service.complete)
|
||||||
|
|||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
package at.mocode.entries.service
|
||||||
|
|
||||||
|
import at.mocode.entries.api.EnhancedEntriesResponse
|
||||||
|
import at.mocode.entries.api.EntriesApi
|
||||||
|
import at.mocode.entries.api.HealthResponse
|
||||||
|
import org.springframework.web.bind.annotation.*
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@CrossOrigin(
|
||||||
|
origins = ["http://localhost:8080", "http://localhost:8083", "http://localhost:4000"],
|
||||||
|
methods = [RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE, RequestMethod.OPTIONS],
|
||||||
|
allowedHeaders = ["*"],
|
||||||
|
allowCredentials = "true"
|
||||||
|
)
|
||||||
|
class EntriesController(
|
||||||
|
private val entriesService: EntriesServiceCircuitBreaker
|
||||||
|
) : EntriesApi {
|
||||||
|
|
||||||
|
// Contract endpoints
|
||||||
|
@GetMapping("/entries/enhanced")
|
||||||
|
suspend fun enhancedEntries(
|
||||||
|
@RequestParam(required = false, defaultValue = "false") simulate: Boolean
|
||||||
|
): EnhancedEntriesResponse = entriesService.entries(simulate)
|
||||||
|
|
||||||
|
@GetMapping("/entries/health")
|
||||||
|
override suspend fun healthCheck(): HealthResponse = entriesService.healthCheck()
|
||||||
|
}
|
||||||
+23
-15
@@ -2,26 +2,34 @@ package at.mocode.entries.service
|
|||||||
|
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication
|
import org.springframework.boot.autoconfigure.SpringBootApplication
|
||||||
import org.springframework.boot.runApplication
|
import org.springframework.boot.runApplication
|
||||||
import org.springframework.web.bind.annotation.GetMapping
|
import org.springframework.context.annotation.Bean
|
||||||
import org.springframework.web.bind.annotation.PostMapping
|
import org.springframework.context.annotation.EnableAspectJAutoProxy
|
||||||
import org.springframework.web.bind.annotation.RestController
|
import org.springframework.web.servlet.config.annotation.CorsRegistry
|
||||||
import org.springframework.http.HttpStatus
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
|
||||||
import org.springframework.http.ResponseEntity
|
|
||||||
|
|
||||||
@SpringBootApplication
|
|
||||||
class EntriesServiceApplication
|
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
runApplication<EntriesServiceApplication>(*args)
|
runApplication<EntriesServiceApplication>(*args)
|
||||||
}
|
}
|
||||||
|
|
||||||
@RestController
|
@SpringBootApplication
|
||||||
class EntriesController {
|
@EnableAspectJAutoProxy
|
||||||
@GetMapping("/")
|
class EntriesServiceApplication {
|
||||||
fun health(): String = "Entries Service is running"
|
|
||||||
|
|
||||||
@PostMapping("/entries/conflict-demo")
|
@Bean
|
||||||
fun conflictDemo(): ResponseEntity<String> {
|
fun corsConfigurer(): WebMvcConfigurer {
|
||||||
return ResponseEntity.status(HttpStatus.CONFLICT).body("Conflict detected (Demo)")
|
return object : WebMvcConfigurer {
|
||||||
|
override fun addCorsMappings(registry: CorsRegistry) {
|
||||||
|
registry.addMapping("/**")
|
||||||
|
.allowedOriginPatterns("http://localhost:*")
|
||||||
|
.allowedOrigins("http://localhost:8080",
|
||||||
|
"http://localhost:8083",
|
||||||
|
"http://localhost:4000"
|
||||||
|
)
|
||||||
|
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
|
||||||
|
.allowedHeaders("*")
|
||||||
|
.allowCredentials(true)
|
||||||
|
.maxAge(3600)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+110
@@ -0,0 +1,110 @@
|
|||||||
|
package at.mocode.entries.service
|
||||||
|
|
||||||
|
import at.mocode.entries.api.EnhancedEntriesResponse
|
||||||
|
import at.mocode.entries.api.HealthResponse
|
||||||
|
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import org.springframework.stereotype.Service
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
import java.time.ZoneOffset
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service demonstrating a Circuit Breaker pattern with Resilience
|
||||||
|
*
|
||||||
|
* This service simulates potential failures and uses circuit breaker
|
||||||
|
* to handle service degradation gracefully with fallback responses.
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
class EntriesServiceCircuitBreaker {
|
||||||
|
|
||||||
|
private val logger = LoggerFactory.getLogger(EntriesServiceCircuitBreaker::class.java)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val ENTRIES_CIRCUIT_BREAKER = "entriesCircuitBreaker"
|
||||||
|
private val formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME //.ofPattern("yyyy-MM-dd HH:mm:ss")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Primary entries method with circuit breaker protection returning DTO directly
|
||||||
|
*
|
||||||
|
* @param simulateFailure - if true, randomly throws exceptions to test circuit breaker
|
||||||
|
*/
|
||||||
|
@CircuitBreaker(name = ENTRIES_CIRCUIT_BREAKER, fallbackMethod = "fallbackEntries")
|
||||||
|
fun entries(simulateFailure: Boolean = false): EnhancedEntriesResponse {
|
||||||
|
val start = System.nanoTime()
|
||||||
|
logger.info("Executing entries service call...")
|
||||||
|
|
||||||
|
if (simulateFailure && Random.nextDouble() < 0.6) {
|
||||||
|
logger.warn("Simulating service failure for circuit breaker testing")
|
||||||
|
throw RuntimeException("Simulated service failure")
|
||||||
|
}
|
||||||
|
|
||||||
|
val currentTime = LocalDateTime.now().atOffset(ZoneOffset.UTC).format(formatter)
|
||||||
|
val elapsedMs = (System.nanoTime() - start) / 1_000_000
|
||||||
|
logger.info("Entries service call successful")
|
||||||
|
|
||||||
|
return EnhancedEntriesResponse(
|
||||||
|
status = "entries",
|
||||||
|
timestamp = currentTime,
|
||||||
|
service = "entries-service",
|
||||||
|
circuitBreakerState = "CLOSED",
|
||||||
|
responseTime = elapsedMs
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fallback method called when circuit breaker is OPEN
|
||||||
|
*
|
||||||
|
* @param simulateFailure - original parameter (ignored in fallback)
|
||||||
|
* @param exception - the exception that triggered the fallback
|
||||||
|
*/
|
||||||
|
fun fallbackEntries(simulateFailure: Boolean = false, exception: Exception): EnhancedEntriesResponse {
|
||||||
|
val start = System.nanoTime()
|
||||||
|
// Die volle Exception nur loggen, nicht an den Client weitergeben.
|
||||||
|
logger.warn("Circuit breaker fallback triggered due to: {}", exception.toString())
|
||||||
|
|
||||||
|
val currentTime = LocalDateTime.now().atOffset(ZoneOffset.UTC).format(formatter)
|
||||||
|
val elapsedMs = (System.nanoTime() - start) / 1_000_000
|
||||||
|
|
||||||
|
return EnhancedEntriesResponse(
|
||||||
|
status = "fallback",
|
||||||
|
timestamp = currentTime,
|
||||||
|
service = "entries-service-fallback",
|
||||||
|
circuitBreakerState = "OPEN",
|
||||||
|
responseTime = elapsedMs
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Health check method with circuit breaker protection returning DTO directly
|
||||||
|
*/
|
||||||
|
@CircuitBreaker(name = ENTRIES_CIRCUIT_BREAKER, fallbackMethod = "fallbackHealth")
|
||||||
|
fun healthCheck(): HealthResponse {
|
||||||
|
logger.info("Executing health check...")
|
||||||
|
|
||||||
|
val currentTime = LocalDateTime.now().atOffset(ZoneOffset.UTC).format(formatter)
|
||||||
|
return HealthResponse(
|
||||||
|
status = "entries",
|
||||||
|
timestamp = currentTime,
|
||||||
|
service = "entries-service",
|
||||||
|
healthy = true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fallback for health check returning DTO
|
||||||
|
*/
|
||||||
|
fun fallbackHealth(exception: Exception): HealthResponse {
|
||||||
|
logger.warn("Health check fallback triggered: {}", exception.message)
|
||||||
|
|
||||||
|
val currentTime = LocalDateTime.now().atOffset(ZoneOffset.UTC).format(formatter)
|
||||||
|
return HealthResponse(
|
||||||
|
status = "down",
|
||||||
|
timestamp = currentTime,
|
||||||
|
service = "entries-service",
|
||||||
|
healthy = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
package at.mocode.entries.service.config
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean
|
||||||
|
import org.springframework.context.annotation.Configuration
|
||||||
|
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
|
||||||
|
import org.springframework.security.config.http.SessionCreationPolicy
|
||||||
|
import org.springframework.security.web.SecurityFilterChain
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Security configuration for the Entries Service.
|
||||||
|
* Enables method-level security for fine-grained authorization control.
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@EnableWebSecurity
|
||||||
|
@EnableMethodSecurity(prePostEnabled = true)
|
||||||
|
class SecurityConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
||||||
|
return http
|
||||||
|
.csrf { it.disable() }
|
||||||
|
.sessionManagement { it.sessionCreationPolicy(SessionCreationPolicy.STATELESS) }
|
||||||
|
.authorizeHttpRequests { auth ->
|
||||||
|
auth
|
||||||
|
// Allow health check endpoints
|
||||||
|
.requestMatchers("/actuator/**", "/health/**").permitAll()
|
||||||
|
// Allow ping endpoints for monitoring (these are typically public)
|
||||||
|
.requestMatchers("/entries/**").permitAll()
|
||||||
|
// All other endpoints require authentication (handled by method-level security)
|
||||||
|
.anyRequest().authenticated()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
spring:
|
||||||
|
application:
|
||||||
|
name: entries-service
|
||||||
|
cloud:
|
||||||
|
consul:
|
||||||
|
host: ${CONSUL_HOST:localhost}
|
||||||
|
port: ${CONSUL_PORT:8500}
|
||||||
|
discovery:
|
||||||
|
enabled: true
|
||||||
|
register: true
|
||||||
|
health-check-path: /actuator/health
|
||||||
|
health-check-interval: 10s
|
||||||
|
|
||||||
|
server:
|
||||||
|
port: ${SERVER_PORT:${ENTRIES_SERVICE_PORT:8083}}
|
||||||
|
|
||||||
|
management:
|
||||||
|
endpoints:
|
||||||
|
web:
|
||||||
|
exposure:
|
||||||
|
include: health,info,metrics,prometheus,circuitbreakers
|
||||||
|
endpoint:
|
||||||
|
health:
|
||||||
|
show-details: always
|
||||||
|
probes:
|
||||||
|
enabled: true
|
||||||
|
tracing:
|
||||||
|
enabled: ${TRACING_ENABLED:false}
|
||||||
|
sampling:
|
||||||
|
probability: ${TRACING_SAMPLING_PROBABILITY:0.1}
|
||||||
|
zipkin:
|
||||||
|
tracing:
|
||||||
|
endpoint: ${ZIPKIN_TRACING_ENDPOINT:http://localhost:9411/api/v2/spans}
|
||||||
|
connect-timeout: 1s
|
||||||
|
read-timeout: 5s
|
||||||
|
# Resilience4j Circuit Breaker Configuration
|
||||||
|
resilience4j:
|
||||||
|
circuitbreaker:
|
||||||
|
configs:
|
||||||
|
default:
|
||||||
|
# Circuit breaker opens when the failure rate exceeds 50%
|
||||||
|
failure-rate-threshold: 50
|
||||||
|
# Minimum number of calls to calculate the failure rate
|
||||||
|
minimum-number-of-calls: 5
|
||||||
|
# Time to wait before transitioning from OPEN to HALF_OPEN
|
||||||
|
wait-duration-in-open-state: 10s
|
||||||
|
# Number of calls in HALF_OPEN state before deciding to close/open
|
||||||
|
permitted-number-of-calls-in-half-open-state: 3
|
||||||
|
# Sliding window size for calculating failure rate
|
||||||
|
sliding-window-size: 10
|
||||||
|
# Type of sliding window (COUNT_BASED or TIME_BASED)
|
||||||
|
sliding-window-type: COUNT_BASED
|
||||||
|
# Record exceptions that should be considered as failures
|
||||||
|
record-exceptions:
|
||||||
|
- java.lang.Exception
|
||||||
|
# Ignore certain exceptions (don't count as failures)
|
||||||
|
ignore-exceptions:
|
||||||
|
- java.lang.IllegalArgumentException
|
||||||
|
instances:
|
||||||
|
entriesCircuitBreaker:
|
||||||
|
# Use default configuration
|
||||||
|
base-config: default
|
||||||
|
# Override specific settings for this instance if needed
|
||||||
|
failure-rate-threshold: 60
|
||||||
|
minimum-number-of-calls: 4
|
||||||
|
wait-duration-in-open-state: 5s
|
||||||
|
|
||||||
|
# Metrics configuration removed to avoid property resolution warnings
|
||||||
|
# Use micrometer and actuator endpoints for metrics instead
|
||||||
|
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
<property name="LOG_PATTERN" value="%d{ISO8601} %-5level [%X{traceId:-}:%X{spanId:-}] %logger{36} - %msg%n"/>
|
||||||
|
|
||||||
|
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>${LOG_PATTERN}</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<logger name="org.springframework" level="INFO"/>
|
||||||
|
<logger name="org.springframework.web" level="INFO"/>
|
||||||
|
<logger name="org.springframework.boot.actuate" level="INFO"/>
|
||||||
|
<logger name="reactor.netty" level="WARN"/>
|
||||||
|
|
||||||
|
<root level="INFO">
|
||||||
|
<appender-ref ref="CONSOLE"/>
|
||||||
|
</root>
|
||||||
|
</configuration>
|
||||||
+1
-1
@@ -355,7 +355,7 @@ services:
|
|||||||
entries-service:
|
entries-service:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: backend/services/entries/entries-service/Dockerfile
|
dockerfile: backend/services/entries/Dockerfile
|
||||||
args:
|
args:
|
||||||
GRADLE_VERSION: "${DOCKER_GRADLE_VERSION:-9.1.0}"
|
GRADLE_VERSION: "${DOCKER_GRADLE_VERSION:-9.1.0}"
|
||||||
JAVA_VERSION: "${DOCKER_JAVA_VERSION:-21}"
|
JAVA_VERSION: "${DOCKER_JAVA_VERSION:-21}"
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
@startuml
|
||||||
|
!define table(x) entity x << (T, white) >>
|
||||||
|
!define primary_key(x) <b><color:#b8861b><&key></color> x</b>
|
||||||
|
!define foreign_key(x) <color:#aaaaaa><&key></color> x
|
||||||
|
|
||||||
|
skinparam linetype ortho
|
||||||
|
|
||||||
|
table(Turnier) {
|
||||||
|
primary_key(turnier_id)
|
||||||
|
--
|
||||||
|
name: varchar
|
||||||
|
start_datum: date
|
||||||
|
end_datum: date
|
||||||
|
ort: varchar
|
||||||
|
kategorie_oeto: varchar
|
||||||
|
}
|
||||||
|
|
||||||
|
table(Bewerb) {
|
||||||
|
primary_key(bewerb_id)
|
||||||
|
--
|
||||||
|
foreign_key(turnier_id)
|
||||||
|
nummer: varchar
|
||||||
|
disziplin: varchar
|
||||||
|
klasse: varchar
|
||||||
|
nenngeld: decimal
|
||||||
|
}
|
||||||
|
|
||||||
|
table(Person) {
|
||||||
|
primary_key(person_id)
|
||||||
|
--
|
||||||
|
vorname: varchar
|
||||||
|
nachname: varchar
|
||||||
|
lizenznummer: varchar
|
||||||
|
}
|
||||||
|
|
||||||
|
table(Pferd) {
|
||||||
|
primary_key(pferd_id)
|
||||||
|
--
|
||||||
|
foreign_key(besitzer_person_id)
|
||||||
|
name: varchar
|
||||||
|
lebensnummer: varchar
|
||||||
|
}
|
||||||
|
|
||||||
|
table(Nennung) {
|
||||||
|
primary_key(nennung_id)
|
||||||
|
--
|
||||||
|
foreign_key(bewerb_id)
|
||||||
|
foreign_key(person_id)
|
||||||
|
foreign_key(pferd_id)
|
||||||
|
status: varchar
|
||||||
|
nennungs_datum: timestamp
|
||||||
|
}
|
||||||
|
|
||||||
|
table(Startplatz) {
|
||||||
|
primary_key(startplatz_id)
|
||||||
|
--
|
||||||
|
foreign_key(nennung_id)
|
||||||
|
startnummer: int
|
||||||
|
startzeit: time
|
||||||
|
status: varchar
|
||||||
|
}
|
||||||
|
|
||||||
|
table(Ergebnis) {
|
||||||
|
primary_key(ergebnis_id)
|
||||||
|
--
|
||||||
|
foreign_key(startplatz_id)
|
||||||
|
wertnote: decimal
|
||||||
|
fehler: int
|
||||||
|
zeit: time
|
||||||
|
platzierung: int
|
||||||
|
}
|
||||||
|
|
||||||
|
Turnier ||--o{ Bewerb
|
||||||
|
Bewerb }o--o{ Nennung
|
||||||
|
Person }o--o{ Nennung
|
||||||
|
Pferd }o--o{ Nennung
|
||||||
|
Person }o..o{ Pferd
|
||||||
|
Nennung ||--|{ Startplatz
|
||||||
|
Startplatz ||--|{ Ergebnis
|
||||||
|
@enduml
|
||||||
@@ -65,6 +65,7 @@ include(":backend:infrastructure:monitoring:monitoring-server")
|
|||||||
// include(":backend:services:events:events-service")
|
// include(":backend:services:events:events-service")
|
||||||
|
|
||||||
// --- ENTRIES (Nennungen) ---
|
// --- ENTRIES (Nennungen) ---
|
||||||
|
include(":backend:services:entries:entries-api")
|
||||||
include(":backend:services:entries:entries-service")
|
include(":backend:services:entries:entries-service")
|
||||||
|
|
||||||
// --- RESULTS (Ergebnisse) ---
|
// --- RESULTS (Ergebnisse) ---
|
||||||
|
|||||||
Reference in New Issue
Block a user