Browse Source

Migrator fixed.

pull/590/head
Sebastian 5 years ago
parent
commit
b4bc123d7c
  1. 10
      backend/src/Squidex.Infrastructure.MongoDb/Migrations/MongoMigrationStatus.cs
  2. 4
      backend/src/Squidex.Infrastructure/Migrations/IMigrationStatus.cs
  3. 4
      backend/src/Squidex.Infrastructure/Migrations/Migrator.cs
  4. 108
      backend/tests/Squidex.Infrastructure.Tests/Migrations/MigratorTests.cs

10
backend/src/Squidex.Infrastructure.MongoDb/Migrations/MongoMigrationStatus.cs

@ -45,12 +45,18 @@ namespace Squidex.Infrastructure.Migrations
return entity == null || entity.IsLocked == false; return entity == null || entity.IsLocked == false;
} }
public Task UnlockAsync(int newVersion) public Task CompleteAsync(int newVersion)
{ {
return Collection.UpdateOneAsync(x => x.Id == DefaultId, return Collection.UpdateOneAsync(x => x.Id == DefaultId,
Update Update
.Set(x => x.IsLocked, false)
.Set(x => x.Version, newVersion)); .Set(x => x.Version, newVersion));
} }
public Task UnlockAsync()
{
return Collection.UpdateOneAsync(x => x.Id == DefaultId,
Update
.Set(x => x.IsLocked, false));
}
} }
} }

4
backend/src/Squidex.Infrastructure/Migrations/IMigrationStatus.cs

@ -15,6 +15,8 @@ namespace Squidex.Infrastructure.Migrations
Task<bool> TryLockAsync(); Task<bool> TryLockAsync();
Task UnlockAsync(int newVersion); Task CompleteAsync(int newVersion);
Task UnlockAsync();
} }
} }

4
backend/src/Squidex.Infrastructure/Migrations/Migrator.cs

@ -90,11 +90,13 @@ namespace Squidex.Infrastructure.Migrations
} }
version = newVersion; version = newVersion;
await migrationStatus.CompleteAsync(newVersion);
} }
} }
finally finally
{ {
await migrationStatus.UnlockAsync(version); await migrationStatus.UnlockAsync();
} }
} }
} }

108
backend/tests/Squidex.Infrastructure.Tests/Migrations/MigratorTests.cs

