Skip to content

Commit 6ee20b9

Browse files
committed
Discount GRpc service created
1 parent ba0263e commit 6ee20b9

File tree

14 files changed

+365
-1
lines changed

14 files changed

+365
-1
lines changed

Src/Services/Basket/Basket.API/Basket.API.csproj

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@
1010
</PropertyGroup>
1111

1212
<ItemGroup>
13+
<PackageReference Include="Grpc.AspNetCore" Version="2.40.0" />
1314
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="7.0.4" />
14-
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.0" />
15+
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.18.1" />
1516
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
1617
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
1718
</ItemGroup>
@@ -20,4 +21,10 @@
2021
<Folder Include="Data\" />
2122
</ItemGroup>
2223

24+
<ItemGroup>
25+
<Protobuf Include="..\..\Discount\Discount.Grpc\Protos\discount.proto" GrpcServices="Client">
26+
<Link>Protos\discount.proto</Link>
27+
</Protobuf>
28+
</ItemGroup>
29+
2330
</Project>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net6.0</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<None Remove="Protos\discount.proto" />
11+
</ItemGroup>
12+
13+
<ItemGroup>
14+
<Protobuf Include="Protos\discount.proto" GrpcServices="Server" />
15+
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
16+
</ItemGroup>
17+
18+
<ItemGroup>
19+
<PackageReference Include="Grpc.AspNetCore" Version="2.52.0" />
20+
<PackageReference Include="npgsql" Version="7.0.2" />
21+
<PackageReference Include="dapper" Version="2.0.123" />
22+
</ItemGroup>
23+
24+
</Project>
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
using Microsoft.Extensions.Hosting;
2+
using Npgsql;
3+
4+
namespace Discount.Grpc.Extensions;
5+
6+
public static class WebAppExtensions
7+
{
8+
public static WebApplication MigrateDatabase<TContext>(this WebApplication application, int retry = 0)
9+
{
10+
int retryCount = retry;
11+
using (var scope = application.Services.CreateScope())
12+
{
13+
var services = scope.ServiceProvider;
14+
var configuration = services.GetRequiredService<IConfiguration>();
15+
var logger = services.GetRequiredService<ILogger<TContext>>();
16+
try
17+
{
18+
logger.LogInformation("Migrating postresql database.");
19+
using var conn = new NpgsqlConnection(configuration.GetValue<string>("PostgreDbSetting:ConnectionString"));
20+
conn.Open();
21+
using (var cmd = conn.CreateCommand()) {
22+
cmd.CommandText = "DROP TABLE IF EXISTS Coupon";
23+
cmd.ExecuteNonQuery();
24+
25+
cmd.CommandText = @"CREATE TABLE Coupon(Id SERIAL PRIMARY KEY,
26+
ProductName VARCHAR(24) NOT NULL,
27+
Description TEXT,
28+
Amount INT)";
29+
cmd.ExecuteNonQuery();
30+
31+
cmd.CommandText = "INSERT INTO Coupon(ProductName, Description, Amount) VALUES('IPhone X', 'IPhone Discount', 150);";
32+
cmd.ExecuteNonQuery();
33+
34+
cmd.CommandText = "INSERT INTO Coupon(ProductName, Description, Amount) VALUES('Samsung 10', 'Samsung Discount', 100);";
35+
cmd.ExecuteNonQuery();
36+
}
37+
conn.Close();
38+
logger.LogInformation("Migrated postresql database.");
39+
}
40+
catch (NpgsqlException ex)
41+
{
42+
logger.LogError(ex, "An error occurred while migrating the postresql database");
43+
if (retryCount < 50)
44+
{
45+
retryCount++;
46+
System.Threading.Thread.Sleep(2000);
47+
logger.LogInformation("Retring Migration: {0}", retry);
48+
MigrateDatabase<TContext>(application, retryCount);
49+
}
50+
}
51+
}
52+
return application;
53+
}
54+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace Discount.Grpc.Models
2+
{
3+
public class Coupon
4+
{
5+
public int ID { get; set; }
6+
public string ProductName { get; set; }
7+
public string Description { get; set; }
8+
public int Amount { get; set; }
9+
}
10+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using Discount.Grpc.Extensions;
2+
using Discount.Grpc.Repositories;
3+
using Discount.Grpc.Services;
4+
5+
var builder = WebApplication.CreateBuilder(args);
6+
7+
// Additional configuration is required to successfully run gRPC on macOS.
8+
// For instructions on how to configure Kestrel and gRPC clients on macOS, visit https://go.microsoft.com/fwlink/?linkid=2099682
9+
10+
// Add services to the container.
11+
builder.Services.AddGrpc();
12+
builder.Services.AddScoped<IDiscountRepository, DiscountRepository>();
13+
14+
var app = builder.Build();
15+
16+
app.MigrateDatabase<Program>();
17+
18+
// Configure the HTTP request pipeline.
19+
app.MapGrpcService<GreeterService>();
20+
app.MapGrpcService<DiscountService>();
21+
22+
app.MapGet("/", () => "Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909");
23+
24+
app.Run();
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"profiles": {
3+
"Discount.Grpc": {
4+
"commandName": "Project",
5+
"environmentVariables": {
6+
"ASPNETCORE_ENVIRONMENT": "Development"
7+
},
8+
"dotnetRunMessages": true,
9+
"applicationUrl": "http://localhost:5003"
10+
}
11+
}
12+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
syntax = "proto3";
2+
3+
option csharp_namespace = "Discount.Grpc.Protos";
4+
5+
package discount;
6+
7+
service DiscountProto{
8+
rpc GetDiscount(DiscountGetRequest) returns (CouponModel);
9+
rpc CreateDiscount(DiscountChangeRequest) returns (CouponModel);
10+
rpc UpdateDiscount(DiscountChangeRequest) returns (CouponModel);
11+
rpc DeleteDiscount(DiscountGetRequest) returns (DeleteResponse);
12+
}
13+
14+
message CouponModel{
15+
int32 id = 1;
16+
string productName = 2;
17+
string description = 3;
18+
int32 amount = 4;
19+
}
20+
message DiscountChangeRequest{
21+
CouponModel coupon = 1;
22+
}
23+
message DiscountGetRequest{
24+
string productName = 1;
25+
}
26+
message DeleteResponse{
27+
bool success = 1;
28+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
syntax = "proto3";
2+
3+
option csharp_namespace = "Discount.Grpc";
4+
5+
package greet;
6+
7+
// The greeting service definition.
8+
service Greeter {
9+
// Sends a greeting
10+
rpc SayHello (HelloRequest) returns (HelloReply);
11+
}
12+
13+
// The request message containing the user's name.
14+
message HelloRequest {
15+
string name = 1;
16+
}
17+
18+
// The response message containing the greetings.
19+
message HelloReply {
20+
string message = 1;
21+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using Dapper;
2+
using Discount.Grpc.Models;
3+
using Npgsql;
4+
5+
namespace Discount.Grpc.Repositories
6+
{
7+
public class DiscountRepository:IDiscountRepository
8+
{
9+
private readonly IConfiguration configuration;
10+
public DiscountRepository(IConfiguration configuration)
11+
{
12+
this.configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
13+
}
14+
15+
public async Task<Coupon> GetCoupon(string productName)
16+
{
17+
using (var conn = new NpgsqlConnection(configuration.GetValue<string>("PostgreDbSetting:ConnectionString")))
18+
{
19+
Coupon coupon = await conn.QueryFirstOrDefaultAsync<Coupon>
20+
("Select * from Coupon where ProductName=@ProductName", new { ProductName = productName });
21+
22+
return coupon ?? new Coupon { ProductName = "No Discount", Amount = 0, Description = "No Discount Available." };
23+
}
24+
}
25+
26+
public async Task<bool> CreateCoupon(Coupon coupon)
27+
{
28+
using (var conn = new NpgsqlConnection(configuration.GetValue<string>("PostgreDbSetting:ConnectionString")))
29+
{
30+
var result = await conn.ExecuteAsync
31+
("INSERT INTO Coupon (ProductName, Description, Amount) VALUES (@ProductName, @Description, @Amount)",
32+
new { ProductName = coupon.ProductName, Description = coupon.Description, Amount = coupon.Description });
33+
34+
return (result > 0);
35+
}
36+
}
37+
38+
public async Task<bool> DeleteCoupon(string productName)
39+
{
40+
using (var conn = new NpgsqlConnection(configuration.GetValue<string>("PostgreDbSetting:ConnectionString")))
41+
{
42+
var result = await conn.ExecuteAsync
43+
("delete from Coupon where ProductName=@ProductName)",
44+
new { ProductName = productName });
45+
46+
return (result > 0);
47+
}
48+
}
49+
50+
public async Task<bool> UpdateCoupon(Coupon coupon)
51+
{
52+
using (var conn = new NpgsqlConnection(configuration.GetValue<string>("PostgreDbSetting:ConnectionString")))
53+
{
54+
var result = await conn.ExecuteAsync
55+
("Update Coupon set ProductName=@ProductName, Description=@Description, Amount=@Amount where ID=@Id)",
56+
new { ProductName = coupon.ProductName, Description = coupon.Description, Amount = coupon.Description, Id=coupon.ID });
57+
58+
return (result > 0);
59+
}
60+
}
61+
}
62+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using Discount.Grpc.Models;
2+
3+
namespace Discount.Grpc.Repositories
4+
{
5+
public interface IDiscountRepository
6+
{
7+
Task<Coupon> GetCoupon(string ProductName);
8+
Task<bool> CreateCoupon(Coupon coupon);
9+
Task<bool> UpdateCoupon(Coupon coupon);
10+
Task<bool> DeleteCoupon(string ProductName);
11+
}
12+
}

0 commit comments

Comments
 (0)