Skip to content

ramon-bernardo/RollingTransactionStats

Repository files navigation

Build Test Format Lint Release Typos .NET License: MIT

RollingTransactionStats

A REST API built with ASP.NET Core (.NET 10) that processes financial transactions and returns real-time statistics over a 60-second rolling window.


Overview

The API accepts transaction records and computes aggregate statistics (count, sum, average, min, max) considering only transactions from the last 60 seconds. All data is stored in-memory — no database required.


Tech Stack

Technology Version Role
.NET / ASP.NET Core 10.0 Runtime & Web API framework
MediatR 14.1.0 CQRS pipeline
AutoMapper 16.1.1 DTO → Command mapping
Autofac 9.1.0 IoC container
FluentValidation 12.1.1 Input validation
Swashbuckle (Swagger) 10.1.7 API documentation
xUnit 2.9.3 Unit testing
Moq 4.20.72 Test mocking

Architecture

The project follows Clean Architecture with Domain-Driven Design (DDD) and CQRS via MediatR, organized into four layers:

RollingTransactionStats/
├── Domain/            # Entities, Value Objects, Domain Exceptions
├── Application/       # Commands, Queries, Handlers, Validators, DTOs
├── Infrastructure/    # In-memory repository, IoC module
└── Api/               # Controllers, Exception Handlers (Middleware)

Patterns in use:

  • CQRS (Commands: create/delete; Queries: statistics)
  • Value Objects (Amount, Timestamp, TransactionId) with invariant enforcement
  • Repository Pattern (ITransactionRepository)
  • MediatR Pipeline Behaviors (validation runs before every command handler)
  • Three-tier Exception Handling (see Error Responses)

API Endpoints

Method Route Body Success
POST /transaction { "amount": decimal, "timestamp": ISO8601 } 201 Created
DELETE /transaction 204 No Content
GET /statistics 200 OK

POST /transaction

{
  "amount": 12.50,
  "timestamp": "2026-04-03T15:30:00Z"
}

Validation rules:

  • amount must be >= 0
  • timestamp cannot be in the future

DELETE /transaction

Deletes all transactions from memory. Returns no body.

GET /statistics

Returns aggregated statistics for all transactions within the last 60 seconds:

{
  "count": 3,
  "sum": 35.00,
  "avg": 11.67,
  "min": 5.00,
  "max": 18.50
}

If no transactions exist within the window, all values return 0.

Error Responses

All errors follow the RFC 7807 Problem Details format.

Status When
422 Unprocessable Entity Input validation fails (e.g. negative amount, future timestamp)
400 Bad Request Domain rule violation
500 Internal Server Error Unhandled exception

Getting Started

Prerequisites

Run

git clone https://github.com/ramon-bernardo/RollingTransactionStats.git
cd RollingTransactionStats

dotnet run

The API will be available at:

  • http://localhost:5182
  • https://localhost:7251

Swagger UI

Navigate to http://localhost:5182/swagger to explore and test the API interactively.

Postman

A ready-to-use collection is available at Postman/Collection.json. Import it into Postman to test all endpoints.


Running Tests

dotnet test Tests/RollingTransactionStats.Tests.csproj

Test coverage includes:

  • Domain — Value Object invariants (Amount, Timestamp, Transaction)
  • Application — Command handlers, query handler (rolling window logic), validators

Benchmarks

Benchmarks are implemented with BenchmarkDotNet and cover the two main hot paths:

Benchmark What it measures
TransactionRepositoryBenchmarks Add, GetSince (60s window), DeleteAll
StatisticsCalculationBenchmarks Full statistics calculation via GetStatisticsQueryHandler

Each benchmark runs with TransactionCount of 10, 100, and 1_000 to observe scaling behavior.

Must be run in Release mode — BenchmarkDotNet requires it.

dotnet run --project Benchmarks/RollingTransactionStats.Benchmarks.csproj -c Release

Results are saved to Benchmarks/BenchmarkDotNet.Artifacts/ after each run.


License

This project is licensed under the MIT License — see the LICENSE file for details.

About

A financial transaction statistics over a rolling window

Topics

Resources

License

Stars

Watchers

Forks

Contributors

Languages