Browse Source

Move using statements to globalusing file

pull/1770/head
Sumit Ghosh 3 years ago
parent
commit
9d73669d86
6 changed files with 160 additions and 194 deletions
  1. +8
    -8
      src/BuildingBlocks/EventBus/IntegrationEventLogEF/EventStateEnum.cs
  2. +25
    -29
      src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogContext.cs
  3. +29
    -36
      src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEntry.cs
  4. +7
    -14
      src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IIntegrationEventLogService.cs
  5. +73
    -84
      src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IntegrationEventLogService.cs
  6. +18
    -23
      src/BuildingBlocks/EventBus/IntegrationEventLogEF/Utilities/ResilientTransaction.cs

+ 8
- 8
src/BuildingBlocks/EventBus/IntegrationEventLogEF/EventStateEnum.cs View File

@ -1,10 +1,10 @@
namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF
namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
public enum EventStateEnum
{ {
public enum EventStateEnum
{
NotPublished = 0,
InProgress = 1,
Published = 2,
PublishedFailed = 3
}
NotPublished = 0,
InProgress = 1,
Published = 2,
PublishedFailed = 3
} }

+ 25
- 29
src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogContext.cs View File

@ -1,45 +1,41 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF
public class IntegrationEventLogContext : DbContext
{ {
public class IntegrationEventLogContext : DbContext
public IntegrationEventLogContext(DbContextOptions<IntegrationEventLogContext> options) : base(options)
{ {
public IntegrationEventLogContext(DbContextOptions<IntegrationEventLogContext> options) : base(options)
{
}
}
public DbSet<IntegrationEventLogEntry> IntegrationEventLogs { get; set; }
public DbSet<IntegrationEventLogEntry> IntegrationEventLogs { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<IntegrationEventLogEntry>(ConfigureIntegrationEventLogEntry);
}
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<IntegrationEventLogEntry>(ConfigureIntegrationEventLogEntry);
}
void ConfigureIntegrationEventLogEntry(EntityTypeBuilder<IntegrationEventLogEntry> builder)
{
builder.ToTable("IntegrationEventLog");
void ConfigureIntegrationEventLogEntry(EntityTypeBuilder<IntegrationEventLogEntry> builder)
{
builder.ToTable("IntegrationEventLog");
builder.HasKey(e => e.EventId);
builder.HasKey(e => e.EventId);
builder.Property(e => e.EventId)
.IsRequired();
builder.Property(e => e.EventId)
.IsRequired();
builder.Property(e => e.Content)
.IsRequired();
builder.Property(e => e.Content)
.IsRequired();
builder.Property(e => e.CreationTime)
.IsRequired();
builder.Property(e => e.CreationTime)
.IsRequired();
builder.Property(e => e.State)
.IsRequired();
builder.Property(e => e.State)
.IsRequired();
builder.Property(e => e.TimesSent)
.IsRequired();
builder.Property(e => e.TimesSent)
.IsRequired();
builder.Property(e => e.EventTypeName)
.IsRequired();
builder.Property(e => e.EventTypeName)
.IsRequired();
}
} }
} }

+ 29
- 36
src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEntry.cs View File

@ -1,43 +1,36 @@
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
using System;
using System.Text.Json;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF
public class IntegrationEventLogEntry
{ {
public class IntegrationEventLogEntry
private IntegrationEventLogEntry() { }
public IntegrationEventLogEntry(IntegrationEvent @event, Guid transactionId)
{ {
private IntegrationEventLogEntry() { }
public IntegrationEventLogEntry(IntegrationEvent @event, Guid transactionId)
EventId = @event.Id;
CreationTime = @event.CreationDate;
EventTypeName = @event.GetType().FullName;
Content = JsonSerializer.Serialize(@event, @event.GetType(), new JsonSerializerOptions
{ {
EventId = @event.Id;
CreationTime = @event.CreationDate;
EventTypeName = @event.GetType().FullName;
Content = JsonSerializer.Serialize(@event, @event.GetType(), new JsonSerializerOptions
{
WriteIndented = true
});
State = EventStateEnum.NotPublished;
TimesSent = 0;
TransactionId = transactionId.ToString();
}
public Guid EventId { get; private set; }
public string EventTypeName { get; private set; }
[NotMapped]
public string EventTypeShortName => EventTypeName.Split('.')?.Last();
[NotMapped]
public IntegrationEvent IntegrationEvent { get; private set; }
public EventStateEnum State { get; set; }
public int TimesSent { get; set; }
public DateTime CreationTime { get; private set; }
public string Content { get; private set; }
public string TransactionId { get; private set; }
WriteIndented = true
});
State = EventStateEnum.NotPublished;
TimesSent = 0;
TransactionId = transactionId.ToString();
}
public Guid EventId { get; private set; }
public string EventTypeName { get; private set; }
[NotMapped]
public string EventTypeShortName => EventTypeName.Split('.')?.Last();
[NotMapped]
public IntegrationEvent IntegrationEvent { get; private set; }
public EventStateEnum State { get; set; }
public int TimesSent { get; set; }
public DateTime CreationTime { get; private set; }
public string Content { get; private set; }
public string TransactionId { get; private set; }
public IntegrationEventLogEntry DeserializeJsonContent(Type type)
{
IntegrationEvent = JsonSerializer.Deserialize(Content, type, new JsonSerializerOptions() { PropertyNameCaseInsensitive = true }) as IntegrationEvent;
return this;
}
public IntegrationEventLogEntry DeserializeJsonContent(Type type)
{
IntegrationEvent = JsonSerializer.Deserialize(Content, type, new JsonSerializerOptions() { PropertyNameCaseInsensitive = true }) as IntegrationEvent;
return this;
} }
} }

+ 7
- 14
src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IIntegrationEventLogService.cs View File

@ -1,17 +1,10 @@
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services;
namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services
public interface IIntegrationEventLogService
{ {
public interface IIntegrationEventLogService
{
Task<IEnumerable<IntegrationEventLogEntry>> RetrieveEventLogsPendingToPublishAsync(Guid transactionId);
Task SaveEventAsync(IntegrationEvent @event, IDbContextTransaction transaction);
Task MarkEventAsPublishedAsync(Guid eventId);
Task MarkEventAsInProgressAsync(Guid eventId);
Task MarkEventAsFailedAsync(Guid eventId);
}
Task<IEnumerable<IntegrationEventLogEntry>> RetrieveEventLogsPendingToPublishAsync(Guid transactionId);
Task SaveEventAsync(IntegrationEvent @event, IDbContextTransaction transaction);
Task MarkEventAsPublishedAsync(Guid eventId);
Task MarkEventAsInProgressAsync(Guid eventId);
Task MarkEventAsFailedAsync(Guid eventId);
} }

+ 73
- 84
src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IntegrationEventLogService.cs View File

@ -1,110 +1,99 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services
{
public class IntegrationEventLogService : IIntegrationEventLogService, IDisposable
{
private readonly IntegrationEventLogContext _integrationEventLogContext;
private readonly DbConnection _dbConnection;
private readonly List<Type> _eventTypes;
private volatile bool disposedValue;
namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services;
public IntegrationEventLogService(DbConnection dbConnection)
{
_dbConnection = dbConnection ?? throw new ArgumentNullException(nameof(dbConnection));
_integrationEventLogContext = new IntegrationEventLogContext(
new DbContextOptionsBuilder<IntegrationEventLogContext>()
.UseSqlServer(_dbConnection)
.Options);
_eventTypes = Assembly.Load(Assembly.GetEntryAssembly().FullName)
.GetTypes()
.Where(t => t.Name.EndsWith(nameof(IntegrationEvent)))
.ToList();
}
public class IntegrationEventLogService : IIntegrationEventLogService, IDisposable
{
private readonly IntegrationEventLogContext _integrationEventLogContext;
private readonly DbConnection _dbConnection;
private readonly List<Type> _eventTypes;
private volatile bool disposedValue;
public async Task<IEnumerable<IntegrationEventLogEntry>> RetrieveEventLogsPendingToPublishAsync(Guid transactionId)
{
var tid = transactionId.ToString();
public IntegrationEventLogService(DbConnection dbConnection)
{
_dbConnection = dbConnection ?? throw new ArgumentNullException(nameof(dbConnection));
_integrationEventLogContext = new IntegrationEventLogContext(
new DbContextOptionsBuilder<IntegrationEventLogContext>()
.UseSqlServer(_dbConnection)
.Options);
_eventTypes = Assembly.Load(Assembly.GetEntryAssembly().FullName)
.GetTypes()
.Where(t => t.Name.EndsWith(nameof(IntegrationEvent)))
.ToList();
}
var result = await _integrationEventLogContext.IntegrationEventLogs
.Where(e => e.TransactionId == tid && e.State == EventStateEnum.NotPublished).ToListAsync();
public async Task<IEnumerable<IntegrationEventLogEntry>> RetrieveEventLogsPendingToPublishAsync(Guid transactionId)
{
var tid = transactionId.ToString();
if (result != null && result.Any())
{
return result.OrderBy(o => o.CreationTime)
.Select(e => e.DeserializeJsonContent(_eventTypes.Find(t => t.Name == e.EventTypeShortName)));
}
var result = await _integrationEventLogContext.IntegrationEventLogs
.Where(e => e.TransactionId == tid && e.State == EventStateEnum.NotPublished).ToListAsync();
return new List<IntegrationEventLogEntry>();
if (result != null && result.Any())
{
return result.OrderBy(o => o.CreationTime)
.Select(e => e.DeserializeJsonContent(_eventTypes.Find(t => t.Name == e.EventTypeShortName)));
} }
public Task SaveEventAsync(IntegrationEvent @event, IDbContextTransaction transaction)
{
if (transaction == null) throw new ArgumentNullException(nameof(transaction));
return new List<IntegrationEventLogEntry>();
}
var eventLogEntry = new IntegrationEventLogEntry(@event, transaction.TransactionId);
public Task SaveEventAsync(IntegrationEvent @event, IDbContextTransaction transaction)
{
if (transaction == null) throw new ArgumentNullException(nameof(transaction));
_integrationEventLogContext.Database.UseTransaction(transaction.GetDbTransaction());
_integrationEventLogContext.IntegrationEventLogs.Add(eventLogEntry);
var eventLogEntry = new IntegrationEventLogEntry(@event, transaction.TransactionId);
return _integrationEventLogContext.SaveChangesAsync();
}
_integrationEventLogContext.Database.UseTransaction(transaction.GetDbTransaction());
_integrationEventLogContext.IntegrationEventLogs.Add(eventLogEntry);
public Task MarkEventAsPublishedAsync(Guid eventId)
{
return UpdateEventStatus(eventId, EventStateEnum.Published);
}
return _integrationEventLogContext.SaveChangesAsync();
}
public Task MarkEventAsInProgressAsync(Guid eventId)
{
return UpdateEventStatus(eventId, EventStateEnum.InProgress);
}
public Task MarkEventAsPublishedAsync(Guid eventId)
{
return UpdateEventStatus(eventId, EventStateEnum.Published);
}
public Task MarkEventAsFailedAsync(Guid eventId)
{
return UpdateEventStatus(eventId, EventStateEnum.PublishedFailed);
}
public Task MarkEventAsInProgressAsync(Guid eventId)
{
return UpdateEventStatus(eventId, EventStateEnum.InProgress);
}
private Task UpdateEventStatus(Guid eventId, EventStateEnum status)
{
var eventLogEntry = _integrationEventLogContext.IntegrationEventLogs.Single(ie => ie.EventId == eventId);
eventLogEntry.State = status;
public Task MarkEventAsFailedAsync(Guid eventId)
{
return UpdateEventStatus(eventId, EventStateEnum.PublishedFailed);
}
private Task UpdateEventStatus(Guid eventId, EventStateEnum status)
{
var eventLogEntry = _integrationEventLogContext.IntegrationEventLogs.Single(ie => ie.EventId == eventId);
eventLogEntry.State = status;
if (status == EventStateEnum.InProgress)
eventLogEntry.TimesSent++;
if (status == EventStateEnum.InProgress)
eventLogEntry.TimesSent++;
_integrationEventLogContext.IntegrationEventLogs.Update(eventLogEntry);
_integrationEventLogContext.IntegrationEventLogs.Update(eventLogEntry);
return _integrationEventLogContext.SaveChangesAsync();
}
return _integrationEventLogContext.SaveChangesAsync();
}
protected virtual void Dispose(bool disposing)
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{ {
if (!disposedValue)
if (disposing)
{ {
if (disposing)
{
_integrationEventLogContext?.Dispose();
}
_integrationEventLogContext?.Dispose();
}
disposedValue = true;
}
disposedValue = true;
} }
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
} }
} }

