Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,12 @@ simulation_output/
temp/
tmp/

# Local development files
local_db/
logs/
.env.local
commands.txt

# Coverage reports
coverage.xml
htmlcov/
Expand Down
126 changes: 122 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ area.**

- `docs/DEVELOPER_HANDBOOK.md` - Complete development guide
- `docs/DATABASE.md` - Database schema and patterns
- `docs/LOCAL_DEVELOPMENT.md` - Local development with console interface
- `tests/CLAUDE.md` - Testing framework guide

### For AI Agents (This File + Directory-Specific)
Expand Down Expand Up @@ -99,12 +100,126 @@ Always activate the virtual environment before running any Python commands:
source venv/bin/activate
```

### Code Quality Tools
## πŸ–₯️ Local Development Mode

This project uses **Ruff** for both linting and formatting, plus **Prettier**
for markdown/YAML files.
**For debugging monitoring issues and cost-effective testing without Cloud
Run.**

#### Quick Commands
### Quick Start

```bash
# 1. Download production database
source venv/bin/activate
python scripts/download_production_db.py

# 2. Start local development mode
python local_dev.py
```

### Local Development Features

- **Console Discord Interface**: Interact with bot commands via stdin/stdout
- **File Watcher Interface**: Send commands by appending to `commands.txt` file
- **Enhanced Logging**: All output to console + rotating log file
(`logs/bot.log`)
- **Production Database**: Real data from Cloud Run backups
- **Monitoring Loop**: Full monitoring functionality with API calls
- **Cost Savings**: Cloud Run scaled to 0 instances

### Console Commands

**Discord Bot Commands** (prefix with `!`):

- `!add location "Name"` - Add location monitoring
- `!list` - Show monitored targets
- `!check` - Manual check all targets
- `!help` - Show command help

**Console Special Commands** (prefix with `.`):

- `.quit` - Exit local development session
- `.health` - Show bot health status (Discord, DB, monitoring loop)
- `.status` - Show monitoring status (target counts, recent targets)
- `.trigger` - Force immediate monitoring loop iteration

### External Command Interface (File Watcher)

**Send commands from another terminal without restarting the bot:**

```bash
# Terminal 1: Keep bot running
python local_dev.py

# Terminal 2: Send commands
echo "!list" >> commands.txt
echo ".status" >> commands.txt
echo "!config poll_rate 15" >> commands.txt

# Terminal 3: Monitor responses
tail -f logs/bot.log
```

**Benefits:**

- **No interruption**: Bot keeps running while you send commands
- **External control**: Control from scripts, other terminals, or automation
- **Command history**: All commands saved in `commands.txt` file
- **Cross-platform**: Works on any system that supports file operations

### Log Monitoring

```bash
# Watch logs in real-time
tail -f logs/bot.log

# Search for monitoring activity
grep "MONITOR" logs/bot.log

# Check for errors
grep "ERROR" logs/bot.log
```

### Troubleshooting Local Dev

- **Console not responding**: Check for EOF/Ctrl+D in input
- **Database not found**: Run `python scripts/download_production_db.py`
- **Discord connection issues**: Verify `DISCORD_BOT_TOKEN` in `.env.local`
- **Missing environment**: Ensure `.env.local` exists with required variables

### Production Database Download

The production database is downloaded from Litestream backups:

```bash
python scripts/download_production_db.py
```

- Downloads latest backup from `dispinmap-bot-sqlite-backups` GCS bucket
- Restores to `local_db/pinball_bot.db`
- Verifies database integrity and shows table counts

## Code Quality Standards

**CRITICAL: We use Ruff exclusively for all Python code quality.**

### Our Tool Stack

- **Python**: `ruff` for ALL linting, formatting, type checking, and import
sorting
- **Markdown/YAML**: `prettier` for formatting
- **Tests**: `pytest` with coverage
- **Git**: `pre-commit` hooks

### Tools We Do NOT Use

We have standardized on Ruff and explicitly **do not use**:

- ❌ `mypy` (Ruff handles type checking)
- ❌ `black` (Ruff handles formatting)
- ❌ `flake8` (Ruff handles linting)
- ❌ `isort` (Ruff handles import sorting)

### Quick Commands

```bash
# Activate environment first
Expand All @@ -120,6 +235,9 @@ prettier --write "**/*.{md,yml,yaml}" --ignore-path .gitignore

# Run tests
pytest tests/ --ignore=tests/simulation -v

# Run ALL checks (comprehensive script)
./scripts/run_all_checks.sh
```

#### VS Code Tasks (Recommended)
Expand Down
214 changes: 214 additions & 0 deletions LOCAL_DEV_PLAN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
# Local Development and Testing Setup Plan

## Objectives

1. **Shut down GCP Cloud Run service** to stop burning money during debugging
2. **Create local development environment** with console-based Discord
interaction
3. **Download production database** for realistic testing
4. **Enhanced logging** to monitor long-term operation
5. **Debug monitoring loop issues** in controlled environment

## Implementation Steps

### Phase 1: Infrastructure Setup

#### 1.1 Shut Down Cloud Run Service

```bash
# Scale down to 0 instances to stop costs
gcloud run services update dispinmap-bot --region=us-central1 --min-instances=0 --max-instances=0
```

#### 1.2 Download Production Database

- Create script `scripts/download_production_db.py`
- Download latest backup from `dispinmap-bot-sqlite-backups` GCS bucket
- Use Litestream to restore to local file `local_db/pinball_bot.db`
- Verify database integrity and content

#### 1.3 Local Environment Configuration

- Create `.env.local` file with:
- `DISCORD_TOKEN` (from user's Discord bot)
- `DATABASE_PATH=local_db/pinball_bot.db`
- `LOCAL_DEV_MODE=true`
- `LOG_LEVEL=DEBUG`

### Phase 2: Console Discord Interface

#### 2.1 Create Console Discord Simulator

- New file: `src/console_discord.py`
- Implements a fake Discord channel that:
- Accepts commands via stdin (like `!add location "Ground Kontrol"`)
- Sends responses to stdout
- Simulates a single user and single channel
- Integrates with existing command handlers

#### 2.2 Local Development Entry Point

- New file: `src/local_dev.py`
- Entry point that:
- Loads local environment variables
- Starts both real Discord connection AND console interface
- Runs monitoring loop normally
- Provides graceful shutdown

#### 2.3 Console Interface Features

- **Command input**: `> !check` (user types commands)
- **Bot responses**: Immediate output to console
- **Background monitoring**: Shows monitoring loop activity
- **Status display**: Current targets, last check times, etc.
- **Manual triggers**: Force monitoring checks with special commands

### Phase 3: Enhanced Logging

#### 3.1 Single Log File with Rotation

- Use Python's `RotatingFileHandler`
- Single file: `logs/bot.log` (max 10MB, keep 5 files)
- All console output also goes to log file
- Timestamps and log levels for all entries

#### 3.2 Monitoring Loop Debugging

- Enhanced logging in `runner.py` to track:
- Every monitoring loop iteration
- Channel processing details
- API call results and timing
- Database operations
- Error conditions with full context

### Phase 4: Testing and Debugging

#### 4.1 Long-term Monitoring Test

- Run locally for 24+ hours
- Monitor log file for:
- Monitoring loop stability
- Memory usage patterns
- API rate limiting issues
- Database performance
- Error patterns

#### 4.2 Interactive Testing

- Test all commands through console interface
- Verify monitoring targets work correctly
- Test error conditions and recovery
- Validate notification logic

## File Structure

```
DisPinMap-Main/
β”œβ”€β”€ .env.local # Local environment config
β”œβ”€β”€ LOCAL_DEV_PLAN.md # This file
β”œβ”€β”€ logs/
β”‚ └── bot.log # Single rotating log file
β”œβ”€β”€ local_db/
β”‚ └── pinball_bot.db # Downloaded production database
β”œβ”€β”€ scripts/
β”‚ β”œβ”€β”€ download_production_db.py # Database download script
β”‚ └── local_setup.sh # Setup script
└── src/
β”œβ”€β”€ console_discord.py # Console Discord simulator
β”œβ”€β”€ local_dev.py # Local development entry point
└── log_config.py # Enhanced logging configuration
```

## Console Interface Design

### Input Format

```
> !add location "Ground Kontrol"
> !list
> !check
> !monitor_health
> .quit # Special command to exit
> .status # Show current monitoring status
> .trigger # Force immediate monitoring check
```

### Output Format

```
[2025-07-04 10:15:32] [CONSOLE] > !add location "Ground Kontrol"
[2025-07-04 10:15:33] [BOT] βœ… Successfully added location monitoring for "Ground Kontrol"
[2025-07-04 10:15:33] [BOT] πŸ“‹ **Last 5 submissions across all monitored targets:**
[2025-07-04 10:15:33] [MONITOR] πŸ”„ Monitor loop iteration #145 starting
[2025-07-04 10:15:34] [MONITOR] βœ… Channel 999999: Ready to poll (61.2 min >= 60 min)
```

## Implementation Order

1. **Shut down Cloud Run** (immediate cost savings)
2. **Create database download script** and get production data
3. **Set up basic local environment** with .env.local
4. **Create console Discord interface** for basic interaction
5. **Enhance logging system** for better monitoring
6. **Create local_dev.py entry point** that ties everything together
7. **Test and debug** monitoring loop issues
8. **Document findings** and prepare Cloud Run fixes

## Success Criteria

- [x] Cloud Run service scaled to 0 (costs stopped)
- [x] Local environment runs with production database
- [x] Console interface accepts and processes commands
- [x] Monitoring loop runs continuously without crashes
- [x] All activity logged to rotating log file
- [ ] Can run for 24+ hours without issues
- [x] Monitoring loop actually sends notifications when appropriate
- [ ] Ready to fix Cloud Run configuration based on local findings

## Implementation Status

βœ… **COMPLETED** - All core functionality is working!

### What's Working:

- Cloud Run scaled to 0 instances (costs stopped)
- Production database successfully downloaded and restored using Litestream
- Local environment with .env.local configuration
- Enhanced logging with rotation (logs/bot.log, 10MB max, 5 backups)
- Console Discord interface with stdin/stdout interaction
- Monitoring loop starts and makes successful API calls
- Bot connects to Discord and processes real channels

### Test Results:

- Bot starts up in ~3 seconds
- Monitoring loop begins immediately and polls PinballMap API
- Database queries work correctly (10 monitoring targets, 5 active channels)
- Graceful shutdown handling works
- All logs captured to both console and rotating file

### Next Steps:

1. Run extended testing (24+ hours) to identify stability issues
2. Test console commands interactively
3. Investigate Cloud Run health check configuration
4. Document findings for Cloud Run fixes

## Cloud Run Issue Investigation (Parallel)

While testing locally, also investigate:

- **Missing health check configuration** in terraform
- **Startup probe and liveness probe** settings
- **Container resource limits** and timeout values
- **Litestream backup path issue** (db vs db-v2)
- **Process startup timing** in startup.sh script

## Next Steps After Local Testing

1. **Fix identified issues** in Cloud Run configuration
2. **Add proper health checks** to terraform
3. **Test fixes locally** first
4. **Deploy improved version** to Cloud Run
5. **Monitor deployment** for stability
6. **Scale back up** once confirmed working
10 changes: 5 additions & 5 deletions alembic.ini
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,11 @@ sqlalchemy.url = sqlite:///test_migration.db
# on newly generated revision scripts. See the documentation for further
# detail and examples

# format using "black" - use the console_scripts runner, against the "black" entrypoint
# hooks = black
# black.type = console_scripts
# black.entrypoint = black
# black.options = -l 79 REVISION_SCRIPT_FILENAME
# format using "ruff" - use the console_scripts runner, against the "ruff" entrypoint
# hooks = ruff_format
# ruff_format.type = console_scripts
# ruff_format.entrypoint = ruff
# ruff_format.options = format REVISION_SCRIPT_FILENAME

# lint with attempts to fix using "ruff" - use the exec runner, execute a binary
# hooks = ruff
Expand Down
Loading