+
Skip to content

Conversation

ahus1
Copy link
Contributor

@ahus1 ahus1 commented Oct 10, 2025

Closes #43362

@ahus1 ahus1 self-assigned this Oct 10, 2025
@ahus1 ahus1 force-pushed the is-43362-remove-em-flush-calls branch from 48b6395 to 5eabd3e Compare October 10, 2025 13:48
Closes keycloak#43362

Signed-off-by: Alexander Schwartz <alexander.schwartz@ibm.com>
@ahus1 ahus1 force-pushed the is-43362-remove-em-flush-calls branch from 5eabd3e to 49dbbc5 Compare October 10, 2025 14:46
@ahus1
Copy link
Contributor Author

ahus1 commented Oct 10, 2025

@shawkins - may I ask you to review this PR, or should I ask a different team? Thanks!

@ahus1 ahus1 marked this pull request as ready for review October 10, 2025 17:27
@ahus1 ahus1 requested a review from a team as a code owner October 10, 2025 17:27
@ahus1 ahus1 enabled auto-merge (squash) October 10, 2025 17:27
Copy link
Contributor

@shawkins shawkins left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, just added a couple of general thoughts. Ideally we can revisit the excess flushing more systematically. If I recall it was roughly doubling the time that it takes to perform an import.

action.setPriority(model.getPriority());
realm.getRequiredActionProviders().add(action);
em.persist(action);
em.flush();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems fine. In general there are a lot of flushes in RealmAdapter that seem ad hoc beyond the pattern of persist / flush / detach.

Comment on lines +1323 to +1343
Set<ClientScopeClientMappingEntity> clientScopeEntities = clientScopes.stream()
.filter(clientScope -> !existingClientScopes.containsKey(clientScope.getName()))
.filter(clientScope -> {
if (clientScope.getProtocol() == null) {
// set default protocol if not set. Otherwise, we will get a NullPointer
clientScope.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
}
return acceptedClientProtocols.contains(clientScope.getProtocol());
})
.map(clientScope -> {
ClientScopeClientMappingEntity entity = new ClientScopeClientMappingEntity();
entity.setClientScopeId(clientScope.getId());
entity.setClientId(client.getId());
entity.setDefaultScope(defaultScope);
em.persist(entity);
return entity;
}).collect(Collectors.toSet());
if (!clientScopeEntities.isEmpty()) {
em.flush();
clientScopeEntities.forEach(entity -> em.detach(entity));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In situations where you have less direct control over the transitive calls, the pattern using the EntityManagers logic looks like:

Suggested change
Set<ClientScopeClientMappingEntity> clientScopeEntities = clientScopes.stream()
.filter(clientScope -> !existingClientScopes.containsKey(clientScope.getName()))
.filter(clientScope -> {
if (clientScope.getProtocol() == null) {
// set default protocol if not set. Otherwise, we will get a NullPointer
clientScope.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
}
return acceptedClientProtocols.contains(clientScope.getProtocol());
})
.map(clientScope -> {
ClientScopeClientMappingEntity entity = new ClientScopeClientMappingEntity();
entity.setClientScopeId(clientScope.getId());
entity.setClientId(client.getId());
entity.setDefaultScope(defaultScope);
em.persist(entity);
return entity;
}).collect(Collectors.toSet());
if (!clientScopeEntities.isEmpty()) {
em.flush();
clientScopeEntities.forEach(entity -> em.detach(entity));
}
EntityManagers.runInBatch(session, () -> {
clientScopes.stream()
.filter(clientScope -> !existingClientScopes.containsKey(clientScope.getName()))
.filter(clientScope -> {
if (clientScope.getProtocol() == null) {
// set default protocol if not set. Otherwise, we will get a NullPointer
clientScope.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
}
return acceptedClientProtocols.contains(clientScope.getProtocol());
})
.forEach(clientScope -> {
ClientScopeClientMappingEntity entity = new ClientScopeClientMappingEntity();
entity.setClientScopeId(clientScope.getId());
entity.setClientId(client.getId());
entity.setDefaultScope(defaultScope);
em.persist(entity);
});
}, true);

However that will generally result in 2 flushes though, rather than the single flush that is done here.

@ahus1
Copy link
Contributor Author

ahus1 commented Oct 13, 2025

@shawkins - thank you for reviewing; this was just about some small improvements I found while working on something else.

@shawkins
Copy link
Contributor

@shawkins - thank you for reviewing; this was just about some small improvements I found while working on something else.

Yes, that is clear from the issue. Just thought it was worth mentioning how broadly flush calls are being used, and another approach that also prevents the accumulation of entities in the peristence context.

@ahus1
Copy link
Contributor Author

ahus1 commented Oct 14, 2025

I'll handle this another time when I have more time to dive into this.

@ahus1 ahus1 closed this Oct 14, 2025
auto-merge was automatically disabled October 14, 2025 08:22

Pull request was closed

@ahus1 ahus1 reopened this Oct 14, 2025
@ahus1
Copy link
Contributor Author

ahus1 commented Oct 14, 2025

@mposolda / @pedroigor / @vramik - as we've briefly discussed it in the chat today: These seem to be some small changes and the CI still passes. So I want to proceed with this changes, but don't introduce any other changes beyond that.

This is an attempt to make use of some analysis I did to test how Keycloak performs with a lot of realms, so I didn't want to waste it as the result was already there.

Please let me know if you agree, and if this PR should be merged as is. Any additional work should be tackled in a different issue and should be planned for separately.

Copy link

@keycloak-github-bot keycloak-github-bot bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unreported flaky test detected, please review

@keycloak-github-bot
Copy link

Unreported flaky test detected

If the flaky tests below are affected by the changes, please review and update the changes accordingly. Otherwise, a maintainer should report the flaky tests prior to merging the PR.

org.keycloak.testsuite.account.AccountRestServiceTest#listApplicationsWithoutPermission

Keycloak CI - Java Distribution IT (windows-latest - temurin - 17)

org.openqa.selenium.TimeoutException: 
java.net.SocketTimeoutException: Read timed out
Build info: version: '4.28.1', revision: '73f5ad48a2'
System info: os.name: 'Windows Server 2025', os.arch: 'amd64', os.version: '10.0', java.version: '17.0.16'
Driver info: driver.version: HtmlUnitDriver
...

Report flaky test

Copy link

@keycloak-github-bot keycloak-github-bot bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unreported flaky test detected, please review

@keycloak-github-bot
Copy link

Unreported flaky test detected

If the flaky tests below are affected by the changes, please review and update the changes accordingly. Otherwise, a maintainer should report the flaky tests prior to merging the PR.

org.keycloak.testsuite.account.AccountRestServiceTest#listApplicationsWithoutPermission

Keycloak CI - Java Distribution IT (windows-latest - temurin - 17)

org.openqa.selenium.TimeoutException: 
java.net.SocketTimeoutException: Read timed out
Build info: version: '4.28.1', revision: '73f5ad48a2'
System info: os.name: 'Windows Server 2025', os.arch: 'amd64', os.version: '10.0', java.version: '17.0.16'
Driver info: driver.version: HtmlUnitDriver
...

Report flaky test

Copy link
Contributor

@vramik vramik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you @ahus1 for preparing the PR

@ahus1 ahus1 merged commit 02dfb4b into keycloak:main Oct 15, 2025
206 of 208 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reduce the number entity manager flushes when creating a realm

4 participants

点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载