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

com.rinoto.migramongo.dao.MongoMigrationHistoryService Maven / Gradle / Ivy

There is a newer version: 2.2.0
Show newest version
package com.rinoto.migramongo.dao;

import static com.mongodb.client.model.Filters.and;
import static com.mongodb.client.model.Filters.eq;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import org.bson.Document;
import org.bson.conversions.Bson;

import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.rinoto.migramongo.MigraMongoStatus.MigrationStatus;
import com.rinoto.migramongo.MigrationEntry;
import com.rinoto.migramongo.MigrationEntry.MigrationType;
import com.rinoto.migramongo.MigrationInfo;
import com.rinoto.migramongo.MigrationRun;

public class MongoMigrationHistoryService implements MigrationHistoryService {

    public static final String MIGRAMONGO_COLLECTION = "_migramongo_upgrade_info";
    private final MongoDatabase database;

    public MongoMigrationHistoryService(MongoDatabase database) {
        this.database = database;
    }

    @Override
    public MigrationEntry insertMigrationStatusInProgress(MigrationInfo migrationInfo) {
        final MigrationEntry migEntry = mapMigrationInfoToMigrationEntry(migrationInfo, MigrationStatus.IN_PROGRESS);
        return insertMigrationEntry(migEntry);
    }

    @Override
    public MigrationEntry insertMigrationStatusSkipped(MigrationInfo migrationInfo) {
        final MigrationEntry migEntry = mapMigrationInfoToMigrationEntry(migrationInfo, MigrationStatus.OK);
        migEntry.setSkipped(true);
        return insertMigrationEntry(migEntry);
    }

    private MigrationEntry mapMigrationInfoToMigrationEntry(MigrationInfo migrationInfo, MigrationStatus status) {
        final MigrationEntry migEntry = new MigrationEntry();
        migEntry.setModule(migrationInfo.getModule());
        migEntry.setStatus(status);
        migEntry.setMigrationType(migrationInfo.getMigrationType());
        migEntry.setFromVersion(migrationInfo.getFromVersion());
        migEntry.setToVersion(migrationInfo.getToVersion());
        migEntry.setInfo(migrationInfo.getInfo());
        migEntry.setCreatedAt(new Date());
        return migEntry;
    }

    private MigrationEntry insertMigrationEntry(MigrationEntry migEntry) {

        migEntry.setUpdatedAt(new Date());

        final Document document = mapMigEntryToDocument(migEntry);
        if (migEntry.getId() == null) {
            getMigramongoCollection().insertOne(document);
            migEntry.setId(document.getObjectId("_id"));
        } else {
            replaceMigrationEntry(migEntry, document);
        }
        return migEntry;
    }

    private void replaceMigrationEntry(MigrationEntry migEntry, final Document document) {
        getMigramongoCollection().replaceOne(eq("_id", migEntry.getId()), document);
    }

    MongoCollection getMigramongoCollection() {
        return this.database.getCollection(MIGRAMONGO_COLLECTION);
    }

    @Override
    public MigrationEntry setMigrationStatusToFailed(MigrationEntry migrationEntry, Exception e) {
        migrationEntry.setStatus(MigrationStatus.ERROR);
        migrationEntry.setStatusMessage(e.getMessage());
        return insertMigrationEntry(migrationEntry);
    }

    @Override
    public MigrationEntry setMigrationStatusToFinished(MigrationEntry migrationEntry) {
        migrationEntry.setStatus(MigrationStatus.OK);
        return insertMigrationEntry(migrationEntry);
    }

    @Override
    public MigrationEntry setMigrationStatusToManuallyRepaired(MigrationEntry migrationEntry) {
        migrationEntry.setStatus(MigrationStatus.OK);
        migrationEntry.setRepaired(true);
        return insertMigrationEntry(migrationEntry);
    }

    @Override
    public MigrationEntry getLastMigrationApplied() {
        final Document doc = getMigramongoCollection().find().sort(new Document("createdAt", -1)).first();
        return mapMigrationEntry(doc);
    }

    @Override
    public Iterable getAllMigrationsApplied() {
        return getMigramongoCollection().find().sort(new Document("createdAt", 1)).map(d -> mapMigrationEntry(d));
    }

    private MigrationEntry mapMigrationEntry(Document doc) {
        if (doc == null) {
            return null;
        }
        final MigrationEntry migEntry = new MigrationEntry();
        migEntry.setId(doc.getObjectId("_id"));
        migEntry.setModule(doc.getString("module"));
        migEntry.setFromVersion(doc.getString("fromVersion"));
        migEntry.setToVersion(doc.getString("toVersion"));
        migEntry.setMigrationType(MigrationType.valueOf(doc.getString("type")));
        fillMigrationRunDataIntoObject(migEntry, doc);
        final Boolean repaired = doc.getBoolean("repaired");
        if (repaired != null) {
            migEntry.setRepaired(repaired);
        }
        final Boolean skipped = doc.getBoolean("skipped");
        if (skipped != null) {
            migEntry.setSkipped(skipped);
        }
        @SuppressWarnings("unchecked")
        final List reruns = doc.get("reruns", List.class);
        if (reruns != null) {
            final List rerunsList = reruns
                .stream()
                .map(d -> mapMigrationRun(d))
                .collect(Collectors.toList());
            migEntry.setReruns(rerunsList);
        }
        return migEntry;
    }

