Skip to content

Commit

Permalink
fix: Store activity using stateless session
Browse files Browse the repository at this point in the history
  • Loading branch information
JanCizmar committed Dec 17, 2023
1 parent 3bc0db7 commit 189828d
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 43 deletions.
50 changes: 23 additions & 27 deletions backend/data/src/main/kotlin/io/tolgee/activity/ActivityService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@ package io.tolgee.activity
import io.tolgee.activity.data.ActivityType
import io.tolgee.activity.projectActivityView.ProjectActivityViewByPageableProvider
import io.tolgee.activity.projectActivityView.ProjectActivityViewByRevisionProvider
import io.tolgee.component.CurrentDateProvider
import io.tolgee.dtos.query_results.TranslationHistoryView
import io.tolgee.events.OnProjectActivityStoredEvent
import io.tolgee.model.activity.ActivityModifiedEntity
import io.tolgee.model.activity.ActivityRevision
import io.tolgee.model.views.activity.ProjectActivityView
import io.tolgee.repository.activity.ActivityModifiedEntityRepository
import io.tolgee.util.Logging
import io.tolgee.util.doInStatelessSession
import io.tolgee.util.flushAndClear
import io.tolgee.util.logger
import jakarta.persistence.EntityExistsException
import jakarta.persistence.EntityManager
import org.hibernate.StatelessSession
import org.springframework.context.ApplicationContext
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
Expand All @@ -24,50 +25,45 @@ import org.springframework.transaction.annotation.Transactional
class ActivityService(
private val entityManager: EntityManager,
private val applicationContext: ApplicationContext,
private val activityModifiedEntityRepository: ActivityModifiedEntityRepository
private val activityModifiedEntityRepository: ActivityModifiedEntityRepository,
private val currentDateProvider: CurrentDateProvider
) : Logging {
@Transactional
fun storeActivityData(activityRevision: ActivityRevision, modifiedEntities: ModifiedEntitiesType) {
// let's keep the persistent context small
entityManager.flushAndClear()

val mergedActivityRevision = activityRevision.persist()
mergedActivityRevision.persistedDescribingRelations()

mergedActivityRevision.modifiedEntities = modifiedEntities.persist()

entityManager.flushAndClear()

val mergedActivityRevision = entityManager.doInStatelessSession { statelessSession ->
val mergedActivityRevision = statelessSession.persist(activityRevision)
statelessSession.persistedDescribingRelations(mergedActivityRevision)
mergedActivityRevision.modifiedEntities = statelessSession.persist(modifiedEntities)
mergedActivityRevision
}
applicationContext.publishEvent(OnProjectActivityStoredEvent(this, mergedActivityRevision))

entityManager.flushAndClear()
}

private fun ModifiedEntitiesType.persist(): MutableList<ActivityModifiedEntity> {
val list = this.values.flatMap { it.values }.toMutableList()
private fun StatelessSession.persist(modifiedEntities: ModifiedEntitiesType): MutableList<ActivityModifiedEntity> {
val list = modifiedEntities.values.flatMap { it.values }.toMutableList()
list.forEach { activityModifiedEntity ->
try {
entityManager.persist(activityModifiedEntity)
} catch (e: EntityExistsException) {
logger.debug("ModifiedEntity entity already exists in persistence context, skipping", e)
}
this.insert(activityModifiedEntity)
}
return list
}

private fun ActivityRevision.persistedDescribingRelations() {
private fun StatelessSession.persistedDescribingRelations(activityRevision: ActivityRevision) {
@Suppress("UselessCallOnCollection")
describingRelations.filterNotNull().forEach {
entityManager.persist(it)
activityRevision.describingRelations.filterNotNull().forEach {
this.insert(it)
}
}

private fun ActivityRevision.persist(): ActivityRevision {
return if (id == 0L) {
entityManager.persist(this)
this
private fun StatelessSession.persist(activityRevision: ActivityRevision): ActivityRevision {
return if (activityRevision.id == 0L) {
activityRevision.timestamp = currentDateProvider.date
this.insert(activityRevision)
activityRevision
} else {
entityManager.getReference(ActivityRevision::class.java, id)
entityManager.getReference(ActivityRevision::class.java, activityRevision.id)
}
}

Expand Down

This file was deleted.

13 changes: 13 additions & 0 deletions backend/data/src/main/kotlin/io/tolgee/util/entityManagerExt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package io.tolgee.util

import jakarta.persistence.EntityManager
import org.hibernate.Session
import org.hibernate.StatelessSession

val EntityManager.session: Session
get() = this.unwrap(org.hibernate.Session::class.java)!!
Expand All @@ -10,3 +11,15 @@ fun EntityManager.flushAndClear() {
this.flush()
this.clear()
}


inline fun <reified T> EntityManager.doInStatelessSession(
crossinline block: (StatelessSession) -> T
): T {
return unwrap(Session::class.java).doReturningWork { connection ->
val statelessSession = unwrap(Session::class.java).sessionFactory.openStatelessSession(connection)
statelessSession.use { ss ->
block(ss)
}
}
}

0 comments on commit 189828d

Please sign in to comment.