io.ebeaninternal.server.transaction.PostCommitProcessing Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ebean Show documentation
Show all versions of ebean Show documentation
composite of common runtime dependencies for all platforms
package io.ebeaninternal.server.transaction;
import io.ebean.annotation.DocStoreMode;
import io.ebeaninternal.api.SpiTransaction;
import io.ebeaninternal.api.TransactionEvent;
import io.ebeaninternal.api.TransactionEventTable;
import io.ebeaninternal.api.TransactionEventTable.TableIUD;
import io.ebeaninternal.server.cache.CacheChangeSet;
import io.ebeaninternal.server.cluster.ClusterManager;
import io.ebeaninternal.server.core.PersistRequestBean;
import io.ebeaninternal.server.deploy.BeanDescriptorManager;
import io.ebeanservice.docstore.api.DocStoreUpdates;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
/**
* Performs post commit processing using a background thread.
*
* This includes Cluster notification, and BeanPersistListeners.
*
*/
public final class PostCommitProcessing {
private static final Logger logger = LoggerFactory.getLogger(PostCommitProcessing.class);
private final ClusterManager clusterManager;
private final TransactionEvent event;
private final String serverName;
private final TransactionManager manager;
private final List> persistBeanRequests;
private final BeanPersistIdMap beanPersistIdMap;
private final RemoteTransactionEvent remoteTransactionEvent;
private final DeleteByIdMap deleteByIdMap;
private final DocStoreMode txnDocStoreMode;
private final int txnDocStoreBatchSize;
private CacheChangeSet cacheChanges;
/**
* Create for an external modification.
*/
public PostCommitProcessing(ClusterManager clusterManager, TransactionManager manager, TransactionEvent event) {
this.clusterManager = clusterManager;
this.manager = manager;
this.serverName = manager.getServerName();
this.txnDocStoreMode = DocStoreMode.IGNORE;
this.txnDocStoreBatchSize = 0;
this.event = event;
this.deleteByIdMap = event.getDeleteByIdMap();
this.persistBeanRequests = event.getPersistRequestBeans();
this.beanPersistIdMap = createBeanPersistIdMap();
this.remoteTransactionEvent = createRemoteTransactionEvent();
}
/**
* Create for a transaction.
*/
public PostCommitProcessing(ClusterManager clusterManager, TransactionManager manager, SpiTransaction transaction) {
this.clusterManager = clusterManager;
this.manager = manager;
this.serverName = manager.getServerName();
this.txnDocStoreMode = transaction.getDocStoreMode();
this.txnDocStoreBatchSize = transaction.getDocStoreBatchSize();
this.event = transaction.getEvent();
this.deleteByIdMap = event.getDeleteByIdMap();
this.persistBeanRequests = event.getPersistRequestBeans();
this.beanPersistIdMap = createBeanPersistIdMap();
this.remoteTransactionEvent = createRemoteTransactionEvent();
}
/**
* Notify the local part of L2 cache.
*/
void notifyLocalCache() {
processTableEvents(event.getEventTables());
if (manager.localL2Caching) {
// process l2 cache changes in foreground
processCacheChanges(event.buildCacheChanges(manager.viewInvalidation));
} else {
// collect l2 cache changes for delayed background processing
cacheChanges = event.buildCacheChanges(manager.viewInvalidation);
}
}
/**
* Table events are where SQL or external tools are used. In this case the
* cache is notified based on the table name (rather than bean type).
*/
private void processTableEvents(TransactionEventTable tableEvents) {
if (tableEvents != null && !tableEvents.isEmpty()) {
// notify cache with table based changes
BeanDescriptorManager dm = manager.getBeanDescriptorManager();
for (TableIUD tableIUD : tableEvents.values()) {
dm.cacheNotify(tableIUD);
}
}
}
/**
* Process any document store updates.
*/
private void processDocStoreUpdates() {
if (isDocStoreUpdate()) {
// collect 'bulk update' and 'queue' events
DocStoreUpdates docStoreUpdates = new DocStoreUpdates();
event.addDocStoreUpdates(docStoreUpdates);
if (deleteByIdMap != null) {
deleteByIdMap.addDocStoreUpdates(docStoreUpdates, txnDocStoreMode);
}
if (!docStoreUpdates.isEmpty()) {
// send to docstore / ElasticSearch and/or queue
manager.processDocStoreUpdates(docStoreUpdates, txnDocStoreBatchSize);
}
}
}
/**
* Return true if updates to the document store occur for this transaction.
*/
private boolean isDocStoreUpdate() {
return manager.isDocStoreActive() && (txnDocStoreMode == null || txnDocStoreMode != DocStoreMode.IGNORE);
}
private void notifyCluster() {
if (remoteTransactionEvent != null && !remoteTransactionEvent.isEmpty()) {
// send the interesting events to the cluster
if (logger.isDebugEnabled()) {
logger.debug("Cluster Send: {}", remoteTransactionEvent);
}
clusterManager.broadcast(remoteTransactionEvent);
}
}
/**
* In background notify persist listeners, cluster and document store.
*/
Runnable backgroundNotify() {
return () -> {
processCacheChanges(cacheChanges);
localPersistListenersNotify();
notifyCluster();
processDocStoreUpdates();
};
}
/**
* Apply the changes to the L2 caches.
*/
private void processCacheChanges(CacheChangeSet cacheChanges) {
if (cacheChanges != null) {
manager.processViewInvalidation(cacheChanges.apply());
}
}
private void localPersistListenersNotify() {
if (persistBeanRequests != null) {
for (PersistRequestBean> persistBeanRequest : persistBeanRequests) {
persistBeanRequest.notifyLocalPersistListener();
}
}
TransactionEventTable eventTables = event.getEventTables();
if (eventTables != null && !eventTables.isEmpty()) {
BulkEventListenerMap map = manager.getBulkEventListenerMap();
for (TableIUD tableIUD : eventTables.values()) {
map.process(tableIUD);
}
}
}
private BeanPersistIdMap createBeanPersistIdMap() {
if (persistBeanRequests == null) {
return null;
}
BeanPersistIdMap m = new BeanPersistIdMap();
for (PersistRequestBean> persistBeanRequest : persistBeanRequests) {
persistBeanRequest.addToPersistMap(m);
}
return m;
}
private RemoteTransactionEvent createRemoteTransactionEvent() {
if (!clusterManager.isClustering()) {
return null;
}
RemoteTransactionEvent remoteTransactionEvent = new RemoteTransactionEvent(serverName);
if (beanPersistIdMap != null) {
for (BeanPersistIds beanPersist : beanPersistIdMap.values()) {
remoteTransactionEvent.addBeanPersistIds(beanPersist);
}
}
if (deleteByIdMap != null) {
remoteTransactionEvent.setDeleteByIdMap(deleteByIdMap);
}
TransactionEventTable eventTables = event.getEventTables();
if (eventTables != null && !eventTables.isEmpty()) {
for (TableIUD tableIUD : eventTables.values()) {
remoteTransactionEvent.addTableIUD(tableIUD);
}
}
return remoteTransactionEvent;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy