![JAR search and dependency download from the Maven repository](/logo.png)
com.yahoo.elide.datastores.multiplex.MultiplexManager Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of elide-datastore-multiplex Show documentation
Show all versions of elide-datastore-multiplex Show documentation
Elide entity manager for multiple data store support
The newest version!
/*
* Copyright 2015, Yahoo Inc.
* Licensed under the Apache License, Version 2.0
* See LICENSE file in project root for terms.
*/
package com.yahoo.elide.datastores.multiplex;
import com.yahoo.elide.core.RequestScope;
import com.yahoo.elide.core.datastore.DataStore;
import com.yahoo.elide.core.datastore.DataStoreTransaction;
import com.yahoo.elide.core.dictionary.EntityBinding;
import com.yahoo.elide.core.dictionary.EntityDictionary;
import com.yahoo.elide.core.security.PermissionExecutor;
import com.yahoo.elide.core.type.Type;
import com.yahoo.elide.core.utils.ObjectCloner;
import com.yahoo.elide.core.utils.ObjectCloners;
import lombok.AccessLevel;
import lombok.Setter;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
/**
* Allows multiple database handlers to each process their own beans while keeping the main
* commit in sync across all managers.
*
* WARNING If a subordinate commit fails, attempts are made to reverse the previous
* commits. If these reversals fail, the databases can be left out of sync.
*
* For example, a Multiplex of two databases DB1, DB2 might do:
*
* - Save to DB1 and DB2
*
- Commit DB1 successfully
*
- Commit DB2 fails
*
- Attempt to reverse DB1 commit fails
*
*/
public final class MultiplexManager implements DataStore {
protected final List dataStores;
protected final ConcurrentHashMap, DataStore> dataStoreMap = new ConcurrentHashMap<>();
protected final Predicate applyCompensatingTransactions;
protected final ObjectCloner objectCloner;
@Setter(AccessLevel.PROTECTED)
private EntityDictionary dictionary;
/**
* Create a single DataStore to handle provided managers within a single transaction.
* @param dataStores list of sub-managers
*/
public MultiplexManager(DataStore... dataStores) {
this(ObjectCloners::clone, dataStore -> true, dataStores);
}
/**
* Create a single DataStore to handle provided managers within a single
* transaction.
*
* @param objectCloner to use for cloning objects to apply to compensating
* transaction
* @param dataStores list of sub-managers
*/
public MultiplexManager(ObjectCloner objectCloner, DataStore... dataStores) {
this(objectCloner, dataStore -> true, dataStores);
}
/**
* Create a single DataStore to handle provided managers within a single
* transaction.
*
* @param objectCloner to use for cloning objects to apply to
* compensating transaction
* @param applyCompensatingTransactions apply compensating transactions on
* rollback to previously committed
* datastores
* @param dataStores list of sub-managers
*/
public MultiplexManager(ObjectCloner objectCloner, Predicate applyCompensatingTransactions,
DataStore... dataStores) {
this.objectCloner = objectCloner;
this.dataStores = Arrays.asList(dataStores);
this.applyCompensatingTransactions = applyCompensatingTransactions;
}
protected boolean isApplyCompensatingTransactions(DataStore dataStore) {
return this.applyCompensatingTransactions.test(dataStore);
}
@Override
public void populateEntityDictionary(EntityDictionary dictionary) {
this.dictionary = dictionary;
for (DataStore dataStore : dataStores) {
EntityDictionary subordinateDictionary = new EntityDictionary(
dictionary.getCheckMappings(),
dictionary.getRoleChecks(),
dictionary.getInjector(),
dictionary.getSerdeLookup(),
dictionary.getEntitiesToExclude(),
dictionary.getScanner(),
dictionary.getIdObfuscator());
dataStore.populateEntityDictionary(subordinateDictionary);
for (EntityBinding binding : subordinateDictionary.getBindings(false)) {
// route class to this database manager
this.dataStoreMap.put(binding.entityClass, dataStore);
// bind to multiplex dictionary
dictionary.bindEntity(binding);
subordinateDictionary.getApiVersions().forEach(dictionary.getApiVersions()::add);
}
for (Map.Entry, Function> entry
: subordinateDictionary.getEntityPermissionExecutor().entrySet()) {
dictionary.bindPermissionExecutor(entry.getKey(), entry.getValue());
}
}
}
@Override
public DataStoreTransaction beginTransaction() {
return new MultiplexWriteTransaction(this);
}
@Override
public DataStoreTransaction beginReadTransaction() {
return new MultiplexReadTransaction(this);
}
public EntityDictionary getDictionary() {
return dictionary;
}
/**
* Lookup subordinate database manager for provided entity class.
* @param type
* @param cls provided class
* @return database manager handling this entity
*/
protected DataStore getSubManager(Type cls) {
// Follow for this class or super-class for Entity annotation
Type type = (Type) dictionary.lookupBoundClass(cls);
return dataStoreMap.get(type);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy