Browse Source

Add proto to catalog

features/migration-dotnet3
ericuss 5 years ago
parent
commit
67af71d2ce
8 changed files with 178 additions and 14 deletions
  1. +1
    -0
      docker-compose.override.yml
  2. +2
    -0
      src/ApiGateways/Web.Bff.Shopping/aggregator/Config/UrlsConfig.cs
  3. +31
    -5
      src/ApiGateways/Web.Bff.Shopping/aggregator/Services/CatalogService.cs
  4. +3
    -3
      src/ApiGateways/Web.Bff.Shopping/aggregator/Services/OrderingService.cs
  5. +1
    -0
      src/ApiGateways/Web.Bff.Shopping/aggregator/appsettings.localhost.json
  6. +117
    -2
      src/Services/Catalog/Catalog.API/Grpc/CatalogService.cs
  7. +1
    -1
      src/Services/Catalog/Catalog.API/Program.cs
  8. +22
    -3
      src/Services/Catalog/Catalog.API/Proto/catalog.proto

+ 1
- 0
docker-compose.override.yml View File

@ -306,6 +306,7 @@ services:
- urls__orders=http://ordering.api - urls__orders=http://ordering.api
- urls__identity=http://identity.api - urls__identity=http://identity.api
- urls__grpcBasket=http://10.0.75.1:5580 - urls__grpcBasket=http://10.0.75.1:5580
- urls__grpcCatalog=http://10.0.75.1:9101
- urls__grpcOrdering=http://10.0.75.1:5581 - urls__grpcOrdering=http://10.0.75.1:5581
- CatalogUrlHC=http://catalog.api/hc - CatalogUrlHC=http://catalog.api/hc
- OrderingUrlHC=http://ordering.api/hc - OrderingUrlHC=http://ordering.api/hc


+ 2
- 0
src/ApiGateways/Web.Bff.Shopping/aggregator/Config/UrlsConfig.cs View File

@ -11,6 +11,7 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Config
{ {
// grpc call under REST must go trough port 80 // grpc call under REST must go trough port 80
public static string GetItemById(int id) => $"/api/v1/catalog/items/{id}"; public static string GetItemById(int id) => $"/api/v1/catalog/items/{id}";
public static string GetItemById(string ids) => $"/api/v1/catalog/items/ids/{string.Join(',', ids)}";
// REST call standard must go through port 5000 // REST call standard must go through port 5000
public static string GetItemsById(IEnumerable<int> ids) => $":5000/api/v1/catalog/items?ids={string.Join(',', ids)}"; public static string GetItemsById(IEnumerable<int> ids) => $":5000/api/v1/catalog/items?ids={string.Join(',', ids)}";
} }
@ -30,6 +31,7 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Config
public string Catalog { get; set; } public string Catalog { get; set; }
public string Orders { get; set; } public string Orders { get; set; }
public string GrpcBasket { get; set; } public string GrpcBasket { get; set; }
public string GrpcCatalog { get; set; }
public string GrpcOrdering { get; set; } public string GrpcOrdering { get; set; }
} }
} }

+ 31
- 5
src/ApiGateways/Web.Bff.Shopping/aggregator/Services/CatalogService.cs View File

@ -6,6 +6,11 @@ using Newtonsoft.Json;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using CatalogApi;
using Grpc.Net.Client;
using System;
using static CatalogApi.Catalog;
using System.Linq;
namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services
{ {
@ -24,17 +29,38 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services
public async Task<CatalogItem> GetCatalogItemAsync(int id) public async Task<CatalogItem> GetCatalogItemAsync(int id)
{ {
var uri=_urls.Catalog + UrlsConfig.CatalogOperations.GetItemById(id);
var stringContent = await _httpClient.GetStringAsync(uri);
_httpClient.BaseAddress = new Uri(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemById(id));
return JsonConvert.DeserializeObject<CatalogItem>(stringContent);
var client = GrpcClient.Create<CatalogClient>(_httpClient);
var request = new CatalogItemRequest { Id = id };
var response = await client.GetItemByIdAsync(request);
return MapToCatalogItemResponse(response);
} }
public async Task<IEnumerable<CatalogItem>> GetCatalogItemsAsync(IEnumerable<int> ids) public async Task<IEnumerable<CatalogItem>> GetCatalogItemsAsync(IEnumerable<int> ids)
{ {
var stringContent = await _httpClient.GetStringAsync(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemsById(ids));
_httpClient.BaseAddress = new Uri(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemsById(ids));
var client = GrpcClient.Create<CatalogClient>(_httpClient);
var request = new CatalogItemsRequest { Ids = string.Join(",", ids), PageIndex = 1, PageSize = 10 };
var response = await client.GetItemsByIdsAsync(request);
return response.Data.Select(this.MapToCatalogItemResponse);
//var stringContent = await _httpClient.GetStringAsync(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemsById(ids));
//var catalogItems = JsonConvert.DeserializeObject<CatalogItem[]>(stringContent);
return JsonConvert.DeserializeObject<CatalogItem[]>(stringContent);
//return catalogItems;
}
private CatalogItem MapToCatalogItemResponse(CatalogItemResponse catalogItemResponse)
{
return new CatalogItem
{
Id = catalogItemResponse.Id,
Name = catalogItemResponse.Name,
PictureUri = catalogItemResponse.PictureUri,
Price = (decimal)catalogItemResponse.Price
};
} }
} }
} }

