Browse Source

Add handler logic for basket repository. Add Post to CatalogController (only for price update).

pull/126/head
dsanz 8 years ago
parent
commit
4d1269b8f2
9 changed files with 114 additions and 19 deletions
  1. +26
    -5
      src/Services/Basket/Basket.API/Events/CatalogPriceChangedHandler.cs
  2. +1
    -0
      src/Services/Basket/Basket.API/Model/BasketItem.cs
  3. +1
    -0
      src/Services/Basket/Basket.API/Model/IBasketRepository.cs
  4. +34
    -4
      src/Services/Basket/Basket.API/Model/RedisBasketRepository.cs
  5. +17
    -2
      src/Services/Basket/Basket.API/Startup.cs
  6. +25
    -1
      src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs
  7. +5
    -4
      src/Services/Common/Infrastructure/Catalog/CatalogPriceChanged.cs
  8. +3
    -2
      src/Services/Common/Infrastructure/EventBus.cs
  9. +2
    -1
      src/Services/Common/Infrastructure/IIntegrationEventHandler.cs

+ 26
- 5
src/Services/Basket/Basket.API/Events/CatalogPriceChangedHandler.cs View File

@ -11,15 +11,36 @@ namespace Basket.API.Events
public class CatalogPriceChangedHandler : IIntegrationEventHandler<CatalogPriceChanged>
{
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);
}
}
}
}

+ 1
- 0
src/Services/Basket/Basket.API/Model/BasketItem.cs View File

@ -11,6 +11,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Model
public string ProductId { get; set; }
public string ProductName { get; set; }
public decimal UnitPrice { get; set; }
public decimal OldUnitPrice { get; set; }
public int Quantity { get; set; }
public string PictureUrl { get; set; }
}


+ 1
- 0
src/Services/Basket/Basket.API/Model/IBasketRepository.cs View File

@ -8,6 +8,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Model
public interface IBasketRepository
{
Task<CustomerBasket> GetBasket(string customerId);
Task<IEnumerable<string>> GetUsers();
Task<CustomerBasket> UpdateBasket(CustomerBasket basket);
Task<bool> DeleteBasket(string id);
}


+ 34
- 4
src/Services/Basket/Basket.API/Model/RedisBasketRepository.cs View File

@ -31,6 +31,18 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Model
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)
{
var database = await GetDatabase();
@ -63,14 +75,32 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Model
{
if (_redis == null)
{
//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);
_logger.LogInformation($"Connecting to database {_settings.ConnectionString} at IP {ips.First().ToString()}");
_redis = await ConnectionMultiplexer.ConnectAsync(ips.First().ToString());
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.
var ips = await Dns.GetHostAddressesAsync(_settings.ConnectionString);
_logger.LogInformation($"Connecting to database {_settings.ConnectionString} at IP {ips.First().ToString()}");
_redis = await ConnectionMultiplexer.ConnectAsync(ips.First().ToString());
}
}
}

+ 17
- 2
src/Services/Basket/Basket.API/Startup.cs View File

@ -79,9 +79,24 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
});
services.AddTransient<IBasketRepository, RedisBasketRepository>();
var eventBus = new EventBus();
services.AddTransient<IIntegrationEventHandler<CatalogPriceChanged>, CatalogPriceChangedHandler>();
var eventBus = new 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.


+ 25
- 1
src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs View File

@ -107,7 +107,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
//hook to run integration tests until POST methods are created
if (catalogTypeId.HasValue && catalogTypeId == 1)
{
_eventBus.Publish(new CatalogPriceChanged(2, 10.4M));
_eventBus.Publish(new CatalogPriceChanged(2, 10.4M, 8.4M));
}
return Ok(model);
@ -135,6 +135,30 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
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) {
var baseUri = _settings.Value.ExternalCatalogBaseUrl;
items.ForEach(x =>


+ 5
- 4
src/Services/Common/Infrastructure/Catalog/CatalogPriceChanged.cs View File

@ -5,17 +5,18 @@ using System.Text;
namespace Microsoft.eShopOnContainers.Services.Common.Infrastructure.Catalog
{
public class CatalogPriceChanged : IIntegrationEvent
{
public string Message { get { return "CatalogPriceChanged here!!"; } }
{
public int ItemId { 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;
NewPrice = newPrice;
OldPrice = oldPrice;
}
}
}

+ 3
- 2
src/Services/Common/Infrastructure/EventBus.cs View File

@ -9,6 +9,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.Services.Common.Infrastructure
{
@ -116,7 +117,7 @@ namespace Microsoft.eShopOnContainers.Services.Common.Infrastructure
}
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
consumer.Received += async (model, ea) =>
{
var eventName = ea.RoutingKey;
if (_handlers.ContainsKey(eventName))
@ -132,7 +133,7 @@ namespace Microsoft.eShopOnContainers.Services.Common.Infrastructure
foreach (var handler in handlers)
{
concreteType.GetMethod("Handle").Invoke(handler, new object[] { integrationEvent });
await (Task)concreteType.GetMethod("Handle").Invoke(handler, new object[] { integrationEvent });
}
}
};


+ 2
- 1
src/Services/Common/Infrastructure/IIntegrationEventHandler.cs View File

@ -1,13 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.Services.Common.Infrastructure
{
public interface IIntegrationEventHandler<in TIntegrationEvent> : IIntegrationEventHandler
where TIntegrationEvent: IIntegrationEvent
{
void Handle(TIntegrationEvent @event);
Task Handle(TIntegrationEvent @event);
}
public interface IIntegrationEventHandler


Loading…
Cancel
Save