From 1f62f2420f771616cfd4e5ed7121076cb8594403 Mon Sep 17 00:00:00 2001 From: Jan Cizmar Date: Thu, 21 Dec 2023 10:25:53 +0100 Subject: [PATCH] fix: Fix auto-translation errors, drop some handled exceptions (sentry) --- .../component/SentryBeforeSendCallback.kt | 34 ++++++++++++++++ .../tolgee/exceptions/ExceptionWithMessage.kt | 2 +- .../translation/AutoTranslationService.kt | 40 +++++++++++-------- .../util/tryUntilItDoesntBreakContraint.kt | 5 ++- 4 files changed, 62 insertions(+), 19 deletions(-) create mode 100644 backend/data/src/main/kotlin/io/tolgee/component/SentryBeforeSendCallback.kt diff --git a/backend/data/src/main/kotlin/io/tolgee/component/SentryBeforeSendCallback.kt b/backend/data/src/main/kotlin/io/tolgee/component/SentryBeforeSendCallback.kt new file mode 100644 index 0000000000..914445d883 --- /dev/null +++ b/backend/data/src/main/kotlin/io/tolgee/component/SentryBeforeSendCallback.kt @@ -0,0 +1,34 @@ +package io.tolgee.component + +import io.sentry.Hint +import io.sentry.SentryEvent +import io.sentry.SentryOptions +import org.springframework.stereotype.Component + +@Component +class SentryBeforeSendCallback : SentryOptions.BeforeSendCallback { + override fun execute(event: SentryEvent, hint: Hint): SentryEvent? { + if (event.containsMessage("Failed to send message to MessageChannel")) { + return null + } + + if (event.containsExceptionOfType("FailedDontRequeueException")) { + return null + } + + if (event.containsExceptionOfType("ClientAbortException")) { + return null + } + + if (event.containsMessage("Cannot render error page for request [/websocket")) return null + + return event + } + + private fun SentryEvent.containsMessage(string: String): Boolean { + return message?.formatted?.contains(string) == true + } + + private fun SentryEvent.containsExceptionOfType(type: String) = + exceptions?.any { it.type?.contains(type) == true } == true +} diff --git a/backend/data/src/main/kotlin/io/tolgee/exceptions/ExceptionWithMessage.kt b/backend/data/src/main/kotlin/io/tolgee/exceptions/ExceptionWithMessage.kt index 0e8b8914ce..e841739f03 100644 --- a/backend/data/src/main/kotlin/io/tolgee/exceptions/ExceptionWithMessage.kt +++ b/backend/data/src/main/kotlin/io/tolgee/exceptions/ExceptionWithMessage.kt @@ -22,7 +22,7 @@ abstract class ExceptionWithMessage( this.tolgeeMessage = message } - constructor(message: Message) : this(null, null) { + constructor(message: Message) : this(message.code, null) { this.tolgeeMessage = message } } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/translation/AutoTranslationService.kt b/backend/data/src/main/kotlin/io/tolgee/service/translation/AutoTranslationService.kt index 20c53b181c..f35f0f2de2 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/translation/AutoTranslationService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/translation/AutoTranslationService.kt @@ -16,10 +16,13 @@ import io.tolgee.repository.AutoTranslationConfigRepository import io.tolgee.security.authentication.AuthenticationFacade import io.tolgee.service.LanguageService import io.tolgee.service.machineTranslation.MtService +import io.tolgee.util.executeInNewTransaction +import io.tolgee.util.tryUntilItDoesntBreakConstraint import jakarta.persistence.EntityManager import org.slf4j.Logger import org.slf4j.LoggerFactory import org.springframework.stereotype.Service +import org.springframework.transaction.PlatformTransactionManager @Service class AutoTranslationService( @@ -30,7 +33,8 @@ class AutoTranslationService( private val languageService: LanguageService, private val batchJobService: BatchJobService, private val authenticationFacade: AuthenticationFacade, - private val entityManager: EntityManager + private val entityManager: EntityManager, + private val transactionManager: PlatformTransactionManager ) { val logger: Logger = LoggerFactory.getLogger(this::class.java) @@ -134,27 +138,31 @@ class AutoTranslationService( useMachineTranslation: Boolean? = null, isBatch: Boolean, ) { - val adjustedConfigs = getAdjustedConfigs(key, forcedLanguageTags, useTranslationMemory, useMachineTranslation) + tryUntilItDoesntBreakConstraint(maxRepeats = 10) { + executeInNewTransaction(transactionManager) { + val adjustedConfigs = getAdjustedConfigs(key, forcedLanguageTags, useTranslationMemory, useMachineTranslation) - val translations = adjustedConfigs.map { - if (it.override) { - return@map it to translationService.getOrCreate(key, it.language) - } + val translations = adjustedConfigs.map { + if (it.override) { + return@map it to translationService.getOrCreate(key, it.language) + } - it to getUntranslatedTranslations(key, listOf(it.language)).firstOrNull() - }.filter { - it.second?.state != TranslationState.DISABLED - } + it to getUntranslatedTranslations(key, listOf(it.language)).firstOrNull() + }.filter { + it.second?.state != TranslationState.DISABLED + } - val toTmTranslate = translations.filter { it.first.usingTm }.mapNotNull { it.second } + val toTmTranslate = translations.filter { it.first.usingTm }.mapNotNull { it.second } - val translatedWithTm = autoTranslateUsingTm(toTmTranslate, key).filter { it.value }.keys + val translatedWithTm = autoTranslateUsingTm(toTmTranslate, key).filter { it.value }.keys - val toMtTranslate = - translations.filter { it.first.usingPrimaryMtService && !translatedWithTm.contains(it.second) } - .mapNotNull { it.second } + val toMtTranslate = + translations.filter { it.first.usingPrimaryMtService && !translatedWithTm.contains(it.second) } + .mapNotNull { it.second } - autoTranslateUsingMachineTranslation(toMtTranslate, key, isBatch) + autoTranslateUsingMachineTranslation(toMtTranslate, key, isBatch) + } + } } /** diff --git a/backend/data/src/main/kotlin/io/tolgee/util/tryUntilItDoesntBreakContraint.kt b/backend/data/src/main/kotlin/io/tolgee/util/tryUntilItDoesntBreakContraint.kt index 69a8bacc9a..8730fa0950 100644 --- a/backend/data/src/main/kotlin/io/tolgee/util/tryUntilItDoesntBreakContraint.kt +++ b/backend/data/src/main/kotlin/io/tolgee/util/tryUntilItDoesntBreakContraint.kt @@ -4,10 +4,10 @@ import jakarta.persistence.PersistenceException import org.springframework.dao.CannotAcquireLockException import org.springframework.dao.DataIntegrityViolationException -inline fun tryUntilItDoesntBreakConstraint(fn: () -> T): T { +inline fun tryUntilItDoesntBreakConstraint(maxRepeats: Int = 100, fn: () -> T): T { var exception: Exception? = null var repeats = 0 - for (it in 1..100) { + for (it in 1..maxRepeats) { try { return fn() } catch (e: Exception) { @@ -16,6 +16,7 @@ inline fun tryUntilItDoesntBreakConstraint(fn: () -> T): T { repeats++ exception = e } + else -> throw e } }