Skip to content

Commit

Permalink
Merge pull request #1 from esleybonomo/feature/EB-Advanced-Migration
Browse files Browse the repository at this point in the history
Feature/eb advanced migration
  • Loading branch information
esleybonomo committed Feb 27, 2020
2 parents 3a990f3 + 960b3de commit 7ffa1d1
Show file tree
Hide file tree
Showing 21 changed files with 652 additions and 16 deletions.
35 changes: 35 additions & 0 deletions Mongo.Migration/ApplicationLogging.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using Microsoft.Extensions.Logging;

public class ApplicationLogging
{
private static ILoggerFactory _factory = null;

public static void ConfigureLogger(ILoggerFactory factory)
{
factory.AddFile("logs/migration/log-migration.log");
}

/// <summary>
/// Cria uma instancia do logFactory
/// </summary>
/// <param name="equipment">Objeto com os dados do equipamento</param>
/// <returns>Instancia da logger Factory</returns>
public static ILoggerFactory LoggerFactory
{
get
{
if (_factory == null)
{
_factory = new LoggerFactory();
ConfigureLogger(_factory);
}
return _factory;
}
}

/// <summary>
/// Retorna uma instancia do ILogger configurada para ser usada nas migrações
/// </summary>
/// <returns>Instancia do ILogger</returns>
public static ILogger CreateLogger() => LoggerFactory.CreateLogger("logger");
}
36 changes: 36 additions & 0 deletions Mongo.Migration/Extensions/EnumerableExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,41 @@ internal static IDictionary<Type, IReadOnlyCollection<IMigration>> ToMigrationDi

return dictonary;
}

internal static IEnumerable<IAdvancedMigration> CheckForDuplicates(this IEnumerable<IAdvancedMigration> list)
{
var uniqueHashes = new HashSet<string>();
foreach (var element in list)
{
var version = element.Version.ToString();
var typeName = element.GetType().Name;

if (uniqueHashes.Add(typeName+version))
continue;

throw new DuplicateVersionException(typeName, element.Version);
}

return list;
}

internal static IDictionary<Type, IReadOnlyCollection<IAdvancedMigration>> ToMigrationDictionary(
this IEnumerable<IAdvancedMigration> migrations)
{
var dictonary = new Dictionary<Type, IReadOnlyCollection<IAdvancedMigration>>();
var types = from m in migrations select m.Type;

foreach (var type in types)
{
if (dictonary.ContainsKey(type))
continue;

var uniqueMigrations =
migrations.Where(m => m.Type == type).CheckForDuplicates().OrderBy(m => m.Version).ToList();
dictonary.Add(type, uniqueMigrations);
}

return dictonary;
}
}
}
70 changes: 70 additions & 0 deletions Mongo.Migration/Migrations/AdvancedMigration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using MongoDB.Bson;
using MongoDB.Driver;

namespace Mongo.Migration.Migrations
{
public abstract class AdvancedMigration : IAdvancedMigration
{
protected AdvancedMigration(string version, string collection)
{
Version = version;
CollectionName = collection;
}

public string Version { get; }

public string CollectionName { get; }

public Type Type => typeof(AdvancedMigration);

public virtual void Up(IMongoDatabase db) {
var bulk = new List<WriteModel<BsonDocument>>();
var collection = db.GetCollection<BsonDocument>(CollectionName);

collection.FindSync(_ => true).ToList().ForEach(document =>
{
Up(document);
var update = new ReplaceOneModel<BsonDocument>(
new BsonDocument {{"_id", document["_id"]}},
document
);
bulk.Add(update);
});

if (bulk.Count > 0)
{
collection.BulkWrite(bulk);
}
}

public virtual void Down(IMongoDatabase db) {
var bulk = new List<WriteModel<BsonDocument>>();
var collection = db.GetCollection<BsonDocument>(CollectionName);

collection.FindSync(_ => true).ToList().ForEach(document =>
{
Down(document);
var update = new ReplaceOneModel<BsonDocument>(
new BsonDocument {{"_id", document["_id"]}},
document
);
bulk.Add(update);
});

if (bulk.Count > 0)
{
collection.BulkWrite(bulk);
}
}

public abstract void Up(BsonDocument document);

public abstract void Down(BsonDocument document);
}
}
105 changes: 105 additions & 0 deletions Mongo.Migration/Migrations/AdvancedMigrationRunner.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.Logging;
using Mongo.Migration.Migrations.Locators;
using Mongo.Migration.Services;
using MongoDB.Bson;
using MongoDB.Driver;

