# Lottery Backend

Spring Boot backend application for Lottery project.

## Technology Stack

- **Java 17**
- **Spring Boot 3.2.0**
- **MySQL 8.0** (using INT/BIGINT only, no floating point numbers)
- **Flyway** (database migrations)
- **Docker** (containerization)
- **Maven** (build tool)

## Local Development

### Prerequisites

- Java 17 JDK
- Maven 3.9+
- Docker and Docker Compose (for local MySQL)

### Setup

1. **Clone the repository**

2. **Start MySQL using Docker Compose**:
   ```bash
   docker-compose up -d db
   ```

3. **Create `.env` file** (for local development):
   ```env
   DB_NAME=lottery_db
   DB_USERNAME=root
   DB_PASSWORD=password
   DB_ROOT_PASSWORD=password
   TELEGRAM_BOT_TOKEN=your_telegram_bot_token_here
   FRONTEND_URL=http://localhost:5173
   ```

4. **Run the application**:
   ```bash
   mvn spring-boot:run
   ```

   Or build and run with Docker:
   ```bash
   docker-compose up --build
   ```

### Database Migrations

Flyway automatically runs migrations on startup. Migrations are located in `src/main/resources/db/migration/`.

## Deployment Guides

### Railway Deployment (Staging Environment)

Railway is the primary deployment platform for staging. It provides built-in logging and easy environment variable management.

#### Step 1: Create Railway Project

