Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Cockroach DB support #1405

Draft
wants to merge 19 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ jobs:
fail-fast: false
matrix:
command: [ "server-app:runContextRecreatingTests", "server-app:runStandardTests", "data:test" ]
profile: [ "default", "cockroach" ]
steps:
- uses: actions/checkout@v2

Expand Down Expand Up @@ -91,7 +92,7 @@ jobs:
tar -xzf ~/backend-testing.tgz ./backend/testing/build

- name: Run backend tests
run: ./gradlew ${{ matrix.command }}
run: SPRING_PROFILES_ACTIVE=${{ matrix.profile }} ./gradlew ${{ matrix.command }}
env:
SKIP_SERVER_BUILD: true

Expand All @@ -104,7 +105,7 @@ jobs:
- uses: actions/upload-artifact@v2
if: always()
with:
name: backend_test_reports_${{ steps.version.outputs.reportName }}
name: backend_test_reports_${{ matrix.profile }}
path: |
./**/build/reports/**/*

Expand All @@ -117,6 +118,7 @@ jobs:
matrix:
total_jobs: [ 10 ]
job_index: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
profile: ["cockroach", "default"]
steps:
- uses: actions/checkout@v2

Expand Down Expand Up @@ -187,6 +189,7 @@ jobs:
SKIP_INSTALL_E2E_DEPS: true
E2E_TOTAL_JOBS: ${{matrix.total_jobs}}
E2E_JOB_INDEX: ${{matrix.job_index}}
SPRING_PROFILES_ACTIVE: ${{matrix.profile}}

- uses: actions/upload-artifact@v2
if: failure()
Expand Down
5 changes: 4 additions & 1 deletion backend/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -167,19 +167,22 @@ dependencies {
test {
useJUnitPlatform()
maxHeapSize = "2048m"
//maxParallelForks = (int) (Runtime.runtime.availableProcessors() / 2 + 1)
}

task runContextRecreatingTests(type: Test, group: 'verification') {
dependsOn "startCockroachDb"
useJUnitPlatform {
includeTags "contextRecreating"
}
finalizedBy "stopCockroachDb"
}

task runStandardTests(type: Test, group: 'verification') {
dependsOn "startCockroachDb"
useJUnitPlatform {
excludeTags "contextRecreating"
}
finalizedBy "stopCockroachDb"
}

springBoot {
Expand Down
2 changes: 2 additions & 0 deletions backend/app/src/main/kotlin/io/tolgee/Application.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ 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
import org.springframework.retry.annotation.EnableRetry

@SpringBootApplication(
exclude = [
Expand All @@ -43,6 +44,7 @@ import org.springframework.data.jpa.repository.config.EnableJpaRepositories
@EntityScan("io.tolgee.model")
@ConfigurationPropertiesScan
@EnableJpaRepositories("io.tolgee.repository")
@EnableRetry
class Application {
companion object {
@JvmStatic
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ class V2ImportController(
}

private fun checkLanguageFromProject(languageId: Long): Language {
val existingLanguage = languageService.findById(languageId).orElse(null) ?: throw NotFoundException()
val existingLanguage = languageService.find(languageId) ?: throw NotFoundException()
if (existingLanguage.project.id != projectHolder.project.id) {
throw BadRequestException(io.tolgee.constants.Message.IMPORT_LANGUAGE_NOT_FROM_PROJECT)
}
Expand Down
9 changes: 9 additions & 0 deletions backend/app/src/main/resources/application-cockroach.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
spring:
datasource:
url: jdbc:postgresql://cockroachdb:26257/postgres
username: root
tolgee:
database:
type: COCKROACH
postgres-autostart:
enabled: false
3 changes: 3 additions & 0 deletions backend/app/src/main/resources/application-devcockroach.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
spring:
datasource:
url: jdbc:postgresql://localhost:26257/postgres
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ class TagsControllerTest : ProjectAuthControllerTest("/v2/projects/") {
performProjectAuthGet("tags?page=5").andAssertThatJson {
node("_embedded.tags") {
isArray.hasSize(20)
node("[0].name").isEqualTo("tag 14 12")
node("[19].name").isEqualTo("tag 15 10")
node("[0].name").isEqualTo("tag 05 19")
node("[19].name").isEqualTo("tag 06 18")
}
}
}
Expand All @@ -61,7 +61,7 @@ class TagsControllerTest : ProjectAuthControllerTest("/v2/projects/") {
node("_embedded.tags") {
isArray.hasSize(20)
node("[0].id").isValidId
node("[0].name").isEqualTo("tag 11 3")
node("[0].name").isEqualTo("tag 02 19")
}
}
}
Expand Down
9 changes: 9 additions & 0 deletions backend/app/src/test/resources/application-cockroach.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
spring:
datasource:
url: jdbc:postgresql://localhost:26257/postgres
username: root
tolgee:
database:
type: COCKROACH
postgres-autostart:
enabled: false
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class ActivityInterceptor : EmptyInterceptor() {
propertyNames: Array<out String>?,
types: Array<out Type>?
): Boolean {
preCommitEventsPublisher.onPersist(entity)
interceptedEventsManager.onFieldModificationsActivity(
entity, state, null, propertyNames, RevisionType.ADD
)
Expand All @@ -39,6 +40,7 @@ class ActivityInterceptor : EmptyInterceptor() {
propertyNames: Array<out String>?,
types: Array<out Type>?
) {
preCommitEventsPublisher.onDelete(entity)
interceptedEventsManager.onFieldModificationsActivity(
entity, null, state, propertyNames, RevisionType.DEL
)
Expand All @@ -52,6 +54,7 @@ class ActivityInterceptor : EmptyInterceptor() {
propertyNames: Array<out String>?,
types: Array<out Type>?
): Boolean {
preCommitEventsPublisher.onUpdate(entity)
interceptedEventsManager.onFieldModificationsActivity(
entity,
currentState,
Expand All @@ -76,4 +79,7 @@ class ActivityInterceptor : EmptyInterceptor() {

val interceptedEventsManager: InterceptedEventsManager
get() = applicationContext.getBean(InterceptedEventsManager::class.java)

val preCommitEventsPublisher: PreCommitEventPublisher
get() = applicationContext.getBean(PreCommitEventPublisher::class.java)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package io.tolgee.activity.iterceptor

import io.tolgee.events.OnEntityPreDelete
import io.tolgee.events.OnEntityPrePersist
import io.tolgee.events.OnEntityPreUpdate
import org.springframework.context.ApplicationContext
import org.springframework.stereotype.Component

@Component
class PreCommitEventPublisher(private val applicationContext: ApplicationContext) {

fun onPersist(entity: Any?) {
applicationContext.publishEvent(OnEntityPrePersist(this, entity))
}

fun onUpdate(entity: Any?) {
applicationContext.publishEvent(OnEntityPreUpdate(this, entity))
}

fun onDelete(entity: Any?) {
applicationContext.publishEvent(OnEntityPreDelete(this, entity))
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.tolgee.configuration

import io.tolgee.configuration.tolgee.DatabaseProperties
import io.tolgee.configuration.tolgee.TolgeeProperties
import liquibase.integration.spring.SpringLiquibase
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
Expand All @@ -10,13 +12,15 @@ import javax.sql.DataSource
class LiquibaseConfiguration {
@Bean
@Primary
fun liquibase(dataSource: DataSource): SpringLiquibase {
fun liquibase(dataSource: DataSource, properties: TolgeeProperties): SpringLiquibase {
val liquibase = SpringLiquibase()

liquibase.dataSource = dataSource
liquibase.changeLog = "classpath:db/changelog/schema.xml"
liquibase.defaultSchema = "public"

if (properties.database.type == DatabaseProperties.DatabaseType.COCKROACH) {
liquibase.setChangeLogParameters(mapOf("isCockroach" to "true"))
}
return liquibase
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package io.tolgee.configuration.tolgee

import org.springframework.boot.context.properties.ConfigurationProperties

@ConfigurationProperties(prefix = "tolgee.database")
class DatabaseProperties {
var type: DatabaseType = DatabaseType.POSTGRES

enum class DatabaseType {
COCKROACH, POSTGRES
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,6 @@ open class TolgeeProperties(
var postgresAutostart: PostgresAutostartProperties = PostgresAutostartProperties(),
var sendInBlueProperties: SendInBlueProperties = SendInBlueProperties(),
open var import: ImportProperties = ImportProperties(),
var rateLimitProperties: RateLimitProperties = RateLimitProperties()
var rateLimitProperties: RateLimitProperties = RateLimitProperties(),
var database: DatabaseProperties = DatabaseProperties()
)
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,18 @@ class TagsTestData : BaseTestData("tagsTestUser", "tagsTestProject") {
}
}
(1..20).forEach { keyNum ->
val keyNumString = keyNum.toString().padStart(2, '0')
addKey {
name = "test key $keyNum"
name = "test key $keyNumString"
}.build {
addMeta {
self {
(1..20).forEach { tagNum ->
val tagNumString = tagNum.toString().padStart(2, '0')
tags.add(
Tag().apply {
project = projectBuilder.self
name = "tag $keyNum $tagNum"
name = "tag $keyNumString $tagNumString"
}
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.tolgee.events

import io.tolgee.activity.iterceptor.PreCommitEventPublisher
import org.springframework.context.ApplicationEvent

class OnEntityPreDelete(
val source: PreCommitEventPublisher,
val entity: Any?
) : ApplicationEvent(source)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.tolgee.events

import io.tolgee.activity.iterceptor.PreCommitEventPublisher
import org.springframework.context.ApplicationEvent

class OnEntityPrePersist(
val source: PreCommitEventPublisher,
val entity: Any?
) : ApplicationEvent(source)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.tolgee.events

import io.tolgee.activity.iterceptor.PreCommitEventPublisher
import org.springframework.context.ApplicationEvent

class OnEntityPreUpdate(
val source: PreCommitEventPublisher,
val entity: Any?
) : ApplicationEvent(source)
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ interface ActivityRevisionRepository : JpaRepository<ActivityRevision, Long> {

@Query(
"""
select count(ar.id) as count, function('to_char', ar.timestamp, 'yyyy-MM-dd') as date
select count(ar.id) as count, cast(cast(ar.timestamp as date) as text) as date
from ActivityRevision ar
where ar.projectId = :projectId
group by date
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import org.springframework.data.domain.Page
import org.springframework.data.domain.PageRequest
import org.springframework.data.domain.Pageable
import org.springframework.data.domain.Sort
import org.springframework.retry.annotation.Retryable
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.util.*
Expand Down Expand Up @@ -78,6 +79,8 @@ class LanguageService(
return find(id) ?: throw NotFoundException(Message.LANGUAGE_NOT_FOUND)
}

@Transactional
@Retryable()
fun find(id: Long): Language? {
return languageRepository.findById(id).orElse(null)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package io.tolgee.service

import org.hibernate.FlushMode
import org.hibernate.Session
import org.springframework.stereotype.Service
import java.math.BigDecimal
import javax.persistence.EntityManager
import javax.persistence.FlushModeType

@Service
class OrganizationStatsService(
private val entityManager: EntityManager
private val entityManager: EntityManager,
) {
fun getProjectLanguageCount(projectId: Long): Long {
return entityManager
Expand All @@ -33,9 +36,13 @@ class OrganizationStatsService(
}

fun getCurrentTranslationCount(organizationId: Long): Long {
val result = entityManager.createNativeQuery(
"""
select
val session = entityManager.unwrap(Session::class.java)
return try {
session.hibernateFlushMode = FlushMode.MANUAL
session.flushMode = FlushModeType.COMMIT
val query = session.createNativeQuery(
"""
select
(select sum(keyCount * languageCount) as translationCount
from (select p.id as projectId, count(l.id) as languageCount
from project as p
Expand All @@ -47,8 +54,13 @@ class OrganizationStatsService(
join key as k on k.project_id = p.id
where p.organization_owner_id = :organizationId
group by p.id) as keyCounts on keyCounts.projectId = languageCounts.projectId)
""".trimIndent()
).setParameter("organizationId", organizationId).singleResult as BigDecimal? ?: 0
return result.toLong()
""".trimIndent()
).setParameter("organizationId", organizationId)
val result = query.singleResult as BigDecimal? ?: 0
result.toLong()
} finally {
session.hibernateFlushMode = FlushMode.AUTO
session.flushMode = FlushModeType.AUTO
}
}
}
Loading