Skip to content

pskumar81/Calculator.Grpc

Repository files navigation

Calculator gRPC Service

CI/CD Pipeline Package Build Pull Request Validation Code Quality

A modern calculator implementation using gRPC for service communication in .NET 9.0. This project demonstrates how to build a distributed calculator service with client-server architecture using gRPC, containerized with Docker, and packaged as reusable NuGet and npm packages using Cake build system.

πŸ“¦ NuGet Packages

  • Calculator.Server - gRPC server library and service implementation
  • Calculator.Client - gRPC client library for consuming calculator services

πŸ“¦ npm Packages

  • @calculator/web - Angular web client library for calculator services

Project Structure

  • Calculator.Server: gRPC server implementation with calculator operations

    • Supports basic arithmetic operations (Add, Subtract, Multiply, Divide)
    • Includes input validation and error handling
    • Uses logging for operation tracking
    • Containerized with Docker
    • Supports gRPC-Web for browser compatibility
    • Available as NuGet package
  • Calculator.Client: Console application that connects to the gRPC server

    • Demonstrates how to make gRPC calls to the server
    • Implements dependency injection for better service management
    • Uses structured logging for operation tracking
    • Handles server responses and errors
    • Containerized with Docker
    • Configurable server connection through environment variables
    • Available as NuGet package
  • Calculator.Web: Angular web client application

    • Modern web interface for the calculator service
    • Two input fields for numbers
    • Operation buttons (Add, Subtract, Multiply, Divide)
    • Submit and Clear functionality
    • Real-time result display with error handling
    • Responsive design with clean UI
    • Uses gRPC-Web to communicate with the server
    • Available as npm package
  • Calculator.Tests: Unit tests for the calculator service

    • Tests all arithmetic operations
    • Includes edge cases and error scenarios
    • Uses xUnit testing framework
  • Docker Support: Complete containerization

    • Multi-stage builds for optimal image size
    • Docker Compose for orchestration
    • Isolated network for service communication
    • Web client served via Nginx

πŸ› οΈ Build System