1. Go to [Railway](https://railway.app) and sign in
2. Click **"New Project"**
3. Select **"Empty Project"**

#### Step 2: Create MySQL Database Service

1. In your Railway project, click **"+ New"** → **"Database"** → **"Add MySQL"**
2. Railway will automatically create a MySQL database
3. Note the connection details (you'll need them for the backend service)

#### Step 3: Create Backend Service

1. In your Railway project, click **"+ New"** → **"GitHub Repo"** (or **"Empty Service"**)
2. If using GitHub:
   - Connect your GitHub account
   - Select the `honey-be` repository
   - Railway will automatically detect it's a Java/Maven project
3. If using Empty Service:
   - Click **"Empty Service"**
   - Connect to your repository or upload files

#### Step 4: Configure Environment Variables

In your backend service settings, go to **"Variables"** and add:

```env
SPRING_DATASOURCE_URL=${MYSQL_URL}
SPRING_DATASOURCE_USERNAME=${MYSQLUSER}
SPRING_DATASOURCE_PASSWORD=${MYSQLPASSWORD}
TELEGRAM_BOT_TOKEN=your_telegram_bot_token
FRONTEND_URL=https://your-frontend-url.railway.app
PORT=8080
```

**Note**: Railway automatically provides `MYSQL_URL`, `MYSQLUSER`, and `MYSQLPASSWORD` when you add a MySQL database. You can reference them using `${MYSQL_URL}` syntax.

#### Step 5: Link Database to Backend

1. In your backend service, go to **"Settings"** → **"Connect"**
2. Find your MySQL database service
3. Click **"Connect"** - Railway will automatically add the MySQL connection variables

#### Step 6: Configure Health Check

1. In your backend service, go to **"Settings"** → **"Healthcheck"**
2. Set **Healthcheck Path** to:
   ```
   /actuator/health/readiness
   ```
3. Railway will poll this endpoint and wait for HTTP 200 before marking deployment as active

#### Step 7: Deploy

1. Railway will automatically deploy when you push to the connected branch
2. Or manually trigger deployment from the Railway dashboard
3. Check the **"Deployments"** tab to monitor the deployment

#### Step 8: Get Backend URL

1. In your backend service, go to **"Settings"** → **"Networking"**
2. Click **"Generate Domain"** to get a public URL
3. Or use the default Railway domain
4. Copy the URL (e.g., `https://lottery-be-production.up.railway.app`)

#### Step 9: Create Frontend Service (Optional - if deploying frontend to Railway)

1. In your Railway project, click **"+ New"** → **"GitHub Repo"**
2. Select your `lottery-fe` repository
3. Railway will detect it's a Node.js project
4. Add environment variable:
   ```env
   VITE_API_BASE_URL=https://your-backend-url.railway.app
   ```
5. Railway will automatically build and deploy

#### Step 10: Create Volume (Optional - for persistent data)

If you need persistent storage:

1. In your Railway project, click **"+ New"** → **"Volume"**
2. Name it (e.g., `lottery-data`)
3. Mount it to your service if needed

### Inferno Deployment (Production Environment)

Inferno Solution provides the production environment. It requires manual server setup and uses Docker Compose with nginx.

#### Prerequisites

- Access to Inferno Solution server (via SSH)
- Docker and Docker Compose installed on the server
- JDK 17 installed on the server (for building, though Docker handles runtime)
- Domain name configured (optional, for HTTPS)

#### Step 1: Prepare Server

1. **SSH into your Inferno server**:
   ```bash
   ssh user@your-server-ip
   ```

2. **Install Docker** (if not installed):
   ```bash
   # For Ubuntu/Debian
   curl -fsSL https://get.docker.com -o get-docker.sh
   sh get-docker.sh
   sudo usermod -aG docker $USER
   ```

3. **Install Docker Compose** (if not installed):
   ```bash
   sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
   sudo chmod +x /usr/local/bin/docker-compose
   ```

4. **Install JDK 17** (for building):
   ```bash
   # For Ubuntu/Debian
   sudo apt update
   sudo apt install openjdk-17-jdk -y
   ```

5. **Create project directory**:
   ```bash
   mkdir -p /opt/lottery
   cd /opt/lottery
   ```

#### Step 2: Clone Repository

```bash
cd /opt/lottery
git clone https://github.com/your-username/lottery-be.git
cd lottery-be
```

#### Step 3: Create Secret Configuration File

Create a tmpfs mount for secrets (more secure than .env files):

```bash
# Create tmpfs mount point
sudo mkdir -p /run/secrets
sudo chmod 700 /run/secrets

# Create secret file
sudo nano /run/secrets/lottery-config.properties
```

Add the following content (replace with your actual values):

```properties
SPRING_DATASOURCE_URL=jdbc:mysql://db:3306/lottery_db
SPRING_DATASOURCE_USERNAME=lottery_user
SPRING_DATASOURCE_PASSWORD=your_secure_mysql_password
TELEGRAM_BOT_TOKEN=your_telegram_bot_token
FRONTEND_URL=https://your-frontend-domain.com
MYSQL_PASSWORD=your_secure_mysql_password
MYSQL_ROOT_PASSWORD=your_secure_mysql_root_password
```

**Important**: 
- Use strong, unique passwords
- Keep this file secure (it's in tmpfs, so it's in-memory only)
- The file will be lost on reboot - you'll need to recreate it or use a startup script

#### Step 4: Configure Docker Compose for Inferno

The `docker-compose.inferno.yml` file is already configured. Make sure it's present in your repository.

#### Step 5: Build and Start Services

```bash
cd /opt/lottery/lottery-be

# Build and start all services
docker-compose -f docker-compose.inferno.yml up -d --build
```

This will:
- Build the backend application
- Start MySQL database
- Start backend service
- Start nginx reverse proxy

#### Step 6: Configure Nginx (if using custom domain)

1. **Edit nginx configuration**:
   ```bash
   nano nginx/conf.d/lottery.conf
   ```

2. **Update server_name** (if using HTTPS):
   ```nginx
   server {
       listen 80;
       server_name your-domain.com;
       # ... rest of config
   }
   ```

3. **Reload nginx**:
   ```bash
   docker-compose -f docker-compose.inferno.yml restart nginx
   ```

#### Step 7: Set Up SSL (Optional - Recommended for Production)

1. **Install Certbot** (Let's Encrypt):
   ```bash
   sudo apt install certbot python3-certbot-nginx -y
   ```

2. **Obtain SSL certificate**:
   ```bash
   sudo certbot --nginx -d your-domain.com
   ```

3. **Update nginx config** to use HTTPS (uncomment HTTPS server block in `nginx/conf.d/lottery.conf`)

4. **Reload nginx**:
   ```bash
   docker-compose -f docker-compose.inferno.yml restart nginx
   ```

#### Step 8: Configure Firewall

```bash
# Allow HTTP and HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# Allow SSH (if not already allowed)
sudo ufw allow 22/tcp

# Enable firewall
sudo ufw enable
```

#### Step 9: Set Up Auto-Start on Boot

Create a systemd service to ensure services start on boot:

```bash
sudo nano /etc/systemd/system/lottery.service
```

Add:

```ini
[Unit]
Description=Lottery Application
Requires=docker.service
After=docker.service

[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/lottery/lottery-be
ExecStart=/usr/local/bin/docker-compose -f docker-compose.inferno.yml up -d
ExecStop=/usr/local/bin/docker-compose -f docker-compose.inferno.yml down
TimeoutStartSec=0

[Install]
WantedBy=multi-user.target
```

Enable the service:

```bash
sudo systemctl daemon-reload
sudo systemctl enable lottery.service
sudo systemctl start lottery.service
```

#### Step 10: Set Up Grafana Integration (Production Logging)

1. **Install Grafana and Loki** (on a separate server or same server):
   ```bash
   # Follow Grafana/Loki installation guide
   # https://grafana.com/docs/loki/latest/installation/
   ```

2. **Configure Promtail** to collect logs from Docker containers:
   ```yaml
   # promtail-config.yml
   server:
     http_listen_port: 9080
     grpc_listen_port: 0

   positions:
     filename: /tmp/positions.yaml

   clients:
     - url: http://loki:3100/loki/api/v1/push

   scrape_configs:
     - job_name: lottery-backend
       docker_sd_configs:
         - host: unix:///var/run/docker.sock
           refresh_interval: 5s
       relabel_configs:
         - source_labels: [__meta_docker_container_name]
           regex: lottery-backend
           action: keep
   ```

3. **Update docker-compose.inferno.yml** to add logging driver:
   ```yaml
   app:
     # ... existing config
     logging:
       driver: "json-file"
       options:
         max-size: "10m"
         max-file: "3"
   ```

4. **Configure Grafana datasource** to connect to Loki

#### Step 11: Monitor and Maintain

**Check service status**:
```bash
docker-compose -f docker-compose.inferno.yml ps
```

**View logs**:
```bash
# All services
docker-compose -f docker-compose.inferno.yml logs -f

# Specific service
docker-compose -f docker-compose.inferno.yml logs -f app
```

**Update application**:
```bash
cd /opt/lottery/lottery-be
git pull
docker-compose -f docker-compose.inferno.yml up -d --build
```

**Backup database**:
```bash
docker-compose -f docker-compose.inferno.yml exec db mysqldump -u lottery_user -p lottery_db > backup_$(date +%Y%m%d).sql
```

## Configuration

### Environment Variables

The application supports two configuration strategies:

1. **Environment Variables** (Railway): Set variables in Railway dashboard
2. **Secret File** (Inferno): Mount file at `/run/secrets/lottery-config.properties`

Priority: Secret file → Environment variables

### Required Variables

- `SPRING_DATASOURCE_URL` - MySQL connection URL
- `SPRING_DATASOURCE_USERNAME` - MySQL username
- `SPRING_DATASOURCE_PASSWORD` - MySQL password
- `TELEGRAM_BOT_TOKEN` - Telegram bot token for authentication
- `FRONTEND_URL` - Frontend URL for CORS configuration

### Database Schema

The database uses **INT** and **BIGINT** only - no floating point numbers.

Current tables:
- `users` - User information (id, telegram_id, username, created_at)

## API Endpoints

### Public Endpoints

- `GET /ping` - Health check (no auth required)
- `GET /actuator/health` - Application health
- `GET /actuator/health/readiness` - Readiness probe (checks database)
- `GET /actuator/health/liveness` - Liveness probe

### Protected Endpoints (require Telegram auth)

- `GET /api/users/current` - Get current user information

## Authorization

The application uses Telegram Mini App authentication:

1. Frontend sends `Authorization: tma <initData>` header
2. Backend validates Telegram signature
3. Backend creates/updates user in database
4. User is stored in thread-local context for the request

## Health Checks

- **Readiness**: `/actuator/health/readiness` - Checks database connectivity
- **Liveness**: `/actuator/health/liveness` - Checks if application is running

Configure Railway to use `/actuator/health/readiness` as the health check path.

## Logging

- **Railway**: Built-in logging available in Railway dashboard
- **Inferno**: Configure Grafana/Loki for log aggregation (see Grafana setup above)

## Troubleshooting

### Database Connection Issues

- Verify MySQL is running: `docker-compose ps`
- Check connection credentials in environment variables
- Review application logs for connection errors

### Authorization Failures

- Verify `TELEGRAM_BOT_TOKEN` is correct
- Check that frontend is sending `Authorization: tma <initData>` header
- Review backend logs for validation errors

### Deployment Issues

- Check health check endpoint: `curl http://your-url/actuator/health/readiness`
- Review Railway deployment logs
- Verify all environment variables are set correctly

## Development

### Running Tests

```bash
mvn test
```

### Building JAR

```bash
mvn clean package
```

### Running Locally with Docker

```bash
docker-compose up --build
```

## Project Structure

```
lottery-be/
├── src/
│   ├── main/
│   │   ├── java/com/lottery/lottery/
│   │   │   ├── config/          # Configuration classes
│   │   │   ├── controller/      # REST controllers
│   │   │   ├── dto/             # Data transfer objects
│   │   │   ├── exception/       # Exception handlers
│   │   │   ├── health/          # Health indicators
│   │   │   ├── logging/         # Grafana logging config
│   │   │   ├── model/           # JPA entities
│   │   │   ├── repository/      # JPA repositories
│   │   │   ├── security/        # Auth interceptor, UserContext
│   │   │   └── service/         # Business logic
│   │   └── resources/
│   │       ├── db/migration/    # Flyway migrations
│   │       └── application.yml # Application config
├── nginx/                        # Nginx config (for Inferno)
├── Dockerfile                    # Dockerfile for Railway
├── Dockerfile.inferno            # Dockerfile for Inferno
├── docker-compose.yml            # Docker Compose for local/Railway
├── docker-compose.inferno.yml    # Docker Compose for Inferno
└── pom.xml                       # Maven configuration
```

## License

[Your License Here]


