Move using statements to globalusing file
This commit is contained in:
		
							parent
							
								
									5fd90e8cb6
								
							
						
					
					
						commit
						9d73669d86
					
				| @ -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 | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -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(); | ||||
| 
 | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -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; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -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); | ||||
| } | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
| namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services | ||||
| public class IntegrationEventLogService : IIntegrationEventLogService, IDisposable | ||||
| { | ||||
|     public class IntegrationEventLogService : IIntegrationEventLogService, IDisposable | ||||
|     private readonly IntegrationEventLogContext _integrationEventLogContext; | ||||
|     private readonly DbConnection _dbConnection; | ||||
|     private readonly List<Type> _eventTypes; | ||||
|     private volatile bool disposedValue; | ||||
| 
 | ||||
|     public IntegrationEventLogService(DbConnection dbConnection) | ||||
|     { | ||||
|         private readonly IntegrationEventLogContext _integrationEventLogContext; | ||||
|         private readonly DbConnection _dbConnection; | ||||
|         private readonly List<Type> _eventTypes; | ||||
|         private volatile bool disposedValue; | ||||
|         _dbConnection = dbConnection ?? throw new ArgumentNullException(nameof(dbConnection)); | ||||
|         _integrationEventLogContext = new IntegrationEventLogContext( | ||||
|             new DbContextOptionsBuilder<IntegrationEventLogContext>() | ||||
|                 .UseSqlServer(_dbConnection) | ||||
|                 .Options); | ||||
| 
 | ||||
|         public IntegrationEventLogService(DbConnection dbConnection) | ||||
|         _eventTypes = Assembly.Load(Assembly.GetEntryAssembly().FullName) | ||||
|             .GetTypes() | ||||
|             .Where(t => t.Name.EndsWith(nameof(IntegrationEvent))) | ||||
|             .ToList(); | ||||
|     } | ||||
| 
 | ||||
|     public async Task<IEnumerable<IntegrationEventLogEntry>> RetrieveEventLogsPendingToPublishAsync(Guid transactionId) | ||||
|     { | ||||
|         var tid = transactionId.ToString(); | ||||
| 
 | ||||
|         var result = await _integrationEventLogContext.IntegrationEventLogs | ||||
|             .Where(e => e.TransactionId == tid && e.State == EventStateEnum.NotPublished).ToListAsync(); | ||||
| 
 | ||||
|         if (result != null && result.Any()) | ||||
|         { | ||||
|             _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(); | ||||
|             return result.OrderBy(o => o.CreationTime) | ||||
|                 .Select(e => e.DeserializeJsonContent(_eventTypes.Find(t => t.Name == e.EventTypeShortName))); | ||||
|         } | ||||
| 
 | ||||
|         public async Task<IEnumerable<IntegrationEventLogEntry>> RetrieveEventLogsPendingToPublishAsync(Guid transactionId) | ||||
|         return new List<IntegrationEventLogEntry>(); | ||||
|     } | ||||
| 
 | ||||
|     public Task SaveEventAsync(IntegrationEvent @event, IDbContextTransaction transaction) | ||||
|     { | ||||
|         if (transaction == null) throw new ArgumentNullException(nameof(transaction)); | ||||
| 
 | ||||
|         var eventLogEntry = new IntegrationEventLogEntry(@event, transaction.TransactionId); | ||||
| 
 | ||||
|         _integrationEventLogContext.Database.UseTransaction(transaction.GetDbTransaction()); | ||||
|         _integrationEventLogContext.IntegrationEventLogs.Add(eventLogEntry); | ||||
| 
 | ||||
|         return _integrationEventLogContext.SaveChangesAsync(); | ||||
|     } | ||||
| 
 | ||||
|     public Task MarkEventAsPublishedAsync(Guid eventId) | ||||
|     { | ||||
|         return UpdateEventStatus(eventId, EventStateEnum.Published); | ||||
|     } | ||||
| 
 | ||||
|     public Task MarkEventAsInProgressAsync(Guid eventId) | ||||
|     { | ||||
|         return UpdateEventStatus(eventId, EventStateEnum.InProgress); | ||||
|     } | ||||
| 
 | ||||
|     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++; | ||||
| 
 | ||||
|         _integrationEventLogContext.IntegrationEventLogs.Update(eventLogEntry); | ||||
| 
 | ||||
|         return _integrationEventLogContext.SaveChangesAsync(); | ||||
|     } | ||||
| 
 | ||||
