Note: This project's purpose is for learning the Rust programming language.
A simple voting service REST API built with Rust, following clean architecture principles.
vote-svc is an HTTP service that manages election candidates. It demonstrates how to structure a Rust web service using layered architecture (delivery → usecase → repository → domain).
| Dependency | Purpose |
|---|---|
| actix-web | HTTP server framework |
| sqlx | Async PostgreSQL driver |
| tokio | Async runtime |
| serde | JSON serialization/deserialization |
| chrono | Date/time handling |
| uuid | UUID types |
| mockall | Mock generation for unit tests |
| config | Configuration management |
| dotenvy | .env file loading |
| anyhow | Flexible error handling |
| thiserror | Structured error types |
src/
├── main.rs # Entry point — wires up server, database, and handlers
├── lib.rs
├── app.rs # Application-level shared state (AppHandlerData)
├── config.rs
├── candidate/ # Candidate feature module
│ ├── domain/ # Core domain: entities, errors, repository trait
│ ├── usecase/ # Business logic (get candidates)
│ ├── repository/ # PostgreSQL repository implementation
│ └── delivery/http/ # HTTP handlers and route definitions
├── infrastructure/
│ ├── config/ # App configuration (loaded from environment)
│ ├── database/ # PostgreSQL connection pool management
│ └── http/ # HTTP server setup
└── utils/ # Shared response utilities
| Method | Path | Description |
|---|---|---|
GET |
/candidates |
List all candidates |
All endpoints return a unified JSON response envelope:
Success
{
"status": true,
"message": "Successfully processed candidate",
"error_code": "",
"data": { ... }
}Error
{
"status": false,
"message": "failed process data",
"error_code": "-1",
"data": null
}Configuration is loaded from environment variables. Copy .env.example to .env and fill in the values:
cp .env.example .env.env.example:
APP__ENV=production
APP__NAME=EVOTE-SERVICE
SERVER__ADDR=0.0.0.0
SERVER__PORT=8080
DATABASE__ADDR=localhost
DATABASE__PORT=5432
DATABASE__NAME=vote
DATABASE__USERNAME=your_username
DATABASE__PASSWORD=your_password
DATABASE__MAX_CONN=2
DATABASE__MIN_CONN=1Environment variables use double underscores (__) as a separator for nested config keys.
- Rust (edition 2024)
- PostgreSQL
# Copy and fill in environment config
cp .env.example .env
# Run the service
cargo runThe server will start on the address and port defined in your .env (default: 0.0.0.0:8080).
cargo testThe server listens for Ctrl+C and shuts down cleanly — stopping the HTTP server and closing the database connection pool before exiting.