-
Notifications
You must be signed in to change notification settings - Fork 51
Integrate EF Core into ingestion unit of work #5615
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,21 +1,35 @@ | ||
| namespace ServiceControl.Persistence.EFCore.Implementation.UnitOfWork; | ||
|
|
||
| using Microsoft.Extensions.DependencyInjection; | ||
| using ServiceControl.Persistence.EFCore.Abstractions; | ||
| using ServiceControl.Persistence.EFCore.DbContexts; | ||
| using ServiceControl.Persistence.EFCore.Infrastructure; | ||
| using ServiceControl.Persistence.UnitOfWork; | ||
|
|
||
| public class EFIngestionUnitOfWork : IIngestionUnitOfWork | ||
| { | ||
| readonly ServiceControlDbContext dbContext; | ||
| readonly AsyncServiceScope scope; | ||
|
|
||
| public EFIngestionUnitOfWork(AsyncServiceScope scope, ServiceControlDbContext dbContext, IBodyStoragePersistence storagePersistence, EFPersisterSettings settings) | ||
| { | ||
| this.scope = scope; | ||
| this.dbContext = dbContext; | ||
| } | ||
|
|
||
| public IMonitoringIngestionUnitOfWork Monitoring => | ||
| throw new NotImplementedException(); | ||
|
|
||
| public IRecoverabilityIngestionUnitOfWork Recoverability => | ||
| throw new NotImplementedException(); | ||
|
|
||
| public Task Complete(CancellationToken cancellationToken) => | ||
| throw new NotImplementedException(); | ||
| public Task Complete(CancellationToken cancellationToken) => dbContext.SaveChangesAsync(cancellationToken); | ||
|
|
||
| public void Dispose() | ||
| public async ValueTask DisposeAsync() | ||
| { | ||
| // Nothing to dispose yet | ||
| await dbContext.DisposeAsync(); | ||
| await scope.DisposeAsync(); | ||
|
|
||
| GC.SuppressFinalize(this); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,12 +1,24 @@ | ||
| namespace ServiceControl.Persistence.EFCore.Implementation.UnitOfWork; | ||
|
|
||
| using Microsoft.Extensions.DependencyInjection; | ||
| using ServiceControl.Persistence.EFCore.Abstractions; | ||
| using ServiceControl.Persistence.EFCore.DbContexts; | ||
| using ServiceControl.Persistence.EFCore.Infrastructure; | ||
| using ServiceControl.Persistence.UnitOfWork; | ||
|
|
||
| public class EFIngestionUnitOfWorkFactory : IIngestionUnitOfWorkFactory | ||
| public class EFIngestionUnitOfWorkFactory( | ||
| IServiceProvider serviceProvider, | ||
| MinimumRequiredStorageState storageState, | ||
| IBodyStoragePersistence storagePersistence) : IIngestionUnitOfWorkFactory | ||
| { | ||
| public ValueTask<IIngestionUnitOfWork> StartNew() => | ||
| throw new NotImplementedException(); | ||
| public ValueTask<IIngestionUnitOfWork> StartNew() | ||
| { | ||
| var scope = serviceProvider.CreateAsyncScope(); | ||
| var dbContext = scope.ServiceProvider.GetRequiredService<ServiceControlDbContext>(); | ||
| var settings = scope.ServiceProvider.GetRequiredService<EFPersisterSettings>(); | ||
| var unitOfWork = new EFIngestionUnitOfWork(scope, dbContext, storagePersistence, settings); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since you are passing the container reference into the unit of work it seems like you could just resolve everything inside it's own constructor However I'd recommend instead passing it in as an (optional?) IDisposable since that's all it cares about. An added bonus here is that it also removes the depend on
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good idea, I'll do this in the next PR |
||
| return ValueTask.FromResult<IIngestionUnitOfWork>(unitOfWork); | ||
| } | ||
|
|
||
| public bool CanIngestMore() => | ||
| throw new NotImplementedException(); | ||
| public bool CanIngestMore() => storageState.CanIngestMore; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| namespace ServiceControl.Persistence.EFCore.Infrastructure; | ||
|
|
||
| using System; | ||
| using System.Threading; | ||
| using System.Threading.Tasks; | ||
|
|
||
| public interface IBodyStoragePersistence | ||
| { | ||
| Task WriteBody(string bodyId, DateTime createdOn, ReadOnlyMemory<byte> body, string contentType, CancellationToken cancellationToken = default); | ||
| Task<MessageBodyFileResult?> ReadBody(string bodyId, DateTime createdOn, CancellationToken cancellationToken = default); | ||
| Task DeleteBody(string bodyId, CancellationToken cancellationToken = default); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| namespace ServiceControl.Persistence.EFCore.Infrastructure; | ||
|
|
||
| using System.IO; | ||
|
|
||
| public class MessageBodyFileResult | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use the 'required' modifier for the props? |
||
| { | ||
| public Stream Stream { get; set; } = null!; | ||
| public string ContentType { get; set; } = null!; | ||
| public int BodySize { get; set; } | ||
| public string Etag { get; set; } = null!; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,25 +1,21 @@ | ||
| namespace ServiceControl.Persistence.UnitOfWork | ||
| namespace ServiceControl.Persistence.UnitOfWork | ||
| { | ||
| using System; | ||
| using System.Threading; | ||
| using System.Threading.Tasks; | ||
|
|
||
| public abstract class IngestionUnitOfWorkBase : IIngestionUnitOfWork | ||
| { | ||
| protected virtual void Dispose(bool disposing) | ||
| { | ||
| } | ||
| protected virtual ValueTask DisposeAsyncCore() => ValueTask.CompletedTask; | ||
|
|
||
| public void Dispose() | ||
| public async ValueTask DisposeAsync() | ||
| { | ||
| Dispose(true); | ||
| await DisposeAsyncCore(); | ||
| GC.SuppressFinalize(this); | ||
| } | ||
|
|
||
| ~IngestionUnitOfWorkBase() => Dispose(false); | ||
|
|
||
| public IMonitoringIngestionUnitOfWork Monitoring { get; protected set; } | ||
| public IRecoverabilityIngestionUnitOfWork Recoverability { get; protected set; } | ||
| public virtual Task Complete(CancellationToken cancellationToken) => Task.CompletedTask; | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'scope.dispose' on the next line should already take care of dbcontext
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this comment is implemented then you don't actually know that anymore