+ 18
- 23
src/BuildingBlocks/EventBus/IntegrationEventLogEF/Utilities/ResilientTransaction.cs View File

@ -1,31 +1,26 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Utilities;
namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Utilities
public class ResilientTransaction
{ {
public class ResilientTransaction
{
private DbContext _context;
private ResilientTransaction(DbContext context) =>
_context = context ?? throw new ArgumentNullException(nameof(context));
private DbContext _context;
private ResilientTransaction(DbContext context) =>
_context = context ?? throw new ArgumentNullException(nameof(context));
public static ResilientTransaction New(DbContext context) =>
new ResilientTransaction(context);
public static ResilientTransaction New(DbContext context) =>
new ResilientTransaction(context);
public async Task ExecuteAsync(Func<Task> action)
public async Task ExecuteAsync(Func<Task> action)
{
//Use of an EF Core resiliency strategy when using multiple DbContexts within an explicit BeginTransaction():
//See: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
var strategy = _context.Database.CreateExecutionStrategy();
await strategy.ExecuteAsync(async () =>
{ {
//Use of an EF Core resiliency strategy when using multiple DbContexts within an explicit BeginTransaction():
//See: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
var strategy = _context.Database.CreateExecutionStrategy();
await strategy.ExecuteAsync(async () =>
using (var transaction = _context.Database.BeginTransaction())
{ {
using (var transaction = _context.Database.BeginTransaction())
{
await action();
transaction.Commit();
}
});
}
await action();
transaction.Commit();
}
});
} }
} }

Loading…
Cancel
Save