+ 3
- 3
src/ApiGateways/Web.Bff.Shopping/aggregator/Services/OrderingService.cs View File

@ -45,13 +45,12 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services
try try
{ {
var command = MapToOrderDraftCommand(basketData); var command = MapToOrderDraftCommand(basketData);
var response = await client.CreateOrderDraftFromBasketDataAsync(command); var response = await client.CreateOrderDraftFromBasketDataAsync(command);
_logger.LogDebug(" grpc response: {@response}", response); _logger.LogDebug(" grpc response: {@response}", response);
return MapToResponse(response);
return MapToResponse(response, basketData);
} }
catch (RpcException e) catch (RpcException e)
{ {
@ -63,7 +62,7 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services
return null; return null;
} }
private OrderData MapToResponse(GrpcOrdering.OrderDraftDTO orderDraft)
private OrderData MapToResponse(GrpcOrdering.OrderDraftDTO orderDraft, BasketData basketData)
{ {
if (orderDraft == null) if (orderDraft == null)
{ {
@ -72,6 +71,7 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services
var data = new OrderData var data = new OrderData
{ {
Buyer = basketData.BuyerId,
Total = (decimal)orderDraft.Total, Total = (decimal)orderDraft.Total,
}; };


+ 1
- 0
src/ApiGateways/Web.Bff.Shopping/aggregator/appsettings.localhost.json View File

@ -5,6 +5,7 @@
"orders": "http://localhost:55102", "orders": "http://localhost:55102",
"identity": "http://localhost:55105", "identity": "http://localhost:55105",
"grpcBasket": "http://localhost:5580", "grpcBasket": "http://localhost:5580",
"grpcCatalog": "http://localhost:81",
"grpcOrdering": "http://localhost:5581" "grpcOrdering": "http://localhost:5581"
} }
} }

+ 117
- 2
src/Services/Catalog/Catalog.API/Grpc/CatalogService.cs View File

