Align startup of Quarkus with the regular startup to ensure boostrap locks are created.

Also fixing an issue where DBLockGlobalLockProviderFactory held on to an old session, which lead to a closed DB connection on Quarkus.

Closes #16642
This commit is contained in:
Alexander Schwartz 2023-01-27 10:23:08 +01:00 committed by Michal Hajas
parent eebbeb26bc
commit 7933f0489d
5 changed files with 17 additions and 25 deletions

View File

@ -40,7 +40,7 @@ public class LiquibaseDBLockProvider implements DBLockProvider {
private static final Logger logger = Logger.getLogger(LiquibaseDBLockProvider.class);
// 10 should be sufficient
private int DEFAULT_MAX_ATTEMPTS = 10;
private final int DEFAULT_MAX_ATTEMPTS = 10;
private final LiquibaseDBLockProviderFactory factory;
@ -83,9 +83,6 @@ public class LiquibaseDBLockProvider implements DBLockProvider {
// Assumed transaction was rolled-back and we want to start with new DB connection
private void restart() {
safeCloseConnection();
this.dbConnection = null;
this.lockService = null;
initialized = false;
lazyInit();
}
@ -187,6 +184,9 @@ public class LiquibaseDBLockProvider implements DBLockProvider {
if (dbConnection != null) {
try {
dbConnection.close();
dbConnection = null;
lockService = null;
initialized = false;
} catch (SQLException e) {
logger.warn("Failed to close connection", e);
}

View File

@ -21,7 +21,6 @@ import org.jboss.logging.Logger;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionTaskWithResult;
import org.keycloak.models.locking.GlobalLockProvider;
import org.keycloak.models.utils.KeycloakModelUtils;
import java.time.Duration;
import java.util.Objects;
@ -69,8 +68,12 @@ public class DBLockGlobalLockProvider implements GlobalLockProvider {
LOG.debug("DBLockGlobalLockProvider does not support setting timeToWaitForLock per lock.");
}
if (dbLockProvider.getCurrentLock() != null) {
throw new IllegalStateException("this lock is not reentrant, already locked for " + dbLockProvider.getCurrentLock());
}
dbLockProvider.waitForLock(stringToNamespace(lockName));
try {
dbLockProvider.waitForLock(stringToNamespace(lockName));
return task.run(session);
} finally {
releaseLock(lockName);

View File

@ -28,15 +28,11 @@ import org.keycloak.provider.EnvironmentDependentProviderFactory;
public class DBLockGlobalLockProviderFactory implements GlobalLockProviderFactory, EnvironmentDependentProviderFactory {
public static final String PROVIDER_ID = "dblock";
private DBLockManager dbLockManager;
@Override
public GlobalLockProvider create(KeycloakSession session) {
if (dbLockManager == null) {
dbLockManager = new DBLockManager(session);
dbLockManager.checkForcedUnlock();
}
DBLockManager dbLockManager = new DBLockManager(session);
dbLockManager.checkForcedUnlock();
return new DBLockGlobalLockProvider(session, dbLockManager.getDBLock());
}

View File

@ -21,8 +21,8 @@ import java.util.Set;
import java.util.stream.Collectors;
import javax.ws.rs.ApplicationPath;
import org.keycloak.exportimport.ExportImportManager;
import org.keycloak.models.utils.PostMigrationEvent;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.quarkus.runtime.integration.QuarkusKeycloakSessionFactory;
import org.keycloak.services.resources.KeycloakApplication;
import org.keycloak.quarkus.runtime.services.resources.QuarkusWelcomeResource;
@ -36,17 +36,10 @@ public class QuarkusKeycloakApplication extends KeycloakApplication {
}
@Override
protected void startup() {
public KeycloakSessionFactory createSessionFactory() {
QuarkusKeycloakSessionFactory instance = QuarkusKeycloakSessionFactory.getInstance();
sessionFactory = instance;
instance.init();
ExportImportManager exportImportManager = bootstrap();
if (exportImportManager.isRunExport()) {
exportImportManager.runExport();
}
sessionFactory.publish(new PostMigrationEvent(sessionFactory));
return instance;
}
@Override

View File

@ -82,7 +82,7 @@ public class KeycloakApplication extends Application {
protected Set<Object> singletons = new HashSet<>();
protected Set<Class<?>> classes = new HashSet<>();
protected static KeycloakSessionFactory sessionFactory;
private static KeycloakSessionFactory sessionFactory;
public KeycloakApplication() {
@ -237,7 +237,7 @@ public class KeycloakApplication extends Application {
}
public static KeycloakSessionFactory createSessionFactory() {
protected KeycloakSessionFactory createSessionFactory() {
DefaultKeycloakSessionFactory factory = new DefaultKeycloakSessionFactory();
factory.init();
return factory;