Skip to content

SinhaWiz/DEVoops---ByeEarth

Repository files navigation

DEVoops β€” ByeEarth 🍱

A resilient, fully-observable microservices platform for the IUT Cafeteria β€” built to survive the Ramadan rush that brought the old monolith down.

Disclosure: This project was built with the help of GitHub Copilot.


⚑ Quick Start

# 1. Bring up all 13 containers (builds images on first run)
docker compose up -d --build

# 2. Wait ~30 s for services to pass their health checks, then seed the DB
npm run seed

# 3. Open the student UI
open http://localhost:3000

Node 18+ required for the seed script (uses native fetch).
Everything else runs inside Docker β€” no local Node needed.


πŸ” Test Credentials

Role Username Password
Student student1 password123
Admin admin adminpassword

🌐 Service URLs

Service URL Notes
Student UI localhost:3000 Login β†’ order β†’ live tracker
Admin Dashboard localhost:3000/admin Health grid, chaos controls, latency alert
Identity Provider localhost:3001 JWT issuance + rate-limiting
Order Gateway localhost:3002 Fast-fail entry point
Stock Service localhost:3003 Postgres inventory (optimistic lock)
Kitchen Queue localhost:3004 RabbitMQ consumer + retry logic
Notification Hub localhost:3005 Socket.io real-time updates
Grafana localhost:3006 admin / admin β€” 12-panel dashboard
Prometheus localhost:9090 Metrics + alert rules
Alertmanager localhost:9093 Slack / email routing
RabbitMQ UI localhost:15672 guest / guest

πŸ—οΈ Architecture

