Skip to content

Commit 1ddc8df

Browse files
committed
HHH-18546 Clean up any hanging BulkOperationCleanupAction after-txn callbacks on Session close
# Conflicts: # hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java
1 parent 0fe73d2 commit 1ddc8df

File tree

3 files changed

+74
-2
lines changed

3 files changed

+74
-2
lines changed

hibernate-core/src/main/java/org/hibernate/action/internal/BulkOperationCleanupAction.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,30 @@ public BeforeTransactionCompletionProcess getBeforeTransactionCompletionProcess(
220220

221221
@Override
222222
public AfterTransactionCompletionProcess getAfterTransactionCompletionProcess() {
223-
return (success, session) -> {
223+
return new BulkOperationCleanUpAfterTransactionCompletionProcess(
224+
entityCleanups,
225+
collectionCleanups,
226+
naturalIdCleanups
227+
);
228+
}
229+
230+
public static final class BulkOperationCleanUpAfterTransactionCompletionProcess
231+
implements AfterTransactionCompletionProcess {
232+
private final Set<EntityCleanup> entityCleanups;
233+
private final Set<CollectionCleanup> collectionCleanups;
234+
private final Set<NaturalIdCleanup> naturalIdCleanups;
235+
236+
public BulkOperationCleanUpAfterTransactionCompletionProcess(
237+
Set<EntityCleanup> entityCleanups,
238+
Set<CollectionCleanup> collectionCleanups,
239+
Set<NaturalIdCleanup> naturalIdCleanups) {
240+
this.entityCleanups = entityCleanups;
241+
this.collectionCleanups = collectionCleanups;
242+
this.naturalIdCleanups = naturalIdCleanups;
243+
}
244+
245+
@Override
246+
public void doAfterTransactionCompletion(boolean success, SharedSessionContractImplementor session) {
224247
for ( EntityCleanup cleanup : entityCleanups ) {
225248
cleanup.release();
226249
}
@@ -235,7 +258,7 @@ public AfterTransactionCompletionProcess getAfterTransactionCompletionProcess()
235258
cleanup.release();
236259
}
237260
collectionCleanups.clear();
238-
};
261+
}
239262
}
240263

241264
@Override

hibernate-core/src/main/java/org/hibernate/engine/spi/ActionQueue.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@
2121

2222
import org.hibernate.AssertionFailure;
2323
import org.hibernate.HibernateException;
24+
import org.hibernate.Internal;
2425
import org.hibernate.PropertyValueException;
2526
import org.hibernate.TransientObjectException;
2627
import org.hibernate.action.internal.AbstractEntityInsertAction;
2728
import org.hibernate.action.internal.BulkOperationCleanupAction;
29+
import org.hibernate.action.internal.BulkOperationCleanupAction.BulkOperationCleanUpAfterTransactionCompletionProcess;
2830
import org.hibernate.action.internal.CollectionRecreateAction;
2931
import org.hibernate.action.internal.CollectionRemoveAction;
3032
import org.hibernate.action.internal.CollectionUpdateAction;
@@ -544,6 +546,16 @@ public void afterTransactionCompletion(boolean success) {
544546
}
545547
}
546548

549+
@Internal
550+
public void executePendingBulkOperationCleanUpActions() {
551+
if ( !isTransactionCoordinatorShared ) {
552+
// Execute completion actions only in transaction owner (aka parent session).
553+
if ( afterTransactionProcesses != null ) {
554+
afterTransactionProcesses.executePendingBulkOperationCleanUpActions();
555+
}
556+
}
557+
}
558+
547559
/**
548560
* Execute any registered {@link BeforeTransactionCompletionProcess}
549561
*/
@@ -1071,6 +1083,39 @@ public void afterTransactionCompletion(boolean success) {
10711083
}
10721084
querySpacesToInvalidate.clear();
10731085
}
1086+
1087+
public void executePendingBulkOperationCleanUpActions() {
1088+
AfterTransactionCompletionProcess process;
1089+
boolean hasPendingBulkOperationCleanUpActions = false;
1090+
while ( ( process = processes.poll() ) != null ) {
1091+
if ( process instanceof BulkOperationCleanUpAfterTransactionCompletionProcess ) {
1092+
try {
1093+
hasPendingBulkOperationCleanUpActions = true;
1094+
process.doAfterTransactionCompletion( true, session );
1095+
}
1096+
catch (CacheException ce) {
1097+
LOG.unableToReleaseCacheLock( ce );
1098+
// continue loop
1099+
}
1100+
catch (Exception e) {
1101+
throw new HibernateException(
1102+
"Unable to perform afterTransactionCompletion callback: " + e.getMessage(),
1103+
e
1104+
);
1105+
}
1106+
}
1107+
}
1108+
1109+
if ( hasPendingBulkOperationCleanUpActions ) {
1110+
if ( session.getFactory().getSessionFactoryOptions().isQueryCacheEnabled() ) {
1111+
session.getFactory().getCache().getTimestampsCache().invalidate(
1112+
querySpacesToInvalidate.toArray( new String[0] ),
1113+
session
1114+
);
1115+
}
1116+
querySpacesToInvalidate.clear();
1117+
}
1118+
}
10741119
}
10751120

10761121
/**

hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,10 @@ public void closeWithoutOpenChecks() {
449449
}
450450
}
451451
finally {
452+
if ( actionQueue.hasAfterTransactionActions() ) {
453+
log.warn( "Closing session with unprocessed clean up bulk operations, forcing their execution" );
454+
actionQueue.executePendingBulkOperationCleanUpActions();
455+
}
452456
final StatisticsImplementor statistics = getSessionFactory().getStatistics();
453457
if ( statistics.isStatisticsEnabled() ) {
454458
statistics.closeSession();

0 commit comments

Comments
 (0)