Improve the frontend 6
This commit is contained in:
363
docs/CALENDAR_DEPLOYMENT_GUIDE.md
Normal file
363
docs/CALENDAR_DEPLOYMENT_GUIDE.md
Normal file
@@ -0,0 +1,363 @@
|
||||
# Hyperlocal School Calendar - Deployment Guide
|
||||
|
||||
## 🎯 Overview
|
||||
|
||||
This guide provides step-by-step instructions to deploy the hyperlocal school calendar feature for Prophet forecasting enhancement.
|
||||
|
||||
---
|
||||
|
||||
## ✅ Prerequisites
|
||||
|
||||
- External service database access
|
||||
- Redis instance running
|
||||
- Access to deploy to external, training, and forecasting services
|
||||
|
||||
---
|
||||
|
||||
## 📦 Deployment Steps
|
||||
|
||||
### Step 1: Run Database Migration
|
||||
|
||||
```bash
|
||||
cd services/external
|
||||
python -m alembic upgrade head
|
||||
```
|
||||
|
||||
**Expected Output:**
|
||||
```
|
||||
INFO [alembic.runtime.migration] Running upgrade b97bab14ac47 -> 693e0d98eaf9, add_school_calendars_and_location_context
|
||||
```
|
||||
|
||||
**Verify Tables Created:**
|
||||
```sql
|
||||
-- Connect to external service database
|
||||
SELECT table_name FROM information_schema.tables
|
||||
WHERE table_schema = 'public'
|
||||
AND table_name IN ('school_calendars', 'tenant_location_contexts');
|
||||
```
|
||||
|
||||
### Step 2: Seed Calendar Data
|
||||
|
||||
```bash
|
||||
cd services/external
|
||||
python scripts/seed_school_calendars.py
|
||||
```
|
||||
|
||||
**Expected Output:**
|
||||
```
|
||||
INFO Starting school calendar seeding...
|
||||
INFO Found 2 calendars in registry
|
||||
INFO Processing calendar calendar_id=madrid_primary_2024_2025 city=madrid type=primary
|
||||
INFO Calendar seeded successfully calendar_id=<uuid> city=madrid type=primary
|
||||
INFO Processing calendar calendar_id=madrid_secondary_2024_2025 city=madrid type=secondary
|
||||
INFO Calendar seeded successfully calendar_id=<uuid> city=madrid type=secondary
|
||||
INFO Calendar seeding completed seeded=2 skipped=0 total=2
|
||||
```
|
||||
|
||||
**Verify Calendars Loaded:**
|
||||
```sql
|
||||
SELECT calendar_name, city_id, school_type, academic_year
|
||||
FROM school_calendars;
|
||||
```
|
||||
|
||||
Expected: 2 rows (Madrid Primary and Secondary 2024-2025)
|
||||
|
||||
### Step 3: Restart External Service
|
||||
|
||||
```bash
|
||||
# Via Tilt or kubectl
|
||||
kubectl rollout restart deployment external-service -n bakery-ia
|
||||
kubectl wait --for=condition=ready pod -l app=external-service -n bakery-ia --timeout=60s
|
||||
```
|
||||
|
||||
**Verify Service Health:**
|
||||
```bash
|
||||
curl -k https://localhost/api/v1/external/health
|
||||
```
|
||||
|
||||
### Step 4: Test Calendar API
|
||||
|
||||
**List Calendars for Madrid:**
|
||||
```bash
|
||||
curl -k -H "X-Tenant-ID: <tenant-id>" \
|
||||
https://localhost/api/v1/external/operations/cities/madrid/school-calendars
|
||||
```
|
||||
|
||||
**Expected Response:**
|
||||
```json
|
||||
{
|
||||
"city_id": "madrid",
|
||||
"calendars": [
|
||||
{
|
||||
"calendar_id": "<uuid>",
|
||||
"calendar_name": "Madrid Primary School Calendar 2024-2025",
|
||||
"city_id": "madrid",
|
||||
"school_type": "primary",
|
||||
"academic_year": "2024-2025",
|
||||
"holiday_periods": [...],
|
||||
"school_hours": {...},
|
||||
"enabled": true
|
||||
},
|
||||
...
|
||||
],
|
||||
"total": 2
|
||||
}
|
||||
```
|
||||
|
||||
### Step 5: Assign Calendar to Test Tenant
|
||||
|
||||
```bash
|
||||
# Get a calendar ID from previous step
|
||||
CALENDAR_ID="<uuid-from-previous-step>"
|
||||
TENANT_ID="<your-test-tenant-id>"
|
||||
|
||||
curl -k -X POST \
|
||||
-H "X-Tenant-ID: $TENANT_ID" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"city_id": "madrid",
|
||||
"school_calendar_id": "'$CALENDAR_ID'",
|
||||
"neighborhood": "Chamberí",
|
||||
"notes": "Test bakery near primary school"
|
||||
}' \
|
||||
https://localhost/api/v1/external/tenants/$TENANT_ID/location-context
|
||||
```
|
||||
|
||||
**Verify Assignment:**
|
||||
```bash
|
||||
curl -k -H "X-Tenant-ID: $TENANT_ID" \
|
||||
https://localhost/api/v1/external/tenants/$TENANT_ID/location-context
|
||||
```
|
||||
|
||||
### Step 6: Test Holiday Check
|
||||
|
||||
```bash
|
||||
# Check if Christmas is a holiday
|
||||
curl -k -H "X-Tenant-ID: $TENANT_ID" \
|
||||
"https://localhost/api/v1/external/operations/school-calendars/$CALENDAR_ID/is-holiday?check_date=2024-12-25"
|
||||
```
|
||||
|
||||
**Expected Response:**
|
||||
```json
|
||||
{
|
||||
"date": "2024-12-25",
|
||||
"is_holiday": true,
|
||||
"holiday_name": "Christmas Holiday",
|
||||
"calendar_id": "<uuid>",
|
||||
"calendar_name": "Madrid Primary School Calendar 2024-2025"
|
||||
}
|
||||
```
|
||||
|
||||
### Step 7: Verify Redis Caching
|
||||
|
||||
**First Request (Cache Miss):**
|
||||
```bash
|
||||
time curl -k -H "X-Tenant-ID: $TENANT_ID" \
|
||||
https://localhost/api/v1/external/tenants/$TENANT_ID/location-context
|
||||
```
|
||||
Expected: ~50-100ms
|
||||
|
||||
**Second Request (Cache Hit):**
|
||||
```bash
|
||||
time curl -k -H "X-Tenant-ID: $TENANT_ID" \
|
||||
https://localhost/api/v1/external/tenants/$TENANT_ID/location-context
|
||||
```
|
||||
Expected: ~5-10ms (much faster!)
|
||||
|
||||
**Check Redis:**
|
||||
```bash
|
||||
redis-cli
|
||||
> KEYS tenant_context:*
|
||||
> GET tenant_context:<tenant-id>
|
||||
> TTL tenant_context:<tenant-id> # Should show ~86400 seconds (24 hours)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Optional: Integrate with Training/Forecasting Services
|
||||
|
||||
### Option A: Manual Integration (Recommended First)
|
||||
|
||||
The helper classes are ready to use:
|
||||
|
||||
**In Training Service:**
|
||||
```python
|
||||
# services/training/app/ml/data_processor.py
|
||||
from app.ml.calendar_features import CalendarFeatureEngine
|
||||
from shared.clients.external_client import ExternalServiceClient
|
||||
|
||||
# In __init__:
|
||||
self.external_client = ExternalServiceClient(config=settings, calling_service_name="training")
|
||||
self.calendar_engine = CalendarFeatureEngine(self.external_client)
|
||||
|
||||
# In _engineer_features():
|
||||
if tenant_id:
|
||||
df = await self.calendar_engine.add_calendar_features(df, tenant_id)
|
||||
```
|
||||
|
||||
**In Forecasting Service:**
|
||||
```python
|
||||
# services/forecasting/app/services/forecasting_service.py or prediction_service.py
|
||||
from app.ml.calendar_features import forecast_calendar_features
|
||||
|
||||
# When preparing future features:
|
||||
future_df = await forecast_calendar_features.add_calendar_features(
|
||||
future_df,
|
||||
tenant_id=tenant_id,
|
||||
date_column="ds"
|
||||
)
|
||||
```
|
||||
|
||||
### Option B: Gradual Rollout
|
||||
|
||||
1. **Phase 1:** Deploy infrastructure (Steps 1-6 above) ✅
|
||||
2. **Phase 2:** Test with 1-2 bakeries near schools
|
||||
3. **Phase 3:** Integrate into training service
|
||||
4. **Phase 4:** Retrain models for test bakeries
|
||||
5. **Phase 5:** Integrate into forecasting service
|
||||
6. **Phase 6:** Compare forecast accuracy
|
||||
7. **Phase 7:** Full rollout to all tenants
|
||||
|
||||
---
|
||||
|
||||
## 📊 Monitoring & Validation
|
||||
|
||||
### Database Metrics
|
||||
|
||||
```sql
|
||||
-- Check calendar usage
|
||||
SELECT COUNT(*) FROM tenant_location_contexts
|
||||
WHERE school_calendar_id IS NOT NULL;
|
||||
|
||||
-- Check which calendars are most used
|
||||
SELECT c.calendar_name, COUNT(t.tenant_id) as tenant_count
|
||||
FROM school_calendars c
|
||||
LEFT JOIN tenant_location_contexts t ON c.id = t.school_calendar_id
|
||||
GROUP BY c.calendar_name;
|
||||
```
|
||||
|
||||
### Redis Cache Metrics
|
||||
|
||||
```bash
|
||||
redis-cli
|
||||
> INFO stats # Check hit/miss rates
|
||||
> KEYS calendar:* # List cached calendars
|
||||
> KEYS tenant_context:* # List cached tenant contexts
|
||||
```
|
||||
|
||||
### API Performance
|
||||
|
||||
Check external service logs for:
|
||||
- Calendar API response times
|
||||
- Cache hit rates
|
||||
- Any errors
|
||||
|
||||
```bash
|
||||
kubectl logs -n bakery-ia -l app=external-service --tail=100 | grep calendar
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔍 Troubleshooting
|
||||
|
||||
### Problem: Migration Fails
|
||||
|
||||
**Error:** `alembic.util.exc.CommandError: Can't locate revision...`
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Check current migration version
|
||||
cd services/external
|
||||
python -m alembic current
|
||||
|
||||
# Force to specific version if needed
|
||||
python -m alembic stamp head
|
||||
```
|
||||
|
||||
### Problem: Seed Script Fails
|
||||
|
||||
**Error:** `No module named 'app'`
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Ensure you're in the right directory
|
||||
cd services/external
|
||||
# Set PYTHONPATH
|
||||
export PYTHONPATH=$(pwd):$PYTHONPATH
|
||||
python scripts/seed_school_calendars.py
|
||||
```
|
||||
|
||||
### Problem: Calendar API Returns 404
|
||||
|
||||
**Check:**
|
||||
1. External service deployed with new router?
|
||||
```bash
|
||||
kubectl logs -n bakery-ia -l app=external-service | grep "calendar_operations"
|
||||
```
|
||||
2. Migration completed?
|
||||
```sql
|
||||
SELECT * FROM alembic_version;
|
||||
```
|
||||
3. Calendars seeded?
|
||||
```sql
|
||||
SELECT COUNT(*) FROM school_calendars;
|
||||
```
|
||||
|
||||
### Problem: Cache Not Working
|
||||
|
||||
**Check Redis Connection:**
|
||||
```bash
|
||||
# From external service pod
|
||||
kubectl exec -it <external-pod> -n bakery-ia -- redis-cli -h <redis-host> PING
|
||||
```
|
||||
|
||||
**Check Logs:**
|
||||
```bash
|
||||
kubectl logs -n bakery-ia -l app=external-service | grep "cache"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 Rollback Procedure
|
||||
|
||||
If you need to rollback:
|
||||
|
||||
```bash
|
||||
# 1. Rollback migration
|
||||
cd services/external
|
||||
python -m alembic downgrade -1
|
||||
|
||||
# 2. Restart external service
|
||||
kubectl rollout restart deployment external-service -n bakery-ia
|
||||
|
||||
# 3. Clear Redis cache
|
||||
redis-cli
|
||||
> FLUSHDB
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎉 Success Criteria
|
||||
|
||||
- ✅ Migration completed successfully
|
||||
- ✅ 2 calendars seeded (Madrid Primary & Secondary)
|
||||
- ✅ Calendar API returns valid responses
|
||||
- ✅ Tenant can be assigned to calendar
|
||||
- ✅ Holiday check works correctly
|
||||
- ✅ Redis cache reduces response time by >80%
|
||||
- ✅ No errors in external service logs
|
||||
|
||||
---
|
||||
|
||||
## 📞 Support
|
||||
|
||||
For issues or questions:
|
||||
- Check [HYPERLOCAL_CALENDAR_IMPLEMENTATION.md](HYPERLOCAL_CALENDAR_IMPLEMENTATION.md) for full technical details
|
||||
- Review API endpoint documentation in calendar_operations.py
|
||||
- Check logs for specific error messages
|
||||
|
||||
---
|
||||
|
||||
**Deployment Completed:** [Date]
|
||||
**Deployed By:** [Name]
|
||||
**Version:** 1.0.0
|
||||
Reference in New Issue
Block a user