This project uses Cake (C# Make) for cross-platform build automation:

  • build.cake: Main build script with all build tasks
  • build.ps1: PowerShell bootstrap script for Windows
  • build.sh: Bash bootstrap script for Linux/macOS
  • dotnet-tools.json: .NET tool configuration for Cake

Available Build Targets

# Build everything
dotnet cake --target=Build

# Run tests
dotnet cake --target=Test

# Create packages
dotnet cake --target=Pack

# Full CI pipeline (clean, build, test, pack)
dotnet cake --target=CI

# Publish packages to NuGet and npm
dotnet cake --target=Publish

Features

  • Add Operation: Adds two numbers
  • Subtract Operation: Subtracts two numbers
  • Multiply Operation: Multiplies two numbers
  • Divide Operation: Divides two numbers (includes division by zero validation)
  • Web Interface: User-friendly Angular web application
  • Real-time Validation: Input validation and error handling
  • Responsive Design: Works on desktop and mobile devices

Technical Details

  • Built with .NET 9.0
  • Uses gRPC for service communication over HTTP/2
  • gRPC-Web support for browser compatibility
  • Angular 17 frontend with TypeScript
  • Implements async/await pattern
  • Implements Dependency Injection (DI) principles
  • Includes comprehensive logging with Microsoft.Extensions.Logging
  • Follows IoC principles for better maintainability and testing
  • Includes proper error handling and logging
  • Certificate generation tools for secure communication
  • Follows C# and Angular best practices

Getting Started

Running with Docker (Recommended)

  1. Clone the repository:

    git clone https://github.com/pskumar81/CalculatorGrpc.git
  2. Build and run using Docker Compose:

    docker-compose up --build

The services will be available at:

Running Locally (Alternative)

  1. Clone the repository:

    git clone https://github.com/pskumar81/CalculatorGrpc.git
  2. Build the solution:

    dotnet build
  3. Run the server:

    cd Calculator.Server
    dotnet run
  4. Run the client (in a new terminal):

    cd Calculator.Client
    dotnet run

πŸ“¦ Using the Packages

Using the NuGet Packages

Calculator.Server Package

dotnet add package Calculator.Server
using Calculator.Server.Services;
using Microsoft.AspNetCore.Server.Kestrel.Core;

var builder = WebApplication.CreateBuilder(args);

// Add gRPC services
builder.Services.AddGrpc();
builder.Services.AddGrpcReflection();

// Configure Kestrel for HTTP/2
builder.Services.Configure<KestrelServerOptions>(options =>
{
    options.ListenAnyIP(5001, o => o.Protocols = HttpProtocols.Http2);
});

var app = builder.Build();

// Configure gRPC pipeline
app.MapGrpcService<CalculatorService>();
app.MapGrpcReflectionService();

app.Run();

Calculator.Client Package

dotnet add package Calculator.Client
using Calculator.Client.Services;
using Grpc.Net.Client;

var services = new ServiceCollection();
services.AddCalculatorClient("https://localhost:5001");

var serviceProvider = services.BuildServiceProvider();
var calculatorClient = serviceProvider.GetRequiredService<ICalculatorClientService>();

var result = await calculatorClient.AddAsync(5, 3);
Console.WriteLine($"5 + 3 = {result}");

Using the npm Package

@calculator/web Package

npm install @calculator/web
import { CalculatorService } from '@calculator/web';

export class AppComponent {
  constructor(private calculatorService: CalculatorService) {}
  
  async calculate(a: number, b: number, operation: string) {
    switch(operation) {
      case 'add':
        return await this.calculatorService.add(a, b);
      case 'subtract':
        return await this.calculatorService.subtract(a, b);
      // ... other operations
    }
  }
}

Add to your Angular module:

import { CalculatorModule } from '@calculator/web';

@NgModule({
  imports: [
    CalculatorModule.forRoot({
      serverUrl: 'https://localhost:5001'
    })
  ]
})
export class AppModule { }

Testing

Run the tests using:

dotnet test

Docker Support

The application is fully containerized with Docker support:

  • Multi-stage Docker builds for both client and server
  • Docker Compose for easy deployment and service orchestration
  • Configured for HTTP/2 communication
  • Includes certificate generation tools for secure communication

Certificate Generation

The project includes tools for generating certificates for secure communication:

  1. Navigate to the certs directory:

    cd certs
  2. Run the certificate generation script:

    ./generate-certs.ps1

This will generate:

  • CA certificate
  • Server certificate
  • Client certificate

These certificates can be used to enable mutual TLS (mTLS) for secure communication between the client and server.

  • Multi-stage builds for both client and server
  • Docker Compose for service orchestration
  • Environment Variables for configuration
  • Network Isolation between services
  • Optimized Images using .NET runtime base images

Docker Commands

Build and start the services:

docker-compose up --build

Stop the services:

docker-compose down

Error Handling

  • Division by zero throws a proper gRPC exception
  • All operations are logged for monitoring and debugging
  • Client handles server errors gracefully
  • Docker containerization ensures consistent environment

CI/CD Pipeline

This project includes a comprehensive GitHub Actions CI/CD pipeline with the following features:

πŸ”„ Automated Workflows

  • CI/CD Pipeline: Builds, tests, and deploys on every push to master
  • Pull Request Validation: Quick validation for PRs
  • Code Quality Analysis: CodeQL security scanning and SonarCloud analysis
  • Automated Releases: Version tagging and Docker image publishing
  • Dependency Updates: Automated dependency updates via Dependabot

🐳 Container Registry

Docker images are automatically built and published to GitHub Container Registry:

  • ghcr.io/pskumar81/calculator-docker-calculator-server
  • ghcr.io/pskumar81/calculator-docker-calculator-web
  • ghcr.io/pskumar81/calculator-docker-calculator-client

πŸ›‘οΈ Security & Quality

  • CodeQL security analysis for C# and JavaScript
  • Docker image vulnerability scanning with Trivy
  • Dockerfile linting with Hadolint
  • Automated dependency security updates

πŸ“‹ Workflow Status

All workflow statuses are displayed via badges at the top of this README. For detailed information, see .github/WORKFLOWS.md.

Contributing

  1. Fork the repository
  2. Create your feature branch
  3. Commit your changes
  4. Push to the branch
  5. Create a new Pull Request

About

No description, website, or topics provided.

Resources

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •