Skip to content

Commit

Permalink
Set the concurrency control stricter when processing transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
Isti01 committed Nov 7, 2024
1 parent 7171a68 commit c180005
Show file tree
Hide file tree
Showing 8 changed files with 36 additions and 9 deletions.
5 changes: 2 additions & 3 deletions backend/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,13 @@ repositories {
mavenCentral()
}

extra["springModulithVersion"] = "1.2.5"

dependencies {
implementation("org.springframework.boot:spring-boot-starter-data-jdbc")
implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.6.0")
implementation("org.springframework.boot:spring-boot-starter-security")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-validation")
implementation("org.springframework.retry:spring-retry")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-csv")
implementation("org.jetbrains.kotlin:kotlin-reflect")
Expand All @@ -45,7 +44,7 @@ dependencies {

dependencyManagement {
imports {
mavenBom("org.springframework.modulith:spring-modulith-bom:${property("springModulithVersion")}")
mavenBom("org.springframework.modulith:spring-modulith-bom:1.2.5")
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ package hu.bme.sch.kir_pay
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.context.properties.ConfigurationPropertiesScan
import org.springframework.boot.runApplication
import org.springframework.retry.annotation.EnableRetry
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity

@SpringBootApplication
@EnableRetry
@EnableMethodSecurity
@ConfigurationPropertiesScan
class KirPayApplication
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
package hu.bme.sch.kir_pay.account

import hu.bme.sch.kir_pay.common.BadRequestException
import hu.bme.sch.kir_pay.common.RetryTransaction
import hu.bme.sch.kir_pay.principal.getLoggedInPrincipal
import org.springframework.context.ApplicationEventPublisher
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Isolation
import org.springframework.transaction.annotation.Transactional
import java.time.Clock

@Service
@Transactional
@Transactional(isolation = Isolation.SERIALIZABLE)
class AccountBalanceService(
private val accountRepository: AccountRepository,
private val events: ApplicationEventPublisher,
private val clock: Clock
) {

@RetryTransaction
@Transactional(isolation = Isolation.SERIALIZABLE)
fun pay(card: String, amount: Long, logEvent: Boolean): Account {
if (amount < 0) throw BadRequestException("Helytelen argumentum!")
val account = accountRepository.findActiveAccountByCard(card)
Expand Down Expand Up @@ -43,6 +47,8 @@ class AccountBalanceService(
}


@RetryTransaction
@Transactional(isolation = Isolation.SERIALIZABLE)
fun upload(card: String, amount: Long): Account {
if (amount < 0) throw BadRequestException("Helytelen argumentum!")
val account = accountRepository.findActiveAccountByCard(card)
Expand All @@ -56,6 +62,8 @@ class AccountBalanceService(


// Returns the sender account
@RetryTransaction
@Transactional(isolation = Isolation.SERIALIZABLE)
fun transfer(senderCard: String, recipientCard: String, amount: Long): Account {
if (amount < 0) throw BadRequestException("Helytelen argumentum!")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package hu.bme.sch.kir_pay.account

import hu.bme.sch.kir_pay.common.BadRequestException
import hu.bme.sch.kir_pay.common.NotFoundException
import hu.bme.sch.kir_pay.common.RetryTransaction
import hu.bme.sch.kir_pay.principal.getLoggedInPrincipal
import org.springframework.context.ApplicationEventPublisher
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Isolation
import org.springframework.transaction.annotation.Transactional
import java.time.Clock

Expand Down Expand Up @@ -59,6 +61,8 @@ class AccountService(
accountRepository.findActiveAccountByCard(card) ?: throw NotFoundException("A kártyához nincs számla rendelve!")


@RetryTransaction
@Transactional(isolation = Isolation.SERIALIZABLE)
fun assignCard(accountId: Int, card: String): Account {
val account = accountRepository.findById(accountId).orElseThrow { BadRequestException("A számla nem található!") }
if (account.card == card) return account
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package hu.bme.sch.kir_pay.common

import org.springframework.retry.annotation.Backoff
import org.springframework.retry.annotation.Retryable
import java.sql.SQLException

@Retryable(
retryFor = [SQLException::class],
maxAttempts = 5,
backoff = Backoff(delay = 200, maxDelay = 750, multiplier = 1.5, random = true),
)
annotation class RetryTransaction
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package hu.bme.sch.kir_pay.order

import hu.bme.sch.kir_pay.account.AccountService
import hu.bme.sch.kir_pay.common.RetryTransaction
import hu.bme.sch.kir_pay.principal.getLoggedInPrincipal
import org.springframework.context.ApplicationEventPublisher
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Isolation
import org.springframework.transaction.annotation.Transactional
import java.time.Clock

Expand Down Expand Up @@ -32,6 +34,8 @@ class OrderService(
orderRepository.findAllOrderWithOrderLinesOrderByTimestampDescPaginated(page.toLong() * size, size)


@RetryTransaction
@Transactional(isolation = Isolation.SERIALIZABLE)
fun checkout(card: String, dto: OrderTerminalController.CheckoutDto) {
val order = newOrder(card)
events.publishEvent(OrderCreatedEvent(order.id, order.accountId, getLoggedInPrincipal(), clock.millis()))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
package hu.bme.sch.kir_pay.principal

import org.springframework.context.annotation.Configuration
import org.springframework.context.event.EventListener
import org.springframework.transaction.annotation.Transactional
import org.springframework.modulith.events.ApplicationModuleListener

@Configuration
class PrincipalLastUseUpdater(private val principalService: PrincipalService) {

@EventListener
@Transactional
@ApplicationModuleListener
fun on(event: PrincipalAuthenticatedEvent) {
principalService.updateLastUsed(event.principal.id)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class PrincipalService(

fun setEnabled(id: Int, enabled: Boolean): Principal {
val principal = find(id)
if (principal.role == Role.ADMIN && !enabled) throw BadRequestException("Admins nem lehet letiltani")
if (principal.role == Role.ADMIN && !enabled) throw BadRequestException("Admint nem lehet letiltani")
val newPrincipal = principalRepository.save(principal.copy(active = enabled))
events.publishEvent(PrincipalUpdatedEvent(newPrincipal, getLoggedInPrincipal(), clock.millis()))
return newPrincipal
Expand Down

0 comments on commit c180005

Please sign in to comment.