    private MigrationRun mapMigrationRun(Document migRunDoc) {
        final MigrationRun migRun = new MigrationRun();
        fillMigrationRunDataIntoObject(migRun, migRunDoc);
        return migRun;
    }

    private void fillMigrationRunDataIntoObject(MigrationRun migRun, Document doc) {
        migRun.setInfo(doc.getString("info"));
        migRun.setStatus(MigrationStatus.valueOf(doc.getString("status")));
        migRun.setStatusMessage(doc.getString("statusMessage"));
        migRun.setCreatedAt(doc.getDate("createdAt"));
        migRun.setUpdatedAt(doc.getDate("updatedAt"));
    }

    private Document mapMigEntryToDocument(MigrationEntry migEntry) {
        final Document migEntryDoc = new Document();
        if (migEntry.getId() != null) {
            migEntryDoc.put("_id", migEntry.getId());
        }
        migEntryDoc.put("module", migEntry.getModule());
        migEntryDoc.put("fromVersion", migEntry.getFromVersion());
        migEntryDoc.put("toVersion", migEntry.getToVersion());
        migEntryDoc.put("type", migEntry.getMigrationType().name());
        migEntryDoc.put("repaired", migEntry.isRepaired());
        migEntryDoc.put("skipped", migEntry.isSkipped());
        fillMigrationRunDataIntoDocument(migEntryDoc, migEntry);
        //there cannot be any MigrationRun when mapping a migrationEntry to a Doc, because a MigrationRun can only be added via #addMigrationRun
        return migEntryDoc;
    }

    private Document mapMigRunToDoc(MigrationRun migRun) {
        final Document migRunDoc = new Document();
        fillMigrationRunDataIntoDocument(migRunDoc, migRun);
        return migRunDoc;
    }

    private void fillMigrationRunDataIntoDocument(Document migRunDoc, MigrationRun migRun) {
        migRunDoc.put("info", migRun.getInfo());
        migRunDoc.put("status", migRun.getStatus().name());
        migRunDoc.put("statusMessage", migRun.getStatusMessage());
        migRunDoc.put("createdAt", migRun.getCreatedAt());
        migRunDoc.put("updatedAt", migRun.getUpdatedAt());
    }

    @Override
    public MigrationEntry findMigration(String fromVersion, String toVersion) {
        return mapMigrationEntry(findMigrationDoc(fromVersion, toVersion));
    }

    private Document findMigrationDoc(String fromVersion, String toVersion) {
        return getMigramongoCollection().find(and(eq("fromVersion", fromVersion), eq("toVersion", toVersion))).first();
    }

    @Override
    public Iterable findMigrations(String fromVersion) {
        if (fromVersion == null) {
            // returning all the migrations
            return getMigramongoCollection().find().sort(new Document("createdAt", 1)).map(d -> mapMigrationEntry(d));
        }
        final List entriesFrom = new ArrayList<>();
        // fromVersion is not null -> we have to find first the one with
        // fromVersion, and then go up
        String nextFromVersion = fromVersion;
        boolean initialFound = false;
        while (true) {
            final Bson fromVersionFilter = eq("fromVersion", nextFromVersion);
            final Bson upgradeFilter = eq("type", MigrationType.UPGRADE.name());
            final FindIterable find = getMigramongoCollection().find();
            if (initialFound) {
                find.filter(and(fromVersionFilter, upgradeFilter));
            } else {
                find.filter(fromVersionFilter);
            }
            final MigrationEntry migEntry = find.map(d -> mapMigrationEntry(d)).first();
            if (migEntry == null) {
                return entriesFrom;
            }
            entriesFrom.add(migEntry);
            nextFromVersion = migEntry.getToVersion();
            if (migEntry.getMigrationType() == MigrationType.INITIAL) {
                initialFound = true;
            }
        }

    }

    @Override
    public MigrationEntry addRunToMigrationEntry(MigrationEntry migEntry, MigrationRun migRun) {
        final Document migEntryDoc = findMigrationDoc(migEntry.getFromVersion(), migEntry.getToVersion());
        if (migEntryDoc == null) {
            return null;
        }
        final Document migRunDoc = mapMigRunToDoc(migRun);
        @SuppressWarnings("unchecked")
        List reRunsList = migEntryDoc.get("reruns", List.class);
        if (reRunsList == null) {
            reRunsList = new ArrayList();
        }
        reRunsList.add(migRunDoc);
        migEntryDoc.put("reruns", reRunsList);

        replaceMigrationEntry(migEntry, migEntryDoc);
        return mapMigrationEntry(migEntryDoc);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy