init commit

This commit is contained in:
2026-01-26 15:08:24 -06:00
commit 67225a725a
33 changed files with 3350 additions and 0 deletions

View File

@@ -0,0 +1,164 @@
# Weather Alerts - Implementation Roadmap
## Overview
This document captures the implementation plan and decisions for the weather alerts application.
## Architecture
### Directory Structure
```
weather_alerts/
├── app/
│ ├── __init__.py
│ ├── main.py # Entry point - orchestration
│ ├── config/
│ │ ├── __init__.py
│ │ ├── loader.py # Typed YAML config loader
│ │ ├── settings.yaml # Main configuration
│ │ └── settings.example.yaml # Example (no secrets)
│ ├── models/
│ │ ├── __init__.py
│ │ ├── weather.py # Weather data models
│ │ ├── alerts.py # Alert rule/triggered alert models
│ │ └── state.py # Deduplication state models
│ ├── services/
│ │ ├── __init__.py
│ │ ├── weather_service.py # VisualCrossing API client
│ │ ├── notification_service.py # ntfy sender
│ │ ├── rule_engine.py # Alert rule evaluation
│ │ └── state_manager.py # Deduplication persistence
│ └── utils/
│ ├── __init__.py
│ ├── http_client.py # Centralized HTTP wrapper
│ └── logging_config.py # Structlog setup
├── tests/
├── data/ # State files (gitignored)
├── .env.example
├── .gitignore
├── requirements.txt
└── run.py # Simple runner
```
## Key Design Decisions
### 1. One-Shot Execution
The application is designed for cron-based scheduling rather than internal scheduling. Each run:
1. Fetches current forecast
2. Evaluates rules
3. Sends new alerts
4. Exits
### 2. Secrets Management
- API keys and tokens stored in environment variables only
- `.env` file for local development (gitignored)
- No secrets in YAML configuration
### 3. Atomic State Persistence
State file writes use write-to-temp-then-rename pattern for crash safety:
```python
fd, temp_path = tempfile.mkstemp(...)
# Write to temp file
os.replace(temp_path, actual_path) # Atomic rename
```
### 4. Deduplication Strategy
Alerts are deduplicated using the key format: `{alert_type}:{forecast_hour}`
This allows:
- Re-alerting for different forecast hours
- Preventing duplicate alerts for the same condition/hour
- Configurable deduplication window (default 24 hours)
### 5. Typed Throughout
- Dataclasses for all data models
- Type hints on all functions
- Configuration loaded into typed dataclasses
### 6. Centralized HTTP
Single `HttpClient` wrapper provides:
- Consistent timeouts
- Automatic retries with exponential backoff
- Structured logging
- Shared across services
## Alert Rules
### Temperature
- **Low temperature**: Alert when forecast drops below threshold (default: 32°F)
- **High temperature**: Alert when forecast exceeds threshold (default: 100°F)
### Precipitation
- Alert when precipitation probability exceeds threshold (default: 70%)
### Wind
- **Sustained wind**: Alert when speed exceeds threshold (default: 25 mph)
- **Wind gusts**: Alert when gusts exceed threshold (default: 40 mph)
### Severe Weather
- Forwards any severe weather alerts from the VisualCrossing API
## Execution Flow
```
1. Load configuration (YAML + environment)
2. Configure logging (structlog)
3. Initialize services
4. Fetch weather forecast
5. Evaluate alert rules
6. Filter duplicate alerts
7. Send new alerts via ntfy
8. Record sent alerts
9. Purge old records
10. Save state
11. Exit (0=success, 1=error)
```
## Dependencies
| Package | Purpose |
|---------|---------|
| requests | HTTP client |
| structlog | Structured logging |
| python-dotenv | Environment variable loading |
| PyYAML | Configuration parsing |
| pytest | Testing |
| responses | HTTP mocking for tests |
## Testing
Run tests with:
```bash
pytest tests/ -v
```
Test coverage:
- Rule engine: Temperature, precipitation, wind, severe weather rules
- Weather service: API parsing, error handling
- State manager: Persistence, deduplication, purging
## Usage
### Setup
1. Copy `.env.example` to `.env` and fill in API keys
2. Copy `app/config/settings.example.yaml` to `app/config/settings.yaml` (optional customization)
3. Install dependencies: `pip install -r requirements.txt`
### Running
```bash
python run.py
```
### Cron Integration
Add to crontab for hourly checks:
```cron
0 * * * * cd /path/to/weather_alerts && /path/to/python run.py >> /var/log/weather-alerts.log 2>&1
```
## Future Enhancements
Potential additions if needed:
- Additional alert types (UV index, humidity, etc.)
- Multiple location support
- Alert cooldown periods
- Notification channels beyond ntfy
- Web dashboard for status