Add handler logic for basket repository. Add Post to CatalogController (only for price update).
This commit is contained in:
parent
5b38a49f11
commit
4d1269b8f2
@ -11,14 +11,35 @@ namespace Basket.API.Events
|
|||||||
public class CatalogPriceChangedHandler : IIntegrationEventHandler<CatalogPriceChanged>
|
public class CatalogPriceChangedHandler : IIntegrationEventHandler<CatalogPriceChanged>
|
||||||
{
|
{
|
||||||
private readonly IBasketRepository _repository;
|
private readonly IBasketRepository _repository;
|
||||||
public CatalogPriceChangedHandler()
|
public CatalogPriceChangedHandler(IBasketRepository repository)
|
||||||
{
|
{
|
||||||
//_repository = repository;
|
_repository = repository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Handle(CatalogPriceChanged @event)
|
public async Task Handle(CatalogPriceChanged @event)
|
||||||
{
|
{
|
||||||
|
var userIds = await _repository.GetUsers();
|
||||||
|
foreach (var id in userIds)
|
||||||
|
{
|
||||||
|
var basket = await _repository.GetBasket(id);
|
||||||
|
await UpdateBasket(@event.ItemId, @event.NewPrice, basket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task UpdateBasket(int itemId, decimal newPrice, CustomerBasket basket)
|
||||||
|
{
|
||||||
|
//TODO here seems to be a problem with the format
|
||||||
|
var itemsToUpdate = basket?.Items?.Where(x => int.Parse(x.Id) == itemId).ToList();
|
||||||
|
if (itemsToUpdate != null)
|
||||||
|
{
|
||||||
|
foreach (var item in itemsToUpdate)
|
||||||
|
{
|
||||||
|
var originalPrice = item.UnitPrice;
|
||||||
|
item.UnitPrice = newPrice;
|
||||||
|
item.OldUnitPrice = originalPrice;
|
||||||
|
}
|
||||||
|
await _repository.UpdateBasket(basket);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Model
|
|||||||
public string ProductId { get; set; }
|
public string ProductId { get; set; }
|
||||||
public string ProductName { get; set; }
|
public string ProductName { get; set; }
|
||||||
public decimal UnitPrice { get; set; }
|
public decimal UnitPrice { get; set; }
|
||||||
|
public decimal OldUnitPrice { get; set; }
|
||||||
public int Quantity { get; set; }
|
public int Quantity { get; set; }
|
||||||
public string PictureUrl { get; set; }
|
public string PictureUrl { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Model
|
|||||||
public interface IBasketRepository
|
public interface IBasketRepository
|
||||||
{
|
{
|
||||||
Task<CustomerBasket> GetBasket(string customerId);
|
Task<CustomerBasket> GetBasket(string customerId);
|
||||||
|
Task<IEnumerable<string>> GetUsers();
|
||||||
Task<CustomerBasket> UpdateBasket(CustomerBasket basket);
|
Task<CustomerBasket> UpdateBasket(CustomerBasket basket);
|
||||||
Task<bool> DeleteBasket(string id);
|
Task<bool> DeleteBasket(string id);
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,18 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Model
|
|||||||
return await database.KeyDeleteAsync(id.ToString());
|
return await database.KeyDeleteAsync(id.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<string>> GetUsers()
|
||||||
|
{
|
||||||
|
var server = await GetServer();
|
||||||
|
|
||||||
|
IEnumerable<RedisKey> data = server.Keys();
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return data.Select(k => k.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<CustomerBasket> GetBasket(string customerId)
|
public async Task<CustomerBasket> GetBasket(string customerId)
|
||||||
{
|
{
|
||||||
var database = await GetDatabase();
|
var database = await GetDatabase();
|
||||||
@ -62,6 +74,25 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Model
|
|||||||
private async Task<IDatabase> GetDatabase()
|
private async Task<IDatabase> GetDatabase()
|
||||||
{
|
{
|
||||||
if (_redis == null)
|
if (_redis == null)
|
||||||
|
{
|
||||||
|
await ConnectToRedisAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
return _redis.GetDatabase();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IServer> GetServer()
|
||||||
|
{
|
||||||
|
if (_redis == null)
|
||||||
|
{
|
||||||
|
await ConnectToRedisAsync();
|
||||||
|
}
|
||||||
|
var endpoint = _redis.GetEndPoints();
|
||||||
|
|
||||||
|
return _redis.GetServer(endpoint.First());
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ConnectToRedisAsync()
|
||||||
{
|
{
|
||||||
//TODO: Need to make this more robust. Also want to understand why the static connection method cannot accept dns names.
|
//TODO: Need to make this more robust. Also want to understand why the static connection method cannot accept dns names.
|
||||||
var ips = await Dns.GetHostAddressesAsync(_settings.ConnectionString);
|
var ips = await Dns.GetHostAddressesAsync(_settings.ConnectionString);
|
||||||
@ -69,8 +100,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Model
|
|||||||
_redis = await ConnectionMultiplexer.ConnectAsync(ips.First().ToString());
|
_redis = await ConnectionMultiplexer.ConnectAsync(ips.First().ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
return _redis.GetDatabase();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,9 +79,24 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
|
|||||||
});
|
});
|
||||||
|
|
||||||
services.AddTransient<IBasketRepository, RedisBasketRepository>();
|
services.AddTransient<IBasketRepository, RedisBasketRepository>();
|
||||||
|
services.AddTransient<IIntegrationEventHandler<CatalogPriceChanged>, CatalogPriceChangedHandler>();
|
||||||
|
|
||||||
var eventBus = new EventBus();
|
var eventBus = new EventBus();
|
||||||
services.AddSingleton<IEventBus>(eventBus);
|
services.AddSingleton<IEventBus>(eventBus);
|
||||||
eventBus.Subscribe<CatalogPriceChanged>(new CatalogPriceChangedHandler());
|
|
||||||
|
var serviceProvider = services.BuildServiceProvider();
|
||||||
|
var catalogPriceHandler = serviceProvider.GetService<IIntegrationEventHandler<CatalogPriceChanged>>();
|
||||||
|
eventBus.Subscribe<CatalogPriceChanged>(catalogPriceHandler);
|
||||||
|
|
||||||
|
//var container = new ContainerBuilder();
|
||||||
|
//container.Populate(services);
|
||||||
|
//container.RegisterModule(new ApplicationModule());
|
||||||
|
|
||||||
|
//return new AutofacServiceProvider(container.Build());
|
||||||
|
|
||||||
|
//var eventBus = new EventBus();
|
||||||
|
//services.AddSingleton<IEventBus>(eventBus);
|
||||||
|
//eventBus.Subscribe<CatalogPriceChanged>(new CatalogPriceChangedHandler(new RedisBasketRepository());
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
|
@ -107,7 +107,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
//hook to run integration tests until POST methods are created
|
//hook to run integration tests until POST methods are created
|
||||||
if (catalogTypeId.HasValue && catalogTypeId == 1)
|
if (catalogTypeId.HasValue && catalogTypeId == 1)
|
||||||
{
|
{
|
||||||
_eventBus.Publish(new CatalogPriceChanged(2, 10.4M));
|
_eventBus.Publish(new CatalogPriceChanged(2, 10.4M, 8.4M));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(model);
|
return Ok(model);
|
||||||
@ -135,6 +135,30 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
|||||||
return Ok(items);
|
return Ok(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<IActionResult> Post([FromBody]CatalogItem value)
|
||||||
|
{
|
||||||
|
var item = await _context.CatalogItems.SingleOrDefaultAsync(i => i.Id == value.Id);
|
||||||
|
|
||||||
|
if (item == null)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.Price != value.Price)
|
||||||
|
{
|
||||||
|
var oldPrice = item.Price;
|
||||||
|
item.Price = value.Price;
|
||||||
|
|
||||||
|
_context.CatalogItems.Update(item);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
|
||||||
|
_eventBus.Publish(new CatalogPriceChanged(item.Id, item.Price, oldPrice));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
private List<CatalogItem> ComposePicUri(List<CatalogItem> items) {
|
private List<CatalogItem> ComposePicUri(List<CatalogItem> items) {
|
||||||
var baseUri = _settings.Value.ExternalCatalogBaseUrl;
|
var baseUri = _settings.Value.ExternalCatalogBaseUrl;
|
||||||
items.ForEach(x =>
|
items.ForEach(x =>
|
||||||
|
@ -6,16 +6,17 @@ namespace Microsoft.eShopOnContainers.Services.Common.Infrastructure.Catalog
|
|||||||
{
|
{
|
||||||
public class CatalogPriceChanged : IIntegrationEvent
|
public class CatalogPriceChanged : IIntegrationEvent
|
||||||
{
|
{
|
||||||
public string Message { get { return "CatalogPriceChanged here!!"; } }
|
|
||||||
|
|
||||||
public int ItemId { get; private set; }
|
public int ItemId { get; private set; }
|
||||||
|
|
||||||
public decimal NewPrice { get; private set; }
|
public decimal NewPrice { get; private set; }
|
||||||
|
|
||||||
public CatalogPriceChanged(int itemId, decimal newPrice)
|
public decimal OldPrice { get; set; }
|
||||||
|
|
||||||
|
public CatalogPriceChanged(int itemId, decimal newPrice, decimal oldPrice)
|
||||||
{
|
{
|
||||||
ItemId = itemId;
|
ItemId = itemId;
|
||||||
NewPrice = newPrice;
|
NewPrice = newPrice;
|
||||||
|
OldPrice = oldPrice;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Services.Common.Infrastructure
|
namespace Microsoft.eShopOnContainers.Services.Common.Infrastructure
|
||||||
{
|
{
|
||||||
@ -116,7 +117,7 @@ namespace Microsoft.eShopOnContainers.Services.Common.Infrastructure
|
|||||||
}
|
}
|
||||||
|
|
||||||
var consumer = new EventingBasicConsumer(channel);
|
var consumer = new EventingBasicConsumer(channel);
|
||||||
consumer.Received += (model, ea) =>
|
consumer.Received += async (model, ea) =>
|
||||||
{
|
{
|
||||||
var eventName = ea.RoutingKey;
|
var eventName = ea.RoutingKey;
|
||||||
if (_handlers.ContainsKey(eventName))
|
if (_handlers.ContainsKey(eventName))
|
||||||
@ -132,7 +133,7 @@ namespace Microsoft.eShopOnContainers.Services.Common.Infrastructure
|
|||||||
|
|
||||||
foreach (var handler in handlers)
|
foreach (var handler in handlers)
|
||||||
{
|
{
|
||||||
concreteType.GetMethod("Handle").Invoke(handler, new object[] { integrationEvent });
|
await (Task)concreteType.GetMethod("Handle").Invoke(handler, new object[] { integrationEvent });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Services.Common.Infrastructure
|
namespace Microsoft.eShopOnContainers.Services.Common.Infrastructure
|
||||||
{
|
{
|
||||||
public interface IIntegrationEventHandler<in TIntegrationEvent> : IIntegrationEventHandler
|
public interface IIntegrationEventHandler<in TIntegrationEvent> : IIntegrationEventHandler
|
||||||
where TIntegrationEvent: IIntegrationEvent
|
where TIntegrationEvent: IIntegrationEvent
|
||||||
{
|
{
|
||||||
void Handle(TIntegrationEvent @event);
|
Task Handle(TIntegrationEvent @event);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IIntegrationEventHandler
|
public interface IIntegrationEventHandler
|
||||||
|
Loading…
x
Reference in New Issue
Block a user