@ -8,6 +8,7 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.eShopOnContainers.Services.Catalog.API; using Microsoft.eShopOnContainers.Services.Catalog.API;
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure; using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
using Microsoft.eShopOnContainers.Services.Catalog.API.Model; using Microsoft.eShopOnContainers.Services.Catalog.API.Model;
using Microsoft.eShopOnContainers.Services.Catalog.API.ViewModel;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using static CatalogApi.Catalog; using static CatalogApi.Catalog;
@ -26,10 +27,10 @@ namespace Catalog.API.Grpc
_logger = logger; _logger = logger;
} }
public override async Task<CatalogItemResponse> GetItemById(CatalogItemRequest request, ServerCallContext context)
public override async Task<CatalogItemResponse> GetItemById(CatalogItemRequest request, ServerCallContext context)
{ {
_logger.LogInformation($"Begin grpc call CatalogService.GetItemById for product id {request.Id}"); _logger.LogInformation($"Begin grpc call CatalogService.GetItemById for product id {request.Id}");
if (request.Id <=0)
if (request.Id <= 0)
{ {
context.Status = new Status(StatusCode.FailedPrecondition, $"Id must be > 0 (received {request.Id})"); context.Status = new Status(StatusCode.FailedPrecondition, $"Id must be > 0 (received {request.Id})");
return null; return null;
@ -60,5 +61,119 @@ namespace Catalog.API.Grpc
context.Status = new Status(StatusCode.NotFound, $"Product with id {request.Id} do not exist"); context.Status = new Status(StatusCode.NotFound, $"Product with id {request.Id} do not exist");
return null; return null;
} }
public override async Task<PaginatedItemsResponse> GetItemsByIds(CatalogItemsRequest request, ServerCallContext context)
{
if (!string.IsNullOrEmpty(request.Ids))
{
var items = await GetItemsByIdsAsync(request.Ids);
if (!items.Any())
{
context.Status = new Status(StatusCode.NotFound, $"ids value invalid. Must be comma-separated list of numbers");
}
context.Status = new Status(StatusCode.OK, string.Empty);
return this.MapToResponse(items);
}
var totalItems = await _catalogContext.CatalogItems
.LongCountAsync();
var itemsOnPage = await _catalogContext.CatalogItems
.OrderBy(c => c.Name)
.Skip(request.PageSize * request.PageIndex)
.Take(request.PageSize)
.ToListAsync();
/* The "awesome" fix for testing Devspaces */
/*
foreach (var pr in itemsOnPage) {
pr.Name = "Awesome " + pr.Name;
}
*/
itemsOnPage = ChangeUriPlaceholder(itemsOnPage);
var model = this.MapToResponse(itemsOnPage, totalItems, request.PageIndex, request.PageSize);
context.Status = new Status(StatusCode.OK, string.Empty);
return model;
}
private PaginatedItemsResponse MapToResponse(List<CatalogItem> items)
{
return this.MapToResponse(items, items.Count(), 1, items.Count());
}
private PaginatedItemsResponse MapToResponse(List<CatalogItem> items, long count, int pageIndex, int pageSize)
{
var result = new PaginatedItemsResponse()
{
Count = count,
PageIndex = pageIndex,
PageSize = pageSize,
};
items.ForEach(i => result.Data.Add(new CatalogItemResponse()
{
AvailableStock = i.AvailableStock,
Description = i.Description,
Id = i.Id,
MaxStockThreshold = i.MaxStockThreshold,
Name = i.Name,
OnReorder = i.OnReorder,
PictureFileName = i.PictureFileName,
PictureUri = i.PictureUri,
RestockThreshold = i.RestockThreshold,
CatalogBrand = new CatalogApi.CatalogBrand()
{
Id = i.CatalogBrand.Id,
Name = i.CatalogBrand.Brand,
},
CatalogType = new CatalogApi.CatalogType()
{
Id = i.CatalogType.Id,
Type = i.CatalogType.Type,
},
Price = (double)i.Price,
}));
return result;
}
private async Task<List<CatalogItem>> GetItemsByIdsAsync(string ids)
{
var numIds = ids.Split(',').Select(id => (Ok: int.TryParse(id, out int x), Value: x));
if (!numIds.All(nid => nid.Ok))
{
return new List<CatalogItem>();
}
var idsToSelect = numIds
.Select(id => id.Value);
var items = await _catalogContext.CatalogItems.Where(ci => idsToSelect.Contains(ci.Id)).ToListAsync();
items = ChangeUriPlaceholder(items);
return items;
}
private List<CatalogItem> ChangeUriPlaceholder(List<CatalogItem> items)
{
var baseUri = _settings.PicBaseUrl;
var azureStorageEnabled = _settings.AzureStorageEnabled;
foreach (var item in items)
{
item.FillProductUrl(baseUri, azureStorageEnabled: azureStorageEnabled);
}
return items;
}
} }
} }

+ 1
- 1
src/Services/Catalog/Catalog.API/Program.cs View File

@ -105,7 +105,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API
private static (int httpPort, int grpcPort) GetDefinedPorts(IConfiguration config) private static (int httpPort, int grpcPort) GetDefinedPorts(IConfiguration config)
{ {
var grpcPort = config.GetValue("GRPC_PORT", 5001);
var grpcPort = config.GetValue("GRPC_PORT", 81);
var port = config.GetValue("PORT", 80); var port = config.GetValue("PORT", 80);
return (port, grpcPort); return (port, grpcPort);
} }


+ 22
- 3
src/Services/Catalog/Catalog.API/Proto/catalog.proto View File

@ -10,6 +10,11 @@ package CatalogApi;
message CatalogItemRequest { message CatalogItemRequest {
int32 id = 1; int32 id = 1;
} }
message CatalogItemsRequest {
string ids = 1;
int32 pageSize = 2;
int32 pageIndex = 3;
}
message CatalogItemResponse { message CatalogItemResponse {
int32 id = 1; int32 id = 1;
@ -36,12 +41,26 @@ message CatalogType {
string type = 2; string type = 2;
} }
message PaginatedItemsResponse {
int32 pageIndex = 1;
int32 pageSize = 2;
int64 count = 3;
repeated CatalogItemResponse data = 4;
}
service Catalog { service Catalog {
rpc GetItemById (CatalogItemRequest) returns (CatalogItemResponse) { rpc GetItemById (CatalogItemRequest) returns (CatalogItemResponse) {
/* >>
/* >>
option (google.api.http) = { option (google.api.http) = {
get: "/api/v1/catalog/items/{id}" get: "/api/v1/catalog/items/{id}"
}; };
<< */
}
<< */
}
rpc GetItemsByIds (CatalogItemsRequest) returns (PaginatedItemsResponse) {
/* >>
option (google.api.http) = {
get: "/api/v1/catalog/items/ids/{ids}"
};
<< */
}
} }

Loading…
Cancel
Save