mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-19 06:54:19 +01:00
Avoid timeouts during EF migrations (#5937)
This commit is contained in:
@@ -5,6 +5,7 @@ using Microsoft.EntityFrameworkCore.Metadata;
|
|||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Npgsql;
|
using Npgsql;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure;
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Migrations;
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Migrations;
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Migrations.Operations;
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Migrations.Operations;
|
||||||
|
|
||||||
@@ -21,7 +22,8 @@ namespace BTCPayServer.Abstractions.Contracts
|
|||||||
_migrationTableName = migrationTableName;
|
_migrationTableName = migrationTableName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract T CreateContext();
|
public T CreateContext() => CreateContext(null);
|
||||||
|
public abstract T CreateContext(Action<NpgsqlDbContextOptionsBuilder> npgsqlOptionsAction = null);
|
||||||
class CustomNpgsqlMigrationsSqlGenerator : NpgsqlMigrationsSqlGenerator
|
class CustomNpgsqlMigrationsSqlGenerator : NpgsqlMigrationsSqlGenerator
|
||||||
{
|
{
|
||||||
#pragma warning disable EF1001 // Internal EF Core API usage.
|
#pragma warning disable EF1001 // Internal EF Core API usage.
|
||||||
@@ -66,13 +68,15 @@ namespace BTCPayServer.Abstractions.Contracts
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ConfigureBuilder(DbContextOptionsBuilder builder)
|
public void ConfigureBuilder(DbContextOptionsBuilder builder) => ConfigureBuilder(builder, null);
|
||||||
|
public void ConfigureBuilder(DbContextOptionsBuilder builder, Action<NpgsqlDbContextOptionsBuilder> npgsqlOptionsAction = null)
|
||||||
{
|
{
|
||||||
builder
|
builder
|
||||||
.UseNpgsql(_options.Value.ConnectionString, o =>
|
.UseNpgsql(_options.Value.ConnectionString, o =>
|
||||||
{
|
{
|
||||||
o.EnableRetryOnFailure(10);
|
o.EnableRetryOnFailure(10);
|
||||||
o.SetPostgresVersion(12, 0);
|
o.SetPostgresVersion(12, 0);
|
||||||
|
npgsqlOptionsAction?.Invoke(o);
|
||||||
var mainSearchPath = GetSearchPath(_options.Value.ConnectionString);
|
var mainSearchPath = GetSearchPath(_options.Value.ConnectionString);
|
||||||
var schemaPrefix = string.IsNullOrEmpty(_migrationTableName) ? "__EFMigrationsHistory" : _migrationTableName;
|
var schemaPrefix = string.IsNullOrEmpty(_migrationTableName) ? "__EFMigrationsHistory" : _migrationTableName;
|
||||||
o.MigrationsHistoryTable(schemaPrefix, mainSearchPath);
|
o.MigrationsHistoryTable(schemaPrefix, mainSearchPath);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using BTCPayServer.Abstractions.Contracts;
|
|||||||
using BTCPayServer.Abstractions.Models;
|
using BTCPayServer.Abstractions.Models;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure;
|
||||||
|
|
||||||
namespace BTCPayServer.Data
|
namespace BTCPayServer.Data
|
||||||
{
|
{
|
||||||
@@ -14,11 +15,11 @@ namespace BTCPayServer.Data
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public override ApplicationDbContext CreateContext()
|
public override ApplicationDbContext CreateContext(Action<NpgsqlDbContextOptionsBuilder> npgsqlOptionsAction = null)
|
||||||
{
|
{
|
||||||
var builder = new DbContextOptionsBuilder<ApplicationDbContext>();
|
var builder = new DbContextOptionsBuilder<ApplicationDbContext>();
|
||||||
builder.AddInterceptors(Data.InvoiceData.MigrationInterceptor.Instance);
|
builder.AddInterceptors(Data.InvoiceData.MigrationInterceptor.Instance);
|
||||||
ConfigureBuilder(builder);
|
ConfigureBuilder(builder, npgsqlOptionsAction);
|
||||||
return new ApplicationDbContext(builder.Options);
|
return new ApplicationDbContext(builder.Options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -885,21 +885,25 @@ WHERE cte.""Id""=p.""Id""
|
|||||||
|
|
||||||
private async Task Migrate(CancellationToken cancellationToken)
|
private async Task Migrate(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
using (CancellationTokenSource timeout = new CancellationTokenSource(10_000))
|
int cancellationTimeout = 60 * 60 * 24;
|
||||||
|
using (CancellationTokenSource timeout = new CancellationTokenSource(cancellationTimeout))
|
||||||
using (CancellationTokenSource cts = CancellationTokenSource.CreateLinkedTokenSource(timeout.Token, cancellationToken))
|
using (CancellationTokenSource cts = CancellationTokenSource.CreateLinkedTokenSource(timeout.Token, cancellationToken))
|
||||||
{
|
{
|
||||||
retry:
|
retry:
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var db = _DBContextFactory.CreateContext();
|
_logger.LogInformation("Running the migration scripts...");
|
||||||
await db.Database.MigrateAsync();
|
var db = _DBContextFactory.CreateContext(o => o.CommandTimeout(cancellationTimeout + 1));
|
||||||
|
await db.Database.MigrateAsync(timeout.Token);
|
||||||
|
_logger.LogInformation("All migration scripts ran successfully");
|
||||||
}
|
}
|
||||||
// Starting up
|
// Starting up
|
||||||
catch (ConfigException) { throw; }
|
catch (ConfigException) { throw; }
|
||||||
catch when (!cts.Token.IsCancellationRequested)
|
catch (Exception ex) when (!cts.Token.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
_logger.LogWarning(ex, "Error while running migration scripts, retrying...");
|
||||||
await Task.Delay(1000, cts.Token);
|
await Task.Delay(1000, cts.Token);
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
|
|||||||
Reference in New Issue
Block a user