Skip to content

Commit

Permalink
Merge pull request WalletWasabi#2 from Kukks/feat/remote-notifications
Browse files Browse the repository at this point in the history
Refactor EF usage
  • Loading branch information
DanGould committed Jul 21, 2021
2 parents 7106780 + 4d81e8e commit 1810047
Show file tree
Hide file tree
Showing 12 changed files with 187 additions and 30 deletions.
3 changes: 3 additions & 0 deletions WalletWasabi.Backend/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ public Config(
[JsonProperty(PropertyName = "RegTestBitcoinCoreRpcEndPoint")]
[JsonConverter(typeof(EndPointJsonConverter), Constants.DefaultRegTestBitcoinCoreRpcPort)]
public EndPoint RegTestBitcoinCoreRpcEndPoint { get; internal set; } = new IPEndPoint(IPAddress.Loopback, Constants.DefaultRegTestBitcoinCoreRpcPort);
[DefaultValue("User ID=postgres;Host=127.0.0.1;Port=65466;Database=wasabibackend;")]
[JsonProperty(PropertyName = "DatabaseConnectionStringName", DefaultValueHandling = DefaultValueHandling.Populate)]
public string DatabaseConnectionStringName { get; internal set; }

public EndPoint GetBitcoinP2pEndPoint()
{
Expand Down
21 changes: 12 additions & 9 deletions WalletWasabi.Backend/Controllers/APNTokensController.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using WalletWasabi.Backend.Data;
using WalletWasabi.Backend.Models;
using WalletWasabi.Helpers;
Expand All @@ -12,11 +12,11 @@ namespace WalletWasabi.Backend.Controllers
[Produces("application/json")]
public class APNTokensController : ControllerBase
{
private readonly APNTokensContext Db;
private readonly IDbContextFactory<WasabiBackendContext> ContextFactory;

public APNTokensController(APNTokensContext db)
public APNTokensController(IDbContextFactory<WasabiBackendContext> contextFactory)
{
Db = db;
ContextFactory = contextFactory;
}

[HttpPost]
Expand All @@ -28,8 +28,10 @@ public async Task<IActionResult> StoreTokenAsync([FromBody] AppleDeviceToken tok
{
return BadRequest("Invalid Apple device token.");
}
Db.Tokens.Add(token);
await Db.SaveChangesAsync();

await using var context = ContextFactory.CreateDbContext();
await context.Tokens.AddAsync(token);
await context.SaveChangesAsync();
return Ok("Device token stored.");
}

Expand All @@ -42,11 +44,12 @@ public async Task<IActionResult> StoreTokenAsync([FromBody] AppleDeviceToken tok
[ProducesResponseType(200)]
public async Task<IActionResult> DeleteTokenAsync([FromRoute] string tokenString)
{
var token = await Db.Tokens.FindAsync(tokenString);
await using var context = ContextFactory.CreateDbContext();
var token = await context.Tokens.FindAsync(tokenString);
if (token != null)
{
Db.Tokens.Remove(token);
await Db.SaveChangesAsync();
context.Tokens.Remove(token);
await context.SaveChangesAsync();
}
return Ok();
}
Expand Down
15 changes: 0 additions & 15 deletions WalletWasabi.Backend/Data/APNTokensContext.cs

This file was deleted.

13 changes: 13 additions & 0 deletions WalletWasabi.Backend/Data/APNTokensDesignTimeDbContextFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Microsoft.EntityFrameworkCore;

namespace WalletWasabi.Backend.Data
{
public class WasabiDesignTimeDbContextFactory :
DesignTimeDbContextFactoryBase<WasabiBackendContext>
{
protected override WasabiBackendContext CreateNewInstance(DbContextOptions<WasabiBackendContext> options)
{
return new WasabiBackendContext(options);
}
}
}
71 changes: 71 additions & 0 deletions WalletWasabi.Backend/Data/DesignTimeDbContextFactoryBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using System;
using System.IO;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;

namespace WalletWasabi.Backend.Data
{
public abstract class DesignTimeDbContextFactoryBase<TContext> :
IDesignTimeDbContextFactory<TContext> where TContext : DbContext
{

public TContext CreateDbContext(string[] args)
{
return Create(
Directory.GetCurrentDirectory(),
Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"));
}

protected abstract TContext CreateNewInstance(
DbContextOptions<TContext> options);

public TContext Create()
{
var environmentName =
Environment.GetEnvironmentVariable(
"ASPNETCORE_ENVIRONMENT");

var basePath = AppContext.BaseDirectory;

return Create(basePath, environmentName);
}

private TContext Create(string basePath, string environmentName)
{
var builder = new ConfigurationBuilder()
.SetBasePath(basePath)
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{environmentName}.json", true)
.AddEnvironmentVariables();

var config = builder.Build();

var connstr = config.GetConnectionString("User ID=postgres;Host=127.0.0.1;Port=65466;Database=doesntmatterbecauseitisnotactuallyused;");
return Create(connstr);
}

private TContext Create(string connectionString)
{
if (string.IsNullOrEmpty(connectionString))
{
throw new ArgumentException(
$"{nameof(connectionString)} is null or empty.",
nameof(connectionString));
}

var optionsBuilder =
new DbContextOptionsBuilder<TContext>();

Console.WriteLine(
"MyDesignTimeDbContextFactory.Create(string): Connection string: {0}",
connectionString);

optionsBuilder.UseNpgsql(connectionString);

DbContextOptions<TContext> options = optionsBuilder.Options;

return CreateNewInstance(options);
}
}
}
46 changes: 46 additions & 0 deletions WalletWasabi.Backend/Data/MigrationStartupTask.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

namespace WalletWasabi.Backend.Data
{
public class MigrationStartupTask : IStartupTask
{
private readonly IServiceProvider _serviceProvider;
private readonly ILogger<MigrationStartupTask> _logger;

public MigrationStartupTask(IServiceProvider serviceProvider, ILogger<MigrationStartupTask> logger)
{
_serviceProvider = serviceProvider;
_logger = logger;
}

public async Task ExecuteAsync(CancellationToken cancellationToken = default)
{
try
{
// we cannot simply ask for this service to be injected automatically in the ctor as a dependency for
// initializing IDbContextFactory<WasabiBackendContext> is the Global.Config object, which requires
// another IStartupTask to run, but RunWithTasksAsync requires that all StartupTask services are loaded
// at once
var contextFactory = _serviceProvider.GetRequiredService<IDbContextFactory<WasabiBackendContext>>();
_logger.LogInformation($"Migrating database to latest version");
await using var context = contextFactory.CreateDbContext();
var pendingMigrations = await context.Database.GetPendingMigrationsAsync(cancellationToken);
_logger.LogInformation(pendingMigrations.Any()
? $"Running migrations: {string.Join(", ", pendingMigrations)}"
: $"Database already at latest version");
await context.Database.MigrateAsync(cancellationToken);
}
catch (Exception e)
{
_logger.LogError(e, "Error on the MigrationStartupTask");
throw;
}
}
}
}
14 changes: 14 additions & 0 deletions WalletWasabi.Backend/Data/WasabiBackendContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Microsoft.EntityFrameworkCore;
using WalletWasabi.Backend.Models;

namespace WalletWasabi.Backend.Data
{
public class WasabiBackendContext : DbContext
{
public DbSet<AppleDeviceToken> Tokens { get; set; }

public WasabiBackendContext(DbContextOptions<WasabiBackendContext> options) : base(options)
{
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace WalletWasabi.Backend.Migrations
{
[DbContext(typeof(APNTokensContext))]
[DbContext(typeof(WasabiBackendContext))]
partial class APNTokensContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
Expand Down
3 changes: 0 additions & 3 deletions WalletWasabi.Backend/Models/AppleDeviceToken.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;

namespace WalletWasabi.Backend.Models
{
Expand Down
13 changes: 12 additions & 1 deletion WalletWasabi.Backend/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore.Internal;
using WalletWasabi.Backend.Middlewares;
using WalletWasabi.Backend.Data;
using WalletWasabi.Helpers;
Expand Down Expand Up @@ -64,11 +65,21 @@ public void ConfigureServices(IServiceCollection services)

services.AddLogging(logging => logging.AddFilter((s, level) => level >= Microsoft.Extensions.Logging.LogLevel.Warning));

services.AddDbContext<APNTokensContext>();

services.AddDbContextFactory<WasabiBackendContext>((provider, builder) =>
{
var connString = provider.GetRequiredService<Global>().Config.DatabaseConnectionStringName;
if (string.IsNullOrEmpty(connString))
{
throw new ArgumentNullException("Database", "Connection string not set");
}
builder.UseNpgsql(connString, optionsBuilder => { optionsBuilder.EnableRetryOnFailure(10); });
});

services.AddSingleton<IExchangeRateProvider>(new ExchangeRateProvider());
services.AddSingleton(new Global(Configuration["datadir"]));
services.AddStartupTask<InitConfigStartupTask>();
services.AddStartupTask<MigrationStartupTask>();
services.AddResponseCompression();
}

Expand Down
14 changes: 14 additions & 0 deletions WalletWasabi.Backend/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
version: "3"
services:
postgres:
image: postgres:13.1
environment:
POSTGRES_HOST_AUTH_METHOD: trust
volumes:
- "postgres_datadir:/var/lib/postgresql/data"
ports:
- "65466:5432"
expose:
- "5432"
volumes:
postgres_datadir:

0 comments on commit 1810047

Please sign in to comment.