namespace Mongo.Migration.Migrations
{
internal class AdvancedMigrationRunner : IAdvancedMigrationRunner
{
private ILogger _logger;
public IAdvancedMigrationLocator _migrationLocator { get; }

private readonly IVersionService _versionService;

private IMongoDatabase _db;

private IMongoCollection<BsonDocument> _migrationshistory;

public AdvancedMigrationRunner(IAdvancedMigrationLocator migrationLocator, IVersionService versionService)
{
_migrationLocator = migrationLocator;
_versionService = versionService;
_logger = ApplicationLogging.CreateLogger();
}

public void Run(IMongoDatabase db, string runningVersion)
{
_logger.LogInformation($"Iniciando a execução das Migrações ...");

_db = db;
_migrationshistory = db.GetCollection<BsonDocument>("_migrationshistory");

var migrations = _migrationLocator.GetMigrations(typeof(AdvancedMigration)) ?? Enumerable.Empty<IAdvancedMigration>();
var migrationsToDowngrade = new List<IAdvancedMigration>();

foreach (var migration in migrations)
{

var migrationsInDb = _migrationshistory.FindSync(CreateQueryForMigration(migration.GetType().ToString())).ToList();

if (migrationsInDb.Count() > 0)
{
foreach (var document in migrationsInDb)
{
if (document["productVersion"].ToString().CompareTo(runningVersion) <= 0)
continue;
else if (document["productVersion"].ToString().CompareTo(runningVersion) > 0)
{
migrationsToDowngrade.Add(migration);
}
}
}
else
{
if (runningVersion.CompareTo(migration.Version) >= 0)
{
try
{
_logger.LogInformation("Iniciando a execução da Migração Up: {0}:{1} ", migration.GetType().ToString(), migration.Version);

migration.Up(_db);
_migrationshistory.InsertOne(new BsonDocument { { "migrationId", migration.GetType().ToString() }, { "productVersion", migration.Version } });

_logger.LogInformation("Migração Up executada com sucesso: {0}:{1} ", migration.GetType().ToString(), migration.Version);
}
catch (Exception e)
{
_logger.LogError(e, "Erro ao executar upgrade da migração {0}:{1} ", migration.GetType().ToString(), migration.Version);
}
}
}
}

migrationsToDowngrade.Reverse();
foreach (var migration in migrationsToDowngrade)
{
try
{
_logger.LogInformation("Iniciando a execução da Migração Down: {0}:{1} ", migration.GetType().ToString(), migration.Version);

migration.Down(_db);
_migrationshistory.DeleteOne(Builders<BsonDocument>.Filter.Eq("migrationId", migration.GetType().ToString()));

_logger.LogInformation("Migração Down executada com sucesso: {0}:{1} ", migration.GetType().ToString(), migration.Version);
}
catch (Exception e)
{
_logger.LogError(e, "Erro ao executar downgrade da migração {0}:{1} ", migration.GetType().ToString(), migration.Version);
}
}

_logger.LogInformation($"Migrações finalizadas.");
}

private FilterDefinition<BsonDocument> CreateQueryForMigration(
string type)
{
return Builders<BsonDocument>.Filter.Eq("migrationId", type);
}
}
}
16 changes: 8 additions & 8 deletions Mongo.Migration/Migrations/CollectionMigrationRunner.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.ComTypes;
using Microsoft.Extensions.Options;
using Mongo.Migration.Documents.Attributes;
using Mongo.Migration.Documents.Locators;
Expand All @@ -17,6 +15,8 @@ internal class CollectionMigrationRunner : ICollectionMigrationRunner
{
private readonly IMongoClient _client;

private IMongoDatabase _db;

private readonly ICollectionLocator _collectionLocator;

private readonly IMigrationRunner _migrationRunner;
Expand Down Expand Up @@ -58,6 +58,7 @@ public CollectionMigrationRunner(

public void RunAll()
{
_db = _client.GetDatabase(_databaseName);
var locations = _collectionLocator.GetLocatesOrEmpty();

foreach (var locate in locations)
Expand All @@ -66,10 +67,9 @@ public void RunAll()
var type = locate.Key;
var databaseName = GetDatabaseOrDefault(information);
var collectionVersion = _versionService.GetCollectionVersion(type);

var collection = _client.GetDatabase(databaseName)
.GetCollection<BsonDocument>(information.Collection);


var collection = _db.GetCollection<BsonDocument>(information.Collection);

var bulk = new List<WriteModel<BsonDocument>>();

var query = CreateQueryForRelevantDocuments(type);
Expand All @@ -82,14 +82,14 @@ public void RunAll()
foreach (var document in batch)
{
_migrationRunner.Run(type, document, collectionVersion);



var update = new ReplaceOneModel<BsonDocument>(
new BsonDocument {{"_id", document["_id"]}},
document
);

bulk.Add(update);
//migrationshistory.InsertOne(new BsonDocument {{"migrationId", nameof(type)}, {"productVersion", _runningVersion}});
}
}
}
Expand Down
47 changes: 47 additions & 0 deletions Mongo.Migration/Migrations/DatabaseMigrationRunner.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using Microsoft.Extensions.Options;
using Mongo.Migration.Startup.DotNetCore;
using MongoDB.Driver;

namespace Mongo.Migration.Migrations
{
internal class DatabaseMigrationRunner : IDatabaseMigrationRunner
{
private readonly IMongoClient _client;

private readonly IAdvancedMigrationRunner _migrationRunner;

private readonly string _databaseName;

private readonly string _runningVersion;

private readonly IOptions<MongoMigrationSettings> _options;

private const int CONNECTION_CHECK_TIMEOUT = 1000;
public DatabaseMigrationRunner(
IOptions<MongoMigrationSettings> options,
IAdvancedMigrationRunner migrationRunner)
: this(
new MongoClient(options.Value.ConnectionString),
migrationRunner,
options.Value.RunningVersion)
{
_options = options;
_databaseName = options.Value.Database;
}

public DatabaseMigrationRunner(
IMongoClient client,
IAdvancedMigrationRunner migrationRunner,
string runningVersion)
{
_runningVersion = runningVersion;
_client = client;
_migrationRunner = migrationRunner;
}

public void RunAll()
{
_migrationRunner.Run(_client.GetDatabase(_databaseName), _runningVersion);
}
}
}
23 changes: 23 additions & 0 deletions Mongo.Migration/Migrations/IAdvancedMigration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System;
using MongoDB.Bson;
using MongoDB.Driver;

namespace Mongo.Migration.Migrations
{
public interface IAdvancedMigration
{
string Version { get; }

string CollectionName { get; }

Type Type { get; }

void Up(IMongoDatabase db);

void Down(IMongoDatabase db);

void Up(BsonDocument document);

void Down(BsonDocument document);
}
}
Loading

0 comments on commit 7ffa1d1

Please sign in to comment.