@ -50,33 +50,81 @@ namespace Squidex.Infrastructure.Migrations
return Task.FromResult(lockAcquired); return Task.FromResult(lockAcquired);
} }
public Task UnlockAsync(int newVersion) public Task CompleteAsync(int newVersion)
{ {
lock (lockObject) lock (lockObject)
{ {
isLocked = false;
version = newVersion; version = newVersion;
} }
return Task.CompletedTask; return Task.CompletedTask;
} }
public Task UnlockAsync()
{
lock (lockObject)
{
isLocked = false;
}
return Task.CompletedTask;
}
} }
public MigratorTests() public MigratorTests()
{ {
A.CallTo(() => path.GetNext(A<int>._)) A.CallTo(() => path.GetNext(A<int>._))
.ReturnsLazily((int v) => .ReturnsLazily((int version) =>
{ {
var m = migrations.Where(x => x.From == v).ToList(); var selected = migrations.Where(x => x.From == version).ToList();
if (selected.Count == 0)
{
return (0, null);
}
return m.Count == 0 ? (0, null) : (migrations.Max(x => x.To), migrations.Select(x => x.Migration)); var newVersion = selected.Max(x => x.To);
return (newVersion, migrations.Select(x => x.Migration));
}); });
A.CallTo(() => status.GetVersionAsync()).Returns(0); A.CallTo(() => status.GetVersionAsync()).Returns(0);
A.CallTo(() => status.TryLockAsync()).Returns(true); A.CallTo(() => status.TryLockAsync()).Returns(true);
} }
[Fact]
public async Task Should_migrate_in_one_step()
{
var migrator_0_1 = BuildMigration(0, 1);
var migrator_1_2 = BuildMigration(0, 2);
var migrator_2_3 = BuildMigration(0, 3);
var sut = new Migrator(status, path, log);
await sut.MigrateAsync();
A.CallTo(() => migrator_0_1.UpdateAsync())
.MustHaveHappened();
A.CallTo(() => migrator_1_2.UpdateAsync())
.MustHaveHappened();
A.CallTo(() => migrator_2_3.UpdateAsync())
.MustHaveHappened();
A.CallTo(() => status.CompleteAsync(1))
.MustNotHaveHappened();
A.CallTo(() => status.CompleteAsync(2))
.MustNotHaveHappened();
A.CallTo(() => status.CompleteAsync(3))
.MustHaveHappened();
A.CallTo(() => status.UnlockAsync())
.MustHaveHappened();
}
[Fact] [Fact]
public async Task Should_migrate_step_by_step() public async Task Should_migrate_step_by_step()
{ {
@ -88,11 +136,25 @@ namespace Squidex.Infrastructure.Migrations
await sut.MigrateAsync(); await sut.MigrateAsync();
A.CallTo(() => migrator_0_1.UpdateAsync()).MustHaveHappened(); A.CallTo(() => migrator_0_1.UpdateAsync())
A.CallTo(() => migrator_1_2.UpdateAsync()).MustHaveHappened(); .MustHaveHappened();
A.CallTo(() => migrator_2_3.UpdateAsync()).MustHaveHappened();
A.CallTo(() => migrator_1_2.UpdateAsync())
.MustHaveHappened();
A.CallTo(() => migrator_2_3.UpdateAsync())
.MustHaveHappened();
A.CallTo(() => status.CompleteAsync(1))
.MustHaveHappened();
A.CallTo(() => status.CompleteAsync(2))
.MustHaveHappened();
A.CallTo(() => status.CompleteAsync(3))
.MustHaveHappened();
A.CallTo(() => status.UnlockAsync(3)) A.CallTo(() => status.UnlockAsync())
.MustHaveHappened(); .MustHaveHappened();
} }
@ -109,11 +171,26 @@ namespace Squidex.Infrastructure.Migrations
await Assert.ThrowsAsync<MigrationFailedException>(() => sut.MigrateAsync()); await Assert.ThrowsAsync<MigrationFailedException>(() => sut.MigrateAsync());
A.CallTo(() => migrator_0_1.UpdateAsync()).MustHaveHappened(); A.CallTo(() => migrator_0_1.UpdateAsync())
A.CallTo(() => migrator_1_2.UpdateAsync()).MustHaveHappened(); .MustHaveHappened();
A.CallTo(() => migrator_2_3.UpdateAsync()).MustNotHaveHappened();
A.CallTo(() => status.UnlockAsync(0)).MustHaveHappened(); A.CallTo(() => migrator_1_2.UpdateAsync())
.MustHaveHappened();
A.CallTo(() => migrator_2_3.UpdateAsync())
.MustNotHaveHappened();
A.CallTo(() => status.CompleteAsync(1))
.MustNotHaveHappened();
A.CallTo(() => status.CompleteAsync(2))
.MustNotHaveHappened();
A.CallTo(() => status.CompleteAsync(3))
.MustNotHaveHappened();
A.CallTo(() => status.UnlockAsync())
.MustHaveHappened();
} }
[Fact] [Fact]
@ -142,7 +219,7 @@ namespace Squidex.Infrastructure.Migrations
public async Task Should_prevent_multiple_updates() public async Task Should_prevent_multiple_updates()
{ {
var migrator_0_1 = BuildMigration(0, 1); var migrator_0_1 = BuildMigration(0, 1);
var migrator_1_2 = BuildMigration(1, 2); var migrator_1_2 = BuildMigration(0, 2);
var sut = new Migrator(new InMemoryStatus(), path, log) { LockWaitMs = 2 }; var sut = new Migrator(new InMemoryStatus(), path, log) { LockWaitMs = 2 };
@ -150,6 +227,7 @@ namespace Squidex.Infrastructure.Migrations
A.CallTo(() => migrator_0_1.UpdateAsync()) A.CallTo(() => migrator_0_1.UpdateAsync())
.MustHaveHappenedOnceExactly(); .MustHaveHappenedOnceExactly();
A.CallTo(() => migrator_1_2.UpdateAsync()) A.CallTo(() => migrator_1_2.UpdateAsync())
.MustHaveHappenedOnceExactly(); .MustHaveHappenedOnceExactly();
} }

Loading…
Cancel
Save