Created
June 20, 2018 23:53
-
-
Save BrutalSimplicity/00ed60869f49b19ac630485f2a3c6287 to your computer and use it in GitHub Desktop.
transaction repo brainstorm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// this is only a marker for resolving the TransactionalQueryManager | |
public interface ITransactionRepository | |
{ | |
} | |
public class ProductRepository : IProductRepository, ITransactionRepository | |
{ | |
} | |
// remove IProductTransactionRepository and implementations | |
// remove ProductTransactionFactory | |
public class TransactionScopedRepositoryFactory : ITransactionScopedRepository | |
{ | |
IEnumerable<ITransactionRepository> _repositories; | |
// when passed an Enumerable, Autofac will automatically | |
// give you all implementations registered to that interface | |
public TransactionScopedRepositoryFactory( | |
IEnumerable<ITransactionRepository> repositories | |
{ | |
_repositories = repositories; | |
} | |
public void Create<T>() | |
{ | |
return repositories.FirstOrDefault(r => r.GetType() == typeof(T)); | |
} | |
} | |
// in DefaultAutoBuilder.cs handle binding all of the repositories that need the | |
// transactional query manager | |
// all of these should be resolved with the same `TransactionalQueryManager` | |
// instance during the scope of a job, so their operations should be included | |
// in the transaction ** I think :) ** | |
this.RegisterType<TransactionalQueryManager>().As<ITransactionalQueryManager>().InstancePerLifetimeScope(); | |
this.RegisterType<ProductRepository>().As<ITransactionRepository>().InstancePerLifetimeScope() | |
.WithParameters(new[] { | |
new Autofac.Core.ResolvedParameter( | |
(pi, ctx) => pi.ParameterType == typeof(IQueryManager), | |
(pi, ctx) => ctx.Resolve<ITransactionalQueryManager>() | |
) | |
}); | |
this.RegisterType<UpdateProductItemRepository>().As<ITransactionRepository>().InstancePerLifetimeScope() | |
.WithParameters(new[] { | |
new Autofac.Core.ResolvedParameter( | |
(pi, ctx) => pi.ParameterType == typeof(IQueryManager), | |
(pi, ctx) => ctx.Resolve<ITransactionalQueryManager>() | |
) | |
}); | |
// usage in service | |
public class ProductUpdateJob | |
{ | |
ITransactinoalQueryManager _manager; | |
IUpdateProductItemRepository _updateRepo; | |
IProductRepository _productRepo; | |
public ProductUpdateJob( | |
ITransactionalQueryManager manager, | |
IProductRepository productRepo, | |
IUpdateProductItemRepository updateRepo | |
{ | |
_manager = manager; | |
_productRepo = productRepo; | |
_updateRepo = updateRepo; | |
} | |
public void ProcessProducts(int limit) | |
{ | |
var items = _updateRepo.GetNextBatchForUpdate(limit); | |
var productsForUpdate = _productRepo.GetWhere("select * from products where pid = any(@pids) for update", | |
new { pids = items.Select(p => p.PID.Value).ToArray() }); | |
// join back with items somehow | |
foreach (var product in productsForUpdate) | |
{ | |
DoUpdate(product); | |
DoRemove(product); | |
} | |
Update(items); | |
_productRepo.Save(productsForUpdate); | |
_updateRepo.Save(items) | |
// this effectively commits the transaction across all of the repositories | |
_manager.Commit(); | |
} | |
} | |
public TestClass | |
{ | |
public void Transaction_scope_should_be_shared() | |
{ | |
var container = ShopSavvyDependencyModule.LoadBindings(() => builder | |
{ | |
builder.RegisterType<MyOwnTransactionQueryManager>().As<ITransactionalQueryManager>(); | |
}); | |
var transactionManager = (MyOwnTransactionQueryManager)context.Resolve<ITransactionalQueryManager>(); | |
var repos = context.Resolve<IEnumerable<ITransactionScopedRepository>>(); | |
// now check that the instance count remains the same | |
Assert.AreEqual(1, transactionManager.InstanceCount); | |
} | |
} | |
public class MyOwnTransactionQueryManager : ITransactionalQueryManager | |
{ | |
public static InstanceCount; | |
public MyOwnTransactionQueryManager() | |
{ | |
InstanceCount++; | |
} | |
// implement interface | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment