All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.yahoo.elide.datastores.multiplex.MultiplexManager Maven / Gradle / Ivy

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