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

Migration with Multitenant (DATABASE) version:5.0.0-SNAPSHOT #380

Open
pinedu1 opened this issue Sep 19, 2024 · 0 comments
Open

Migration with Multitenant (DATABASE) version:5.0.0-SNAPSHOT #380

pinedu1 opened this issue Sep 19, 2024 · 0 comments

Comments

@pinedu1
Copy link

pinedu1 commented Sep 19, 2024

Hello!
When activating a MULTITENANT (DATABASE) project, where the configuration is as follows:

SO:

  • Operating System: Linux Fedora 39
  • Grails Version: Grails: 6.2.0
  • Plugin Version: 5.0.0-SNAPSHOT (Downloaded on: 2024-08-12)
  • Database: Postgresql12
  • JDK Version: openjdk version "17.0.12" 2024-07-16
  • ** LINK TO REPOSITORY **: https://github.com/pinedu1/pndImo

Where I downloaded the source code from the 5.x branch, compiled it, and distributed it to my local Maven repository:
/code/
#> ./gradlew publishToMavenLocal -x groovydoc
/code/

I added this compilation to my project: build.gradle
/code/
buildscript {
dependencies {
classpath 'org.grails.plugins:database-migration:5.0.0-SNAPSHOT'
}
}
sourceSets {
main {
resources {
srcDir 'grails-app/migrations'
}
}
}
...
dependencies {
...
implementation('org.grails.plugins:database-migration:5.0.0-SNAPSHOT')
}
/code/

tenantresolver: org.grails.datastore.mapping.multitenancy.TenantResolver (SUBDOMAIN)
application.properties:

Configurações da Aplicação

grails.gorm.reactor.events=false
grails.gorm.multiTenancy.mode=DATABASE
grails.gorm.multiTenancy.tenantResolverClass=org.grails.datastore.mapping.multitenancy.TenantResolver (SUBDOMAIN)
grails.plugin.databasemigration.updateAllOnStart=true
grails.plugin.databasemigration.updateOnStartFileName=changelog.groovy
grails.plugin.databasemigration.changelogFileName=changelog.groovy

Default

dataSource.url=jdbc:postgresql://localhost:5432/pnd
dataSource.driverClassName=org.postgresql.Driver
dataSource.username=pnd
dataSource.password=pnd
dataSource.pooled=true
dataSource.jmxExport=true
dataSource.dbCreate=none

Cliente: joao

dataSources.JOAO.dbCreate=none
dataSources.JOAO.password=joao
dataSources.JOAO.url=jdbc:postgresql://localhost:5432/joao
dataSources.JOAO.username=joao

Cliente: pedro

dataSources.PEDRO.dbCreate=none
dataSources.PEDRO.password=pedro
dataSources.PEDRO.url=jdbc:postgresql://localhost:5432/pedro
dataSources.PEDRO.username=pedro

Cliente: antonio

dataSources.ANTONIO.dbCreate=none
dataSources.ANTONIO.password=antonio
dataSources.ANTONIO.url=jdbc:postgresql://localhost:5432/antonio
dataSources.ANTONIO.username=antonio

Cliente: jose

dataSources.JOSE.dbCreate=none
dataSources.JOSE.password=jose
dataSources.JOSE.url=jdbc:postgresql://localhost:5432/jose
dataSources.JOSE.username=jose

It turns out that in this configuration, the MULTITENANT setup creates the DATASOURCE_NAME map as follows:
datasources.JOAO=[map of properties]
datasources.PEDRO=[map of properties]
...
datasources.ANTONIO=[map of properties]

These dataSources are collected by the plugin in:
class: DatabaseMigrationGrailsPlugin

And in line 100, there is the following method:
/* code /
private Set getDataSourceNames() {
def dataSources = config.getProperty('dataSources', Map, [:])
if (!dataSources) {
return ['dataSource']
}
Set dataSourceNames = dataSources.keySet()
if (!dataSourceNames.contains('dataSource')) {
dataSourceNames = ['dataSource'] + dataSourceNames
}
return dataSourceNames
}
/
code */

In this method, the if block:
/code/
if (!dataSourceNames.contains('dataSource')) {
dataSourceNames = ['dataSource'] + dataSourceNames
}
/code/
cannot exist in this configuration, as it creates a false entry in the dataSources set and breaks the UPDATE_ALL_ON_START functionality.
In my solution, I simply removed this piece of code (the if condition above).

A second point related to my configuration:

The class DatabaseMigrationTransactionManager also collects the databases to retrieve the TransactionManager linked to each of these tenants.
In line 27 of this class:
/code/
PlatformTransactionManager getTransactionManager() {
String dataSource = this.dataSource ?: "dataSource"
String beanName = "transactionManager"
if (dataSource != "dataSource") {
beanName += "_${dataSource}"
}
applicationContext.getBean(beanName, PlatformTransactionManager)
}
/code/
The method retrieves the transaction managers, and in my configuration, it retrieves by the object's name:
"transactionManager_JOAO"
"transactionManager_PEDRO"
...
"transactionManager_ANTONIO"

However, at some point, the dataSource name becomes degenerated into the following form:

"dataSource_JOAO"
"dataSource_PEDRO"
...
"dataSource_ANTONIO"

Where it should simply be:

"JOAO"
"PEDRO"
...
"ANTONIO"

My homemade solution was to modify the method as follows:

/code/
PlatformTransactionManager getTransactionManager() {
String dataSource = this.dataSource ?: "dataSource"
String beanName = "transactionManager"
if (dataSource.startsWith('dataSource_')) {
dataSource = dataSource.substring(dataSource.indexOf('') + 1)
}
if (dataSource != "dataSource") {
beanName += "
${dataSource}"
}
applicationContext.getBean(beanName, PlatformTransactionManager)
}
/code/

Note that I force the elimination of the 'dataSource_' substring in the following if block:
/code/
if (dataSource.startsWith('dataSource_')) {
dataSource = dataSource.substring(dataSource.indexOf('_') + 1)
}
/code/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant