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

io.mongock.driver.mongodb.reactive.repository.MongoReactiveRepositoryBase Maven / Gradle / Ivy

The newest version!
package io.mongock.driver.mongodb.reactive.repository;

import com.mongodb.client.model.IndexOptions;
import com.mongodb.reactivestreams.client.MongoCollection;
import io.mongock.api.exception.MongockException;
import io.mongock.driver.api.common.EntityRepository;
import io.mongock.driver.api.common.RepositoryIndexable;
import io.mongock.driver.mongodb.reactive.util.SubscriberSync;
import io.mongock.driver.mongodb.reactive.util.MongoCollectionSync;
import io.mongock.driver.mongodb.reactive.util.MongoSubscriberSync;
import org.bson.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public abstract class MongoReactiveRepositoryBase implements EntityRepository, RepositoryIndexable {

  private final static Logger logger = LoggerFactory.getLogger(MongoReactiveRepositoryBase.class);
  private final static int INDEX_ENSURE_MAX_TRIES = 3;

  private final String[] uniqueFields;
  private boolean indexCreation = true;
  private boolean ensuredCollectionIndex = false;
  protected MongoCollectionSync collection;

  public MongoReactiveRepositoryBase(MongoCollection collection, String[] uniqueFields, ReadWriteConfiguration readWriteConfiguration) {
    MongoCollection enhancedCollection = collection
        .withReadConcern(readWriteConfiguration.getReadConcern())
        .withReadPreference(readWriteConfiguration.getReadPreference())
        .withWriteConcern(readWriteConfiguration.getWriteConcern());
    this.collection = new MongoCollectionSync(enhancedCollection);
    this.uniqueFields = uniqueFields;
  }

  @Override
  public synchronized void initialize() {
    if (!this.ensuredCollectionIndex) {
      ensureIndex(INDEX_ENSURE_MAX_TRIES);
      this.ensuredCollectionIndex = true;
    }
  }

  private void ensureIndex(int tryCounter) {
    if (tryCounter <= 0) {
      throw new MongockException("Max tries " + INDEX_ENSURE_MAX_TRIES + " index  creation");
    }
    if (!isIndexFine()) {
      if (!indexCreation) {
        throw new MongockException("Index creation not allowed, but not created or wrongly created for collection " + collection.getNamespace().getCollectionName());
      }
      cleanResidualUniqueKeys();
      if (!isRequiredIndexCreated()) {
        createRequiredUniqueIndex();
      }
      ensureIndex(tryCounter - 1);
    }
  }

  protected boolean isIndexFine() {
    return getResidualKeys().isEmpty() && isRequiredIndexCreated();
  }

  protected void cleanResidualUniqueKeys() {
    logger.debug("Removing residual uniqueKeys for collection [{}]", getCollectionName());
    getResidualKeys().stream()
        .peek(index -> logger.debug("Removed residual uniqueKey [{}] for collection [{}]", index.toString(), getCollectionName()))
        .forEach(this::dropIndex);
  }

  private List getResidualKeys() {
    return collection.listIndexes()
        .stream()
        .filter(this::doesNeedToBeRemoved)
        .collect(Collectors.toList());
  }

  protected boolean doesNeedToBeRemoved(Document index) {
    return !isIdIndex(index) && isUniqueIndex(index) && !isRightIndex(index);
  }

  protected boolean isIdIndex(Document index) {
    return ((Document) index.get("key")).get("_id") != null;
  }

  protected boolean isRequiredIndexCreated() {
    return collection.listIndexes()
        .stream()
        .anyMatch(this::isRightIndex);
  }

  protected void createRequiredUniqueIndex() {
    collection.createIndex(getIndexDocument(uniqueFields), new IndexOptions().unique(true));
    logger.debug("Index in collection [{}] was recreated", getCollectionName());
  }

  protected boolean isRightIndex(Document index) {
    final Document key = (Document) index.get("key");
    boolean keyContainsAllFields = Stream.of(uniqueFields).allMatch(uniqueField -> key.get(uniqueField) != null);
    boolean onlyTheseFields = key.size() == uniqueFields.length;
    return keyContainsAllFields && onlyTheseFields && isUniqueIndex(index);
  }

  protected boolean isUniqueIndex(Document index) {
    return index.getBoolean("unique", false);// checks it'unique
  }

  private String getCollectionName() {
    return collection.getNamespace().getCollectionName();
  }

  protected Document getIndexDocument(String[] uniqueFields) {
    final Document indexDocument = new Document();
    Stream.of(uniqueFields).forEach(field -> indexDocument.append(field, 1));
    return indexDocument;
  }

  protected void dropIndex(Document index) {
    collection.dropIndex(index.get("name").toString());
  }

  @Override
  public void setIndexCreation(boolean indexCreation) {
    this.indexCreation = indexCreation;
  }

  /**
   * Only for testing
   */
  public void deleteAll() {
    collection.deleteMany(new Document());
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy