-
-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix race condition in migrator (#2730)
- Loading branch information
Showing
8 changed files
with
52 additions
and
66 deletions.
There are no files selected for viewing
2 changes: 1 addition & 1 deletion
2
...inrpg.Dal.Migrate/JoinMigrationsConfig.cs → ...g.Dal.Migrate/Ef6/JoinMigrationsConfig.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...Migrate/MigrationsLoggerILoggerAdapter.cs → ...ate/Ef6/MigrationsLoggerILoggerAdapter.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
56 changes: 18 additions & 38 deletions
56
src/Joinrpg.Dal.Migrate/EfCore/MigrateEfCoreHostService.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,71 +1,51 @@ | ||
using Microsoft.EntityFrameworkCore; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.Extensions.Hosting; | ||
using Microsoft.Extensions.Logging; | ||
|
||
namespace Joinrpg.Dal.Migrate; | ||
|
||
internal class MigrateEfCoreHostService<TContext>( | ||
IServiceProvider services, | ||
ILogger<MigrateEfCoreHostService<TContext>> logger, | ||
IHostApplicationLifetime applicationLifetime) : BackgroundService | ||
TContext dbContext, | ||
ILogger<MigrateEfCoreHostService<TContext>> logger) : IMigratorService | ||
where TContext : DbContext | ||
{ | ||
private async Task MigrateAsync(DbContext dbContext, CancellationToken stoppingToken) | ||
private static readonly string contextName = typeof(TContext).Name!; | ||
public async Task MigrateAsync(CancellationToken stoppingToken) | ||
{ | ||
logger.LogInformation("Start migration of {contextName}", typeof(TContext).FullName); | ||
using var logScope = logger.BeginScope("Migration of {dbContext}", contextName); | ||
|
||
logger.LogInformation("Start migration of {dbContext}", contextName); | ||
|
||
var lastAppliedMigration = (await dbContext.Database.GetAppliedMigrationsAsync(stoppingToken)).LastOrDefault(); | ||
if (!string.IsNullOrEmpty(lastAppliedMigration)) | ||
{ | ||
logger.LogInformation("Last applied migration: {LastAppliedMigration}", lastAppliedMigration); | ||
logger.LogInformation("Last applied migration for {dbContext}: {LastAppliedMigration}", contextName, lastAppliedMigration); | ||
} | ||
|
||
if (stoppingToken.IsCancellationRequested) | ||
{ | ||
return; | ||
} | ||
|
||
if (dbContext.Database.HasPendingModelChanges()) | ||
{ | ||
logger.LogError("There is pending changes in model!"); | ||
throw new InvalidOperationException("Pending changes in model"); | ||
} | ||
|
||
var pendingMigrations = await dbContext.Database.GetPendingMigrationsAsync(stoppingToken); | ||
|
||
foreach (var pm in pendingMigrations) | ||
{ | ||
logger.LogInformation("Pending migration: {PendingMigration}", pm); | ||
logger.LogInformation("Pending migration for {dbContext}: {PendingMigration}", contextName, pm); | ||
} | ||
|
||
if (stoppingToken.IsCancellationRequested) | ||
{ | ||
return; | ||
} | ||
|
||
logger.LogInformation("Applying migrations..."); | ||
logger.LogInformation("Applying migrations for {dbContext} ...", contextName); | ||
await dbContext.Database.MigrateAsync(stoppingToken); | ||
logger.LogInformation("Database has been successfully migrated"); | ||
} | ||
|
||
/// <inheritdoc /> | ||
protected override async Task ExecuteAsync(CancellationToken stoppingToken) | ||
{ | ||
logger.LogInformation("Starting migrator..."); | ||
await using var scope = services.CreateAsyncScope(); | ||
try | ||
{ | ||
await MigrateAsync( | ||
scope.ServiceProvider.GetRequiredService<TContext>(), | ||
stoppingToken); | ||
|
||
if (stoppingToken.IsCancellationRequested) | ||
{ | ||
logger.LogInformation("Terminating by cancellation token"); | ||
} | ||
} | ||
catch (Exception ex) | ||
{ | ||
logger.LogError(ex, "Error executing migrator"); | ||
Environment.ExitCode = 1; | ||
} | ||
finally | ||
{ | ||
applicationLifetime.StopApplication(); | ||
} | ||
logger.LogInformation("Database {dbContext} has been successfully migrated", contextName); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
namespace Joinrpg.Dal.Migrate; | ||
internal interface IMigratorService | ||
{ | ||
internal abstract Task MigrateAsync(CancellationToken ct); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters