A fully working multiplayer Tic-Tac-Toe game with microservices architecture, using React frontend, Python backend services, Kafka for event streaming, and MongoDB for data persistence.
- Frontend: React application (WebSocket client)
- Gateway Service: WebSocket server that forwards moves to Kafka and broadcasts state updates
- Game Logic Service: Authoritative game logic, consumes moves from Kafka, publishes state updates
- Archive Service: Consumes game state updates, stores win records in MongoDB
- Statistics Service: REST API to query win statistics from MongoDB
- Kafka: Event bus for service-to-service communication
- MongoDB: Database for storing win records
| Service | URL/Port | Description |
|---|---|---|
| Frontend | http://localhost:3000 | React web application |
| Gateway Service | ws://localhost:9000 | WebSocket server |
| Statistics Service | http://localhost:8000 | REST API |
| Statistics Swagger UI | http://localhost:8000/docs | Interactive API documentation |
| Kafka | localhost:9092 | Kafka broker |
| MongoDB | localhost:27017 | MongoDB database |
- Python 3.10+
- Node.js and npm
- Kafka (running on localhost:9092)
- MongoDB (running on localhost:27017)
Source the environment variables file:
cd /home/ronbut/games/tic-tac-toe
source infra/env-exports.shOr manually set the required variables:
export KAFKA_BOOTSTRAP_SERVERS=localhost:9092
export MONGO_URL=mongodb://localhost:27017
export MONGO_DB_NAME=admin
export GATEWAY_PORT=9000
export STATISTICS_PORT=8000Ensure Kafka is running on localhost:9092. If using Docker:
# Check if Kafka is running
docker ps | grep kafka
# Or start Kafka using docker-compose (if available)
cd infra
docker-compose up -d kafkaEnsure MongoDB is running on localhost:27017. If using Docker:
# Check if MongoDB is running
docker ps | grep mongo
# Or start MongoDB
docker run -d -p 27017:27017 --name mongodb mongo:latestThe Game Logic Service is the core service that processes game moves and maintains authoritative game state.
cd game-logic-service
# Create virtual environment (first time only)
python3 -m venv venv
source venv/bin/activate
# Install dependencies (first time only)
pip install -r requirements.txt
# Run the service
python -m serviceExpected output:
INFO:__main__:Game Logic Service started
INFO:__main__:Game Logic Service consuming moves from topic game-moves
The Gateway Service handles WebSocket connections from clients and forwards messages to/from Kafka.
cd gateway-service
# Create virtual environment (first time only)
python3 -m venv venv
source venv/bin/activate
# Install dependencies (first time only)
pip install -r requirements.txt
# Run the service
python -m appExpected output:
INFO:__main__:Gateway WebSocket server listening on 0.0.0.0:9000
The Archive Service consumes game state updates and stores win records in MongoDB.
cd archive-service
# Create virtual environment (first time only)
python3 -m venv venv
source venv/bin/activate
# Install dependencies (first time only)
pip install -r requirements.txt
# Run the service
python -m serviceExpected output:
INFO:__main__:Archive Service consuming state updates from topic game-state-updates
INFO:__main__:Archive Service started, connected to MongoDB database: admin
The Statistics Service provides a REST API to query win statistics.
cd statistics-service
# Create virtual environment (first time only)
python3 -m venv venv
source venv/bin/activate
# Install dependencies (first time only)
pip install -r requirements.txt
# Run the service
python -m serviceExpected output:
INFO:__main__:Statistics Service started successfully
INFO: Started server process
INFO: Uvicorn running on http://0.0.0.0:8000
The React frontend application.
cd frontend
# Install dependencies (first time only)
npm install
# Start the development server
npm startExpected output:
webpack compiled successfully
The frontend will be available at http://localhost:3000
For a complete setup, start services in this order:
- Kafka (if not already running)
- MongoDB (if not already running)
- Game Logic Service (required)
- Gateway Service (required)
- Archive Service (optional - for win tracking)
- Statistics Service (optional - for statistics API)
- Frontend (required for playing)
- Open http://localhost:3000 in your browser
- Enter a Player ID (e.g., "player1")
- Enter a Game ID (e.g., "game-1")
- Open another browser window/tab
- Enter a different Player ID (e.g., "player2") and the same Game ID
- Start playing!
# Get win statistics
curl http://localhost:8000/statistic
# Expected response:
# {
# "totalWins": 5,
# "players": [
# {"playerId": "ron", "wins": 3},
# {"playerId": "shimi", "wins": 2}
# ]
# }- Open http://localhost:8000/docs in your browser
- Explore available endpoints
- Test the
/statisticendpoint directly from the browser
# Connect to MongoDB
mongosh mongodb://localhost:27017
# Switch to database
use admin
# Query wins collection
db.wins.find().pretty()
# Count wins per player
db.wins.aggregate([
{ $group: { _id: "$playerId", wins: { $sum: 1 } } },
{ $sort: { wins: -1 } }
])Frontend
└─> Gateway Service (WebSocket)
└─> Kafka
└─> Game Logic Service
└─> Kafka (state updates)
└─> Gateway Service (broadcast to clients)
└─> Archive Service (store wins)
└─> MongoDB
└─> Statistics Service (read stats)
All services support environment variables. See infra/env-exports.sh for all available variables.
KAFKA_BOOTSTRAP_SERVERS: Kafka broker address (default:localhost:9092)MONGO_URL: MongoDB connection URL (default:mongodb://localhost:27017)MONGO_DB_NAME: MongoDB database name (default:admin)MONGO_USE_AUTH: Enable MongoDB authentication (default:false)
Game Logic Service:
KAFKA_MOVES_TOPIC: Topic for game moves (default:game-moves)KAFKA_STATE_TOPIC: Topic for state updates (default:game-state-updates)KAFKA_CONSUMER_GROUP: Consumer group ID (default:game-logic-service)
Gateway Service:
GATEWAY_HOST: WebSocket server host (default:0.0.0.0)GATEWAY_PORT: WebSocket server port (default:9000)
Statistics Service:
STATISTICS_HOST: API server host (default:0.0.0.0)STATISTICS_PORT: API server port (default:8000)
- Change
GATEWAY_PORTto a different port (e.g.,9001) - Or stop the process using port 9000:
lsof -ti:9000 | xargs kill
- Verify Kafka is running:
docker ps | grep kafka - Check Kafka logs:
docker logs <kafka-container-id> - Verify
KAFKA_BOOTSTRAP_SERVERSenvironment variable
- Verify MongoDB is running:
docker ps | grep mongo - Test connection:
mongosh mongodb://localhost:27017 - Check
MONGO_URLenvironment variable
- Verify Gateway Service is running on port 9000
- Check browser console for WebSocket connection errors
- Verify
GATEWAY_PORTmatches frontend WebSocket URL
# Game Logic Service tests
cd game-logic-service
source venv/bin/activate
python -m pytest test_game.pytic-tac-toe/
├── frontend/ # React frontend
├── gateway-service/ # WebSocket gateway
├── game-logic-service/ # Core game logic
├── archive-service/ # Win record archiving
├── statistics-service/ # Statistics API
├── infra/ # Infrastructure configs
│ └── env-exports.sh # Environment variables
└── k8s/ # Kubernetes manifests
This project is part of a microservices architecture demonstration.