Skip to content

Commit

Permalink
feat: Batch translation state change (#1804)
Browse files Browse the repository at this point in the history
  • Loading branch information
JanCizmar authored Jul 17, 2023
1 parent c2f556a commit cf1ab51
Show file tree
Hide file tree
Showing 27 changed files with 644 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import io.swagger.v3.oas.annotations.tags.Tag
import io.tolgee.batch.BatchJobService
import io.tolgee.batch.BatchJobType
import io.tolgee.batch.request.BatchTranslateRequest
import io.tolgee.batch.request.ClearTranslationsRequest
import io.tolgee.batch.request.CopyTranslationRequest
import io.tolgee.batch.request.DeleteKeysRequest
import io.tolgee.batch.request.SetTranslationsStateStateRequest
import io.tolgee.hateoas.batch.BatchJobModel
import io.tolgee.hateoas.batch.BatchJobModelAssembler
import io.tolgee.model.batch.BatchJob
Expand Down Expand Up @@ -45,7 +48,7 @@ class StartBatchJobController(
data,
projectHolder.projectEntity,
authenticationFacade.userAccountEntity,
BatchJobType.TRANSLATION
BatchJobType.AUTO_TRANSLATION
).model
}

Expand All @@ -63,6 +66,52 @@ class StartBatchJobController(
).model
}

@PostMapping(value = ["/set-translation-state"])
@AccessWithApiKey()
@AccessWithProjectPermission(Scope.TRANSLATIONS_STATE_EDIT)
@Operation(summary = "Set translation state")
fun setTranslationState(@Valid @RequestBody data: SetTranslationsStateStateRequest): BatchJobModel {
securityService.checkKeyIdsExistAndIsFromProject(data.keyIds, projectHolder.project.id)
securityService.checkLanguageStateChangePermission(projectHolder.project.id, data.languageIds)
return batchJobService.startJob(
data,
projectHolder.projectEntity,
authenticationFacade.userAccountEntity,
BatchJobType.SET_TRANSLATIONS_STATE
).model
}

@PostMapping(value = ["/clear-translations"])
@AccessWithApiKey()
@AccessWithProjectPermission(Scope.TRANSLATIONS_EDIT)
@Operation(summary = "Clear translation values")
fun clearTranslations(@Valid @RequestBody data: ClearTranslationsRequest): BatchJobModel {
securityService.checkKeyIdsExistAndIsFromProject(data.keyIds, projectHolder.project.id)
securityService.checkLanguageTranslatePermission(projectHolder.project.id, data.languageIds)
return batchJobService.startJob(
data,
projectHolder.projectEntity,
authenticationFacade.userAccountEntity,
BatchJobType.CLEAR_TRANSLATIONS
).model
}

@PostMapping(value = ["/copy-translations"])
@AccessWithApiKey()
@AccessWithProjectPermission(Scope.TRANSLATIONS_EDIT)
@Operation(summary = "Clear translation values")
fun copyTranslations(@Valid @RequestBody data: CopyTranslationRequest): BatchJobModel {
securityService.checkKeyIdsExistAndIsFromProject(data.keyIds, projectHolder.project.id)
securityService.checkLanguageTranslatePermission(projectHolder.project.id, data.targetLanguageIds)
securityService.checkLanguageViewPermission(projectHolder.project.id, listOf(data.sourceLanguageId))
return batchJobService.startJob(
data,
projectHolder.projectEntity,
authenticationFacade.userAccountEntity,
BatchJobType.COPY_TRANSLATIONS
).model
}

val BatchJob.model
get() = batchJobModelAssembler.toModel(batchJobService.getView(this))
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ package io.tolgee.api.v2.controllers.batch

