Skip to content

Commit

Permalink
feat: Running operations & progress WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
JanCizmar committed Jun 18, 2023
1 parent b168c43 commit fcdf002
Show file tree
Hide file tree
Showing 53 changed files with 753 additions and 223 deletions.
1 change: 1 addition & 0 deletions backend/api/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ dependencies {
implementation "org.springframework.boot:spring-boot-starter-hateoas"
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation("org.springframework.boot:spring-boot-starter-security")
implementation "org.springframework.boot:spring-boot-starter-websocket"

implementation(project(':data'))
implementation(project(':misc'))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import javax.validation.Valid
@RestController
@CrossOrigin(origins = ["*"])
@RequestMapping(value = ["/v2/projects/{projectId:\\d+}/batch", "/v2/projects/batch"])
@Tag(name = "Export")
@Tag(name = "Batch operations")
@Suppress("SpringJavaInjectionPointsAutowiringInspection", "MVCPathVariableInspection")
class BatchOperationController(
private val securityService: SecurityService,
Expand All @@ -34,8 +34,13 @@ class BatchOperationController(
@AccessWithProjectPermission(Scope.TRANSLATIONS_EDIT)
@Operation(summary = "Translates provided keys to provided languages")
fun translate(@Valid @RequestBody data: BatchTranslateRequest) {
securityService.checkLanguageViewPermission(projectHolder.project.id, data.targetLanguageIds)
securityService.checkLanguageTranslatePermission(projectHolder.project.id, data.targetLanguageIds)
securityService.checkKeyIdsExistAndIsFromProject(data.keyIds, projectHolder.project.id)
batchJobService.startJob(data, authenticationFacade.userAccountEntity, BatchJobType.TRANSLATION)
batchJobService.startJob(
data,
projectHolder.projectEntity,
authenticationFacade.userAccountEntity,
BatchJobType.TRANSLATION
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ import org.redisson.Redisson
import org.redisson.api.RedissonClient
import org.springframework.boot.autoconfigure.AutoConfigureAfter
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.redis.core.RedisOperations

@Configuration
@ConditionalOnClass(Redisson::class, RedisOperations::class)
@AutoConfigureAfter(ConditionalRedissonAutoConfiguration::class)
@ConditionalOnProperty(name = ["tolgee.cache.use-redis"], havingValue = "true")
@ConditionalOnExpression("\${tolgee.cache.use-redis:false} and \${tolgee.cache.enabled:false}")
class RedisLockingConfiguration(
val redissonClient: RedissonClient
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import org.redisson.spring.cache.CacheConfig
import org.redisson.spring.cache.RedissonSpringCacheManager
import org.springframework.boot.autoconfigure.AutoConfigureAfter
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression
import org.springframework.cache.CacheManager
import org.springframework.cache.annotation.EnableCaching
import org.springframework.context.annotation.Bean
Expand All @@ -19,7 +19,7 @@ import org.springframework.data.redis.core.RedisOperations
@EnableCaching
@ConditionalOnClass(Redisson::class, RedisOperations::class)
@AutoConfigureAfter(ConditionalRedissonAutoConfiguration::class)
@ConditionalOnProperty(name = ["tolgee.cache.use-redis"], havingValue = "true")
@ConditionalOnExpression("\${tolgee.cache.use-redis:false} and \${tolgee.cache.enabled:false}")
class RedissonCacheConfiguration(private val tolgeeProperties: TolgeeProperties) {
@Bean
fun cacheManager(redissonClient: RedissonClient): CacheManager? {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package io.tolgee.websocket

import io.tolgee.activity.projectActivityView.RelationDescriptionExtractor
import io.tolgee.batch.OnBatchOperationProgress
import io.tolgee.batch.WebsocketProgressInfo
import io.tolgee.events.OnProjectActivityStoredEvent
import io.tolgee.hateoas.user_account.SimpleUserAccountModelAssembler
import io.tolgee.model.activity.ActivityModifiedEntity
Expand Down Expand Up @@ -74,6 +76,20 @@ class ActivityWebsocketListener(
)
}

@EventListener(OnBatchOperationProgress::class)
fun onBatchOperationProgress(event: OnBatchOperationProgress) {
websocketEventPublisher(
"/projects/${event.job.project.id}/${Types.BATCH_OPERATION_PROGRESS.typeName}",
WebsocketEvent(
actor = getActorInfo(event.job.author?.id),
data = WebsocketProgressInfo(event.job.id, event.processed, event.total),
sourceActivity = null,
activityId = null,
dataCollapsed = false
)
)
}

private fun getModifiedEntityView(it: ActivityModifiedEntity): MutableMap<String, Any?> {
val data = mutableMapOf<String, Any?>("id" to it.entityId)
it.describingData?.let { describingData -> data.putAll(describingData) }
Expand Down
8 changes: 5 additions & 3 deletions backend/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ dependencies {
implementation("org.springframework.ldap:spring-ldap-core")
implementation("org.springframework.security:spring-security-ldap")
implementation "org.springframework.boot:spring-boot-starter-batch"
implementation "org.springframework.boot:spring-boot-starter-websocket"
implementation "org.springframework.boot:spring-boot-starter-actuator"

/**
* TESTING
Expand All @@ -95,6 +95,7 @@ dependencies {
testImplementation("io.socket:socket.io-client:1.0.1")
testImplementation group: 'org.springframework.batch', name: 'spring-batch-test', version: '4.3.5'
testImplementation libs.sendInBlue
testImplementation "org.springframework.boot:spring-boot-starter-websocket"

/**
* MISC
Expand All @@ -105,8 +106,9 @@ dependencies {
implementation libs.amazonSTS
implementation libs.icu4j
implementation libs.jacksonModuleKotlin
implementation libs.redissonSpringBootStarter
implementation libs.redissonSpringData

testApi libs.redissonSpringBootStarter
testApi libs.redissonSpringData

/**
* KOTLIN
Expand Down
28 changes: 0 additions & 28 deletions backend/app/src/main/kotlin/io/tolgee/Application.kt
Original file line number Diff line number Diff line change
@@ -1,42 +1,14 @@
package io.tolgee

import io.tolgee.configuration.Banner
import org.redisson.spring.starter.RedissonAutoConfiguration
import org.springframework.boot.SpringApplication
import org.springframework.boot.actuate.autoconfigure.endpoint.jmx.JmxEndpointAutoConfiguration
import org.springframework.boot.actuate.autoconfigure.info.InfoContributorAutoConfiguration
import org.springframework.boot.actuate.autoconfigure.liquibase.LiquibaseEndpointAutoConfiguration
import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration
import org.springframework.boot.actuate.autoconfigure.metrics.JvmMetricsAutoConfiguration
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsEndpointAutoConfiguration
import org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration
import org.springframework.boot.actuate.autoconfigure.metrics.startup.StartupTimeMetricsListenerAutoConfiguration
import org.springframework.boot.actuate.autoconfigure.metrics.web.tomcat.TomcatMetricsAutoConfiguration
import org.springframework.boot.actuate.autoconfigure.system.DiskSpaceHealthContributorAutoConfiguration
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.autoconfigure.domain.EntityScan
import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration
import org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration
import org.springframework.boot.context.properties.ConfigurationPropertiesScan
import org.springframework.data.jpa.repository.config.EnableJpaAuditing
import org.springframework.data.jpa.repository.config.EnableJpaRepositories

@SpringBootApplication(
exclude = [
RedissonAutoConfiguration::class,
CompositeMeterRegistryAutoConfiguration::class,
DataSourcePoolMetricsAutoConfiguration::class,
DiskSpaceHealthContributorAutoConfiguration::class,
InfoContributorAutoConfiguration::class,
JmxAutoConfiguration::class,
JvmMetricsAutoConfiguration::class,
JmxEndpointAutoConfiguration::class,
LdapAutoConfiguration::class,
LiquibaseEndpointAutoConfiguration::class,
MetricsEndpointAutoConfiguration::class,
StartupTimeMetricsListenerAutoConfiguration::class,
TomcatMetricsAutoConfiguration::class,
],
scanBasePackages = ["io.tolgee"]
)
@EnableJpaAuditing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ package io.tolgee.configuration

import io.tolgee.component.LockingProvider
import io.tolgee.component.lockingProvider.SimpleLockingProvider
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration
@ConditionalOnExpression("\${tolgee.cache.use-redis:false} == false")
@ConditionalOnMissingBean(LockingProvider::class)
class SimpleLockingConfiguration {
@Bean
fun getLockingProvider(): LockingProvider {
Expand Down

This file was deleted.

This file was deleted.

2 changes: 2 additions & 0 deletions backend/app/src/main/resources/application.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
spring:
autoconfigure:
exclude: org.redisson.spring.starter.RedissonAutoConfiguration, org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
data:
redis:
repositories:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package io.tolgee.api.v2.controllers.batch

import io.tolgee.ProjectAuthControllerTest
import io.tolgee.development.testDataBuilder.data.BatchOperationsTestData
import io.tolgee.fixtures.andIsOk
import io.tolgee.fixtures.waitForNotThrowing
import io.tolgee.model.translation.Translation
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.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
import org.springframework.boot.test.context.SpringBootTest

@SpringBootTest
@AutoConfigureMockMvc
class BatchOperationControllerTest : ProjectAuthControllerTest("/v2/projects/") {
lateinit var testData: BatchOperationsTestData
var fakeBefore = false

@BeforeEach
fun setup() {
testData = BatchOperationsTestData()
fakeBefore = internalProperties.fakeMtProviders
internalProperties.fakeMtProviders = true
machineTranslationProperties.google.apiKey = "mock"
machineTranslationProperties.google.defaultEnabled = true
machineTranslationProperties.google.defaultPrimary = true
machineTranslationProperties.aws.defaultEnabled = false
machineTranslationProperties.aws.accessKey = "mock"
machineTranslationProperties.aws.secretKey = "mock"
}

@AfterEach
fun after() {
internalProperties.fakeMtProviders = fakeBefore
}

fun saveAndPrepare() {
testDataService.saveTestData(testData.root)
userAccount = testData.user
this.projectSupplier = { testData.projectBuilder.self }
}

@Test
@ProjectJWTAuthTestMethod
fun `it batch translates`() {
val keyCount = 100
val keys = testData.addTranslationOperationData(keyCount)
saveAndPrepare()

val keyIds = keys.map { it.id }.toList()

performProjectAuthPut(
"batch/translate",
mapOf(
"keyIds" to keyIds,
"targetLanguageIds" to listOf(
testData.projectBuilder.getLanguageByTag("cs")!!.self.id,
testData.projectBuilder.getLanguageByTag("de")!!.self.id
)
)
).andIsOk

waitForNotThrowing(pollTime = 1000) {
@Suppress("UNCHECKED_CAST") val czechTranslations = entityManager.createQuery(
"""
from Translation t where t.key.id in :keyIds and t.language.tag = 'cs'
""".trimIndent()
).setParameter("keyIds", keyIds).resultList as List<Translation>
czechTranslations.assert.hasSize(keyCount)
czechTranslations.forEach {
it.text.assert.contains("translated with GOOGLE from en to cs")
}
}
}
}
Loading

0 comments on commit fcdf002

Please sign in to comment.