javatransactionstimeoutkeycloakkeycloak-spi

Keycloak custom spi - custom transaction timeout


I am trying to do a sync process via the keycloak ImportSynchronization interface. (wildlfy 18.0.1.Final) it provides the following method to override:

    @Override
    public SynchronizationResult sync(
        final KeycloakSessionFactory sessionFactory,
        final String realmId,
        final UserStorageProviderModel model) {
    ...}

This sync process takes much more time than our default transaction timeout (300 sec = 5 min).

I am aware of this possible opportunity:

            <core-environment node-identifier="${jboss.tx.node.id:1}">
                <process-id>
                    <uuid/>
                </process-id>
            </core-environment>
            <recovery-environment socket-binding="txn-recovery-environment" status-socket-binding="txn-status-manager"/>
            <coordinator-environment statistics-enabled="${wildfly.transactions.statistics-enabled:${wildfly.statistics-enabled:false}}"
                                     default-timeout="${env.TRANSACTION_TIMEOUT_SEC:300}"/>
            <object-store path="tx-object-store" relative-to="jboss.server.data.dir"/>
        </subsystem>

BUT this is not what I want, unfortunately.

I don't want to increase the timeout for all of our processes, just for this one. Meaning I am searching for a custom transaction timeout solution. (something like @TransactionTimeout...)


I've tried the following


@Override
    public SynchronizationResult doCleanup(final KeycloakSessionFactory keycloakSessionFactory, final String realmId)  {
        final SynchronizationResult synchronizationResult = new SynchronizationResult();

        try {

            final RealmModel realmModel = this.getRealmModelInTx(realmId, keycloakSessionFactory);

            Thread.sleep(<more than tx timeout>);

            final int userEntityCountBeforeCleanup = this.getUserCountInTx(realmModel, keycloakSessionFactory);
...}

and in both methods, I created a new keycloakSession and a new transactionManager and closed them like here:

    private CleanupTransactionHandler createSession(final KeycloakSessionFactory  keycloakSessionFactory) {
        KeycloakTransactionManager transactionManager = null;
        final KeycloakSession keycloakSession = keycloakSessionFactory.create();

        log.tracef("KeycloakSession has been created [%s].", keycloakSession.hashCode());
        transactionManager = keycloakSession.getTransactionManager();
        transactionManager.begin();
        log.tracef("KeycloakTransactionManager's transaction has been begun [%s].", transactionManager.hashCode());
        return new CleanupTransactionHandler(keycloakSession,transactionManager);
    }

    private void closeSession(final KeycloakSession keycloakSession) {
        keycloakSession.close();
        log.tracef("KeycloakSession has been closed [%s].", keycloakSession.hashCode());
    }

    private void rollback(final KeycloakTransactionManager keycloakTransactionManager) {
        keycloakTransactionManager.rollback();
        log.tracef("KeycloakTransactionManager's transaction has been rolled back [%s].", keycloakTransactionManager.hashCode());
    }

Solution

  • If someone wonders how this might be fixed in Keycloak 21.1.1++, here is what I did:

    quarkus.transaction-manager.default-transaction-timeout=PT6H
    

    The quarkus.properties file must be copied to the conf folder in the Keycloak distribution.

    Sources: tons of debugging :)

    https://www.keycloak.org/migration/migrating-to-quarkus

    https://quarkus.io/guides/transaction#configuring-the-transaction-timeout

    Regarding the duration format:

    https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html#parse-java.lang.CharSequence-