|     protected virtual void Dispose(bool disposing) | ||||
|     { | ||||
|         if (!disposedValue) | ||||
|         { | ||||
|             var tid = transactionId.ToString(); | ||||
| 
 | ||||
|             var result = await _integrationEventLogContext.IntegrationEventLogs | ||||
|                 .Where(e => e.TransactionId == tid && e.State == EventStateEnum.NotPublished).ToListAsync(); | ||||
| 
 | ||||
|             if (result != null && result.Any()) | ||||
|             if (disposing) | ||||
|             { | ||||
|                 return result.OrderBy(o => o.CreationTime) | ||||
|                     .Select(e => e.DeserializeJsonContent(_eventTypes.Find(t => t.Name == e.EventTypeShortName))); | ||||
|                 _integrationEventLogContext?.Dispose(); | ||||
|             } | ||||
| 
 | ||||
|             return new List<IntegrationEventLogEntry>(); | ||||
|         } | ||||
| 
 | ||||
|         public Task SaveEventAsync(IntegrationEvent @event, IDbContextTransaction transaction) | ||||
|         { | ||||
|             if (transaction == null) throw new ArgumentNullException(nameof(transaction)); | ||||
| 
 | ||||
|             var eventLogEntry = new IntegrationEventLogEntry(@event, transaction.TransactionId); | ||||
| 
 | ||||
|             _integrationEventLogContext.Database.UseTransaction(transaction.GetDbTransaction()); | ||||
|             _integrationEventLogContext.IntegrationEventLogs.Add(eventLogEntry); | ||||
| 
 | ||||
|             return _integrationEventLogContext.SaveChangesAsync(); | ||||
|         } | ||||
| 
 | ||||
|         public Task MarkEventAsPublishedAsync(Guid eventId) | ||||
|         { | ||||
|             return UpdateEventStatus(eventId, EventStateEnum.Published); | ||||
|         } | ||||
| 
 | ||||
|         public Task MarkEventAsInProgressAsync(Guid eventId) | ||||
|         { | ||||
|             return UpdateEventStatus(eventId, EventStateEnum.InProgress); | ||||
|         } | ||||
| 
 | ||||
|         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++; | ||||
| 
 | ||||
|             _integrationEventLogContext.IntegrationEventLogs.Update(eventLogEntry); | ||||
| 
 | ||||
|             return _integrationEventLogContext.SaveChangesAsync(); | ||||
|         } | ||||
| 
 | ||||
|         protected virtual void Dispose(bool disposing) | ||||
|         { | ||||
|             if (!disposedValue) | ||||
|             { | ||||
|                 if (disposing) | ||||
|                 { | ||||
|                     _integrationEventLogContext?.Dispose(); | ||||
|                 } | ||||
| 
 | ||||
| 
 | ||||
|                 disposedValue = true; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public void Dispose() | ||||
|         { | ||||
|             Dispose(disposing: true); | ||||
|             GC.SuppressFinalize(this); | ||||
|             disposedValue = true; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public void Dispose() | ||||
|     { | ||||
|         Dispose(disposing: true); | ||||
|         GC.SuppressFinalize(this); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -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)); | ||||
| 
 | ||||
|     public static ResilientTransaction New(DbContext context) => | ||||
|         new ResilientTransaction(context); | ||||
| 
 | ||||
|     public async Task ExecuteAsync(Func<Task> action) | ||||
|     { | ||||
|         private DbContext _context; | ||||
|         private ResilientTransaction(DbContext context) => | ||||
|             _context = context ?? throw new ArgumentNullException(nameof(context)); | ||||
| 
 | ||||
|         public static ResilientTransaction New(DbContext context) => | ||||
|             new ResilientTransaction(context); | ||||
| 
 | ||||
|         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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user