import io.tolgee.ProjectAuthControllerTest
import io.tolgee.batch.BatchJobActionService
import io.tolgee.batch.BatchJobChunkExecutionQueue
import io.tolgee.batch.BatchJobConcurrentLauncher
import io.tolgee.batch.BatchJobDto
import io.tolgee.batch.BatchJobService
import io.tolgee.batch.BatchJobType
import io.tolgee.batch.JobChunkExecutionQueue
import io.tolgee.batch.processors.TranslationChunkProcessor
import io.tolgee.batch.processors.AutoTranslationChunkProcessor
import io.tolgee.batch.request.BatchTranslateRequest
import io.tolgee.batch.state.BatchJobStateProvider
import io.tolgee.component.CurrentDateProvider
Expand Down Expand Up @@ -52,13 +52,13 @@ class BatchJobManagementControllerTest : ProjectAuthControllerTest("/v2/projects

@Autowired
@MockBean
lateinit var translationChunkProcessor: TranslationChunkProcessor
lateinit var autoTranslationChunkProcessor: AutoTranslationChunkProcessor

@Autowired
lateinit var batchJobStateProvider: BatchJobStateProvider

@Autowired
lateinit var jobChunkExecutionQueue: JobChunkExecutionQueue
lateinit var batchJobChunkExecutionQueue: BatchJobChunkExecutionQueue

@Autowired
lateinit var batchJobConcurrentLauncher: BatchJobConcurrentLauncher
Expand All @@ -69,9 +69,9 @@ class BatchJobManagementControllerTest : ProjectAuthControllerTest("/v2/projects
@BeforeEach
fun setup() {
testData = BatchJobsTestData()
jobChunkExecutionQueue.populateQueue()
whenever(translationChunkProcessor.getParams(any<BatchTranslateRequest>(), any())).thenCallRealMethod()
whenever(translationChunkProcessor.getTarget(any<BatchTranslateRequest>())).thenCallRealMethod()
batchJobChunkExecutionQueue.populateQueue()
whenever(autoTranslationChunkProcessor.getParams(any<BatchTranslateRequest>(), any())).thenCallRealMethod()
whenever(autoTranslationChunkProcessor.getTarget(any<BatchTranslateRequest>())).thenCallRealMethod()
}

@AfterEach
Expand Down Expand Up @@ -133,7 +133,7 @@ class BatchJobManagementControllerTest : ProjectAuthControllerTest("/v2/projects
val jobIds = ConcurrentHashMap.newKeySet<Long>()
var wait = true
whenever(
translationChunkProcessor.process(any(), any(), any(), any())
autoTranslationChunkProcessor.process(any(), any(), any(), any())
).then {
val id = it.getArgument<BatchJobDto>(0).id
if (jobIds.size == 2 && !jobIds.contains(id)) {
Expand Down Expand Up @@ -222,7 +222,7 @@ class BatchJobManagementControllerTest : ProjectAuthControllerTest("/v2/projects

var wait = true
whenever(
translationChunkProcessor.process(any(), any(), any(), any())
autoTranslationChunkProcessor.process(any(), any(), any(), any())
).then {
while (wait) {
Thread.sleep(100)
Expand Down Expand Up @@ -323,7 +323,7 @@ class BatchJobManagementControllerTest : ProjectAuthControllerTest("/v2/projects
},
project = testData.projectBuilder.self,
author = author,
type = BatchJobType.TRANSLATION
type = BatchJobType.AUTO_TRANSLATION
)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
package io.tolgee.api.v2.controllers.batch

import io.tolgee.ProjectAuthControllerTest
import io.tolgee.batch.BatchJobChunkExecutionQueue
import io.tolgee.development.testDataBuilder.data.BatchJobsTestData
import io.tolgee.fixtures.andAssertThatJson
import io.tolgee.fixtures.andIsOk
import io.tolgee.fixtures.isValidId
import io.tolgee.fixtures.waitForNotThrowing
import io.tolgee.model.batch.BatchJob
import io.tolgee.model.batch.BatchJobStatus
import io.tolgee.model.enums.TranslationState
import io.tolgee.model.translation.Translation
import io.tolgee.testing.ContextRecreatingTest
import io.tolgee.testing.annotations.ProjectJWTAuthTestMethod
import io.tolgee.testing.assert
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc

@AutoConfigureMockMvc
Expand All @@ -23,8 +26,12 @@ class StartBatchJobControllerTest : ProjectAuthControllerTest("/v2/projects/") {
lateinit var testData: BatchJobsTestData
var fakeBefore = false

@Autowired
lateinit var batchJobOperationQueue: BatchJobChunkExecutionQueue

@BeforeEach
fun setup() {
batchJobOperationQueue.clear()
testData = BatchJobsTestData()
fakeBefore = internalProperties.fakeMtProviders
internalProperties.fakeMtProviders = true
Expand All @@ -50,7 +57,7 @@ class StartBatchJobControllerTest : ProjectAuthControllerTest("/v2/projects/") {
@Test
@ProjectJWTAuthTestMethod
fun `it batch translates`() {
val keyCount = 100
val keyCount = 1000
val keys = testData.addTranslationOperationData(keyCount)
saveAndPrepare()

Expand Down Expand Up @@ -79,12 +86,12 @@ class StartBatchJobControllerTest : ProjectAuthControllerTest("/v2/projects/") {
val job = jobs[0]
job.status.assert.isEqualTo(BatchJobStatus.SUCCESS)
job.activityRevision.assert.isNotNull
job.activityRevision!!.modifiedEntities.assert.hasSize(200)
job.activityRevision!!.modifiedEntities.assert.hasSize(2000)
}
}

private fun waitForAllTranslated(keyIds: List<Long>, keyCount: Int) {
waitForNotThrowing(pollTime = 1000) {
waitForNotThrowing(pollTime = 1000, timeout = 60000) {
@Suppress("UNCHECKED_CAST") val czechTranslations = entityManager.createQuery(
"""
from Translation t where t.key.id in :keyIds and t.language.tag = 'cs'
Expand Down Expand Up @@ -129,4 +136,90 @@ class StartBatchJobControllerTest : ProjectAuthControllerTest("/v2/projects/") {
}
}
}

@Test
@ProjectJWTAuthTestMethod
fun `it changes translation state`() {
val keyCount = 100
val keys = testData.addStateChangeData(keyCount)
saveAndPrepare()

val allKeyIds = keys.map { it.id }.toList()
val keyIds = allKeyIds.take(10)
val allLanguageIds = testData.projectBuilder.data.languages.map { it.self.id }
val languagesToChangeStateIds = listOf(testData.germanLanguage.id, testData.englishLanguage.id)

performProjectAuthPost(
"start-batch-job/set-translation-state",
mapOf(
"keyIds" to keyIds,
"languageIds" to languagesToChangeStateIds,
"state" to "REVIEWED"
)
).andIsOk

waitForNotThrowing(pollTime = 1000, timeout = 10000) {
val all = translationService.getTranslations(
keys.map { it.id }, allLanguageIds
)
all.count { it.state == TranslationState.REVIEWED }.assert.isEqualTo(keyIds.size * 2)
}
}

@Test
@ProjectJWTAuthTestMethod
fun `it clears translations`() {
val keyCount = 1000
val keys = testData.addStateChangeData(keyCount)
saveAndPrepare()

val allKeyIds = keys.map { it.id }.toList()
val keyIds = allKeyIds.take(10)
val allLanguageIds = testData.projectBuilder.data.languages.map { it.self.id }
val languagesToClearIds = listOf(testData.germanLanguage.id, testData.englishLanguage.id)

performProjectAuthPost(
"start-batch-job/clear-translations",
mapOf(
"keyIds" to keyIds,
"languageIds" to languagesToClearIds,
)
).andIsOk

waitForNotThrowing(pollTime = 1000, timeout = 10000) {
val all = translationService.getTranslations(
keys.map { it.id }, allLanguageIds
)
all.count { it.state == TranslationState.UNTRANSLATED && it.text == null }.assert.isEqualTo(keyIds.size * 2)
}
}

@Test
@ProjectJWTAuthTestMethod
fun `it copies translations`() {
val keyCount = 1000
val keys = testData.addStateChangeData(keyCount)
saveAndPrepare()

val allKeyIds = keys.map { it.id }.toList()
val keyIds = allKeyIds.take(10)
val allLanguageIds = testData.projectBuilder.data.languages.map { it.self.id }
val languagesToChangeStateIds = listOf(testData.germanLanguage.id, testData.czechLanguage.id)

performProjectAuthPost(
"start-batch-job/copy-translations",
mapOf(
"keyIds" to keyIds,
"sourceLanguageId" to testData.englishLanguage.id,
"targetLanguageIds" to languagesToChangeStateIds,
)
).andIsOk

waitForNotThrowing(pollTime = 1000, timeout = 10000) {
val all = translationService.getTranslations(
keys.map { it.id }, allLanguageIds
)
all.count { it.text?.startsWith("en") == true }.assert.isEqualTo(allKeyIds.size + keyIds.size * 2)
}
}
}
Loading

0 comments on commit cf1ab51

Please sign in to comment.