Browser
  β”‚
  β”œβ”€ Next.js Frontend (3000)
  β”‚    β”œβ”€β”€ /api/identity-provider/*  ─► Identity Provider (3001)
  β”‚    β”œβ”€β”€ /api/order-gateway/*      ─► Order Gateway (3002)
  β”‚    β”œβ”€β”€ /api/stock-service/*      ─► Stock Service (3003)
  β”‚    β”œβ”€β”€ /api/kitchen-queue/*      ─► Kitchen Queue (3004)
  β”‚    └── Socket.io                 ─► Notification Hub (3005)
  β”‚
  └─ /admin  ─► Admin Dashboard (same Next.js app)

Order Gateway (3002)
  β”œβ”€β”€ Redis fast-fail check (stock:{id})
  β”œβ”€β”€ JWT auth verify β†’ Identity Provider
  └── Publish β†’ RabbitMQ [orders_queue]

Kitchen Queue (3004) ← RabbitMQ consumer
  β”œβ”€β”€ Immediate ACK (async processing)
  β”œβ”€β”€ POST /stock/reduce β†’ Stock Service (3003)
  β”‚     β”œβ”€β”€ Postgres optimistic lock (version field)
  β”‚     └── Redis cache sync
  β”œβ”€β”€ Retry: up to 3Γ— with exponential back-off (transient errors)
  └── Publish β†’ RabbitMQ [notifications_queue]

Notification Hub (3005) ← RabbitMQ consumer
  └── Socket.io emit β†’ connected browser

Prometheus (9090) ─► scrapes all 5 services every 15 s
Grafana (3006)    ─► pre-provisioned 12-panel dashboard
Alertmanager (9093) ─► GatewayHighLatency / ServiceDown / HighOrderFailureRate

πŸ”„ Real-Time Order Flow

Step Where Detail
1. Fast-Fail Order Gateway + Redis Stock 0 β†’ reject in <50 ms, no DB hit
2. Accept Order Gateway + RabbitMQ Enqueue, return 202 Accepted in <2 s
3. In Kitchen Kitchen Queue Immediate ACK, status notification emitted
4. Stock Verify Stock Service Atomic Postgres update with optimistic lock; on 409 kitchen retries up to 3Γ—
5. Notify Notification Hub β†’ Socket.io Browser tracker advances: Pending β†’ In Kitchen β†’ Stock Verified β†’ Ready / Rejected

πŸ§ͺ Testing

Run all unit + integration tests

# Test a single service
cd services/identity-provider && npm test

# Or run every service from the root
for svc in identity-provider order-gateway stock-service kitchen-queue notification-hub; do
  echo "β–Ά $svc" && (cd services/$svc && npm test)
done

Re-seed the database (reset quantities)

npm run seed

The seed script upserts 19 menu items (mains, sides, drinks, desserts) β€” safe to run as many times as you like.

Smoke-test the full order flow with curl

# 1. Login β€” get a JWT
TOKEN=$(curl -s -X POST http://localhost:3001/login \
  -H 'Content-Type: application/json' \
  -d '{"username":"student1","password":"password123"}' \
  | grep -o '"token":"[^"]*"' | cut -d'"' -f4)

echo "Token: $TOKEN"

# 2. Check stock
curl -s http://localhost:3003/stock | jq '.[] | {id, name, quantity}'

# 3. Place an order
curl -s -X POST http://localhost:3002/order \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"itemId":"burger","quantity":1,"orderId":"smoke-test-001"}'

# 4. Check latency stats on the gateway
curl -s http://localhost:3002/latency-stats | jq

Test rate-limiting (identity provider)

# 4th attempt within a minute β†’ 429
for i in 1 2 3 4; do
  echo "Attempt $i:"
  curl -s -o /dev/null -w "%{http_code}" -X POST http://localhost:3001/login \
    -H 'Content-Type: application/json' \
    -d '{"username":"student1","password":"wrongpass"}'
  echo
done

Trigger chaos mode

# Enable chaos on stock-service
curl -s -X POST http://localhost:3003/chaos \
  -H 'Content-Type: application/json' \
  -d '{"enable":true}'

# Place an order β€” kitchen-queue will retry then give up
curl -s -X POST http://localhost:3002/order \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"itemId":"ramen","quantity":1,"orderId":"chaos-test-001"}'

# Recover
curl -s -X POST http://localhost:3003/chaos \
  -H 'Content-Type: application/json' \
  -d '{"enable":false}'

πŸ“Š Observability

Grafana (pre-provisioned)

Open localhost:3006 (admin / admin) β€” the IUT Cafeteria dashboard loads automatically.

12 panels:

  • Orders accepted / rejected / processed / retried / failed / notifications pushed
  • Gateway request rate (req/s)
  • Gateway latency p50 / p95 / p99 with 1 s alert threshold
  • Login success / failed
  • Stock reductions / failures

Prometheus alert rules (monitoring/alerts.yml)

Alert Condition Severity
GatewayHighLatency 30 s rolling avg > 1 s for 30 s warning
ServiceDown up == 0 for 1 min critical
HighOrderFailureRate failed / accepted > 10 % over 5 min warning

Alertmanager (monitoring/alertmanager.yml)

Routes all alerts to Slack and email. Set these env vars before docker compose up to activate real delivery:

export SLACK_WEBHOOK_URL="https://hooks.slack.com/services/..."
export SMTP_FROM="alerts@yourdomain.com"
export SMTP_TO="oncall@yourdomain.com"
export SMTP_HOST="smtp.gmail.com"
export SMTP_PORT="587"
export SMTP_USERNAME="you@gmail.com"
export SMTP_PASSWORD="your-app-password"

Without these, the stack still boots β€” Alertmanager logs delivery errors but does not crash.


πŸ›‘οΈ Resilience Features

Feature Where Detail
JWT Auth Order Gateway All order routes protected; 401 on missing/invalid token
Rate Limiting Identity Provider 3 login attempts / min per Student ID
Redis Fast-Fail Order Gateway Instant 422 if Redis says stock = 0
Idempotency Keys Order Gateway + Redis order:processed:{orderId} with 24 h TTL prevents duplicate processing
Optimistic Locking Stock Service Sequelize version: true; concurrent updates get 409 Conflict
Async ACK Kitchen Queue RabbitMQ message ACK'd immediately; processing happens in background
Retry + Back-off Kitchen Queue Up to 3 retries on transient errors (5xx / 409); exponential delay (2 s, 4 s, 6 s); 422 = permanent failure, no retry
Chaos Mode All 5 services POST /chaos {"enable":true} makes a service return 503 β€” test fault handling live
Visual Latency Alert Admin Dashboard 30 s rolling ring buffer; banner turns red when avg > 1 s
Docker Healthchecks docker-compose.yml All 13 containers; depends_on: condition: service_healthy ensures correct startup order

πŸ“‚ Project Structure

.
β”œβ”€β”€ docker-compose.yml            # Full 13-container stack
β”œβ”€β”€ package.json                  # Root β€” exposes `npm run seed`
β”œβ”€β”€ scripts/
β”‚   └── seed.js                   # Seeds 19 menu items via REST
β”œβ”€β”€ monitoring/
β”‚   β”œβ”€β”€ prometheus.yml            # Scrape config + alert rules wiring
β”‚   β”œβ”€β”€ alerts.yml                # Prometheus alert rules (3 rules)
β”‚   β”œβ”€β”€ alertmanager.yml          # Slack + email routing
β”‚   └── grafana/
β”‚       β”œβ”€β”€ provisioning/         # Auto-loads datasource + dashboard
β”‚       └── dashboards/
β”‚           └── cafeteria.json    # 12-panel Grafana dashboard
β”œβ”€β”€ services/
β”‚   β”œβ”€β”€ frontend/                 # Next.js 16 (React 19, TypeScript, Tailwind)
β”‚   β”œβ”€β”€ identity-provider/        # JWT issuance, bcrypt, rate-limiting
β”‚   β”œβ”€β”€ order-gateway/            # Fast-fail, idempotency, RabbitMQ publish
β”‚   β”œβ”€β”€ stock-service/            # Postgres + Sequelize (optimistic lock) + Redis cache
β”‚   β”œβ”€β”€ kitchen-queue/            # RabbitMQ consumer, retry logic
β”‚   └── notification-hub/         # Socket.io real-time push
└── .github/
    └── workflows/
        β”œβ”€β”€ ci.yml                # Matrix build + lint (frontend) + test
        └── integration-test.yml  # Full docker compose stack smoke test

βš™οΈ CI/CD

GitHub Actions runs on every push to main:

Job Steps
ci.yml (matrix across 6 services) npm ci β†’ build β†’ ESLint (frontend only) β†’ Jest
integration-test.yml docker compose up β†’ wait for health β†’ run integration tests β†’ tear down

Build fails if any test fails or the frontend has ESLint errors.


πŸ—ƒοΈ Data Model

StockItem (PostgreSQL β€” stock-service)

Column Type Notes
id STRING (PK) e.g. "burger"
name STRING Display name
quantity INTEGER Validated >= 0
version INTEGER Optimistic lock counter
createdAt TIMESTAMP Sequelize auto
updatedAt TIMESTAMP Sequelize auto

Users (in-memory β€” identity-provider)

Hardcoded for dev. Passwords stored as bcrypt hashes (cost factor 10).


Generated for DevSprint 2026. Problem statement: problem_statement.txt.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors