1
0

Adding WaitAvailable to EFCore extensions

This commit is contained in:
2022-03-23 20:50:20 +01:00
parent e89e8bc69a
commit e38864b32b
4 changed files with 79 additions and 7 deletions

View File

@@ -56,7 +56,7 @@ namespace AMWD.Common.AspNetCore.BasicAuthentication
if (context.Result != null) if (context.Result != null)
return; return;
if (context.HttpContext.Request.Headers.ContainsKey("Authorization")) if (!context.HttpContext.Request.Headers.ContainsKey("Authorization"))
{ {
SetAuthenticateRequest(context); SetAuthenticateRequest(context);
return; return;

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data;
using System.Data.Common; using System.Data.Common;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@@ -28,18 +29,24 @@ namespace Microsoft.EntityFrameworkCore
if (database == null) if (database == null)
throw new ArgumentNullException(nameof(database)); throw new ArgumentNullException(nameof(database));
var options = new DatabaseMigrationOptions();
optionsAction?.Invoke(options);
if (database.GetProviderType() == DatabaseProvider.InMemory) if (database.GetProviderType() == DatabaseProvider.InMemory)
return true; return true;
var options = new DatabaseMigrationOptions();
optionsAction?.Invoke(options);
if (string.IsNullOrWhiteSpace(options.MigrationsTableName)) if (string.IsNullOrWhiteSpace(options.MigrationsTableName))
throw new ArgumentNullException(nameof(options.MigrationsTableName), $"The property {nameof(options.MigrationsTableName)} of the {nameof(options)} parameter is required."); throw new ArgumentNullException(nameof(options.MigrationsTableName), $"The property {nameof(options.MigrationsTableName)} of the {nameof(options)} parameter is required.");
if (string.IsNullOrWhiteSpace(options.Path)) if (string.IsNullOrWhiteSpace(options.Path))
throw new ArgumentNullException(nameof(options.Path), $"The property {nameof(options.Path)} of the {nameof(options)} parameter is required."); throw new ArgumentNullException(nameof(options.Path), $"The property {nameof(options.Path)} of the {nameof(options)} parameter is required.");
await database.WaitAvailableAsync(opts =>
{
opts.WaitDelay = options.WaitDelay;
opts.Logger = options.Logger;
}, cancellationToken);
var connection = database.GetDbConnection(); var connection = database.GetDbConnection();
try try
{ {
@@ -52,7 +59,58 @@ namespace Microsoft.EntityFrameworkCore
} }
finally finally
{ {
connection.Close(); await connection.CloseAsync();
}
}
/// <summary>
/// Waits until the database connection is available.
/// </summary>
/// <param name="database">The database connection.</param>
/// <param name="optionsAction">An action to set additional options.</param>
/// <param name="cancellationToken">A cancellation token.</param>
/// <returns>An awaitable task to wait until the database is available.</returns>
public static async Task WaitAvailableAsync(this DatabaseFacade database, Action<DatabaseMigrationOptions> optionsAction = null, CancellationToken cancellationToken = default)
{
if (database == null)
throw new ArgumentNullException(nameof(database));
if (database.GetProviderType() == DatabaseProvider.InMemory)
return;
var options = new DatabaseMigrationOptions();
optionsAction?.Invoke(options);
options.Logger?.LogInformation("Waiting for a database connection");
var connection = database.GetDbConnection();
while (!cancellationToken.IsCancellationRequested)
{
try
{
await connection.OpenAsync(cancellationToken);
options.Logger?.LogInformation("Database connection available");
return;
}
catch
{
// keep things quiet
try
{
await Task.Delay(options.WaitDelay, cancellationToken);
}
catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
{
return;
}
catch
{
// keep things quiet
}
}
finally
{
await connection.CloseAsync();
}
} }
} }

View File

@@ -1,4 +1,5 @@
using System.Reflection; using System;
using System.Reflection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace Microsoft.EntityFrameworkCore namespace Microsoft.EntityFrameworkCore
@@ -27,5 +28,10 @@ namespace Microsoft.EntityFrameworkCore
/// Gets or sets the source assembly for embedded files. /// Gets or sets the source assembly for embedded files.
/// </summary> /// </summary>
public Assembly SourceAssembly { get; set; } public Assembly SourceAssembly { get; set; }
/// <summary>
/// Gets or sets a delay to wait before a connect retry.
/// </summary>
public TimeSpan WaitDelay { get; set; } = TimeSpan.FromSeconds(1);
} }
} }

View File

@@ -4,9 +4,17 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased](https://git.am-wd.de/AM.WD/common/compare/v1.4.0...master) - 0000-00-00 ## [Unreleased](https://git.am-wd.de/AM.WD/common/compare/v1.4.1...master) - 0000-00-00
_nothing changed yet_
## [v1.4.1](https://git.am-wd.de/AM.WD/common/compare/v1.4.0...v1.4.1) - 2022-03-23
### Added ### Added
- `IntegrityHashTagHelper` can be used with `asp-integrity="true|false"` and `asp-integrity-strength="256|384|512"` - `IntegrityHashTagHelper` can be used with `asp-integrity="true|false"` and `asp-integrity-strength="256|384|512"`
- `WaitAvailableAsync` can be used to wait for a database connection to be available.
### Changed
- `ApplyMigrationsAsync` uses `WaitAvailableAsync` internally.
### Fixed ### Fixed
- `InMemory` database provider does not fail on "migration" (none possible) - `InMemory` database provider does not fail on "migration" (none possible)