Repository navigation
Refactor app into modular Flask project + probabilistic forecast, dashboard, map, and tests - #4
Conversation
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (30)
📝 WalkthroughWalkthroughThe PR refactors the Flask app into an application factory with shared services for USGS ingestion, SQLite caching, analytics, and risk scoring. It adds new routes, dashboard/map/forecast pages, tests, deployment settings, and documentation updates. ChangesQuakeRisk application refactor
Sequence Diagram(s)sequenceDiagram
participant forecast_js as "static/js/forecast.js"
participant api_forecast as "app.routes.api_forecast"
participant predict as "app.services.model.predict"
forecast_js->>api_forecast: GET /api/forecast with lat/lon/radius/hours/min_mag
api_forecast->>predict: score forecast request
predict-->>api_forecast: risk payload
api_forecast-->>forecast_js: JSON response
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cf90fa6ff5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| app.config.from_object(config_class) | ||
| logging.basicConfig(level=logging.INFO) | ||
| init_db(app.config['SQLITE_DB_PATH']) | ||
| seed_bootstrap_if_empty(app.config['SQLITE_DB_PATH'], app.config['ENABLE_BOOTSTRAP_DATA']) |
There was a problem hiding this comment.
Fetch live data before seeding demo rows
With the default ENABLE_BOOTSTRAP_DATA=true and an empty DB, this inserts bootstrap rows during app creation; upsert_earthquakes records last_successful_refresh_epoch as now, so the first /api/earthquakes call hits the TTL check in refresh_if_needed and returns cache instead of trying USGS. New deployments can show bootstrap_demo earthquakes for the full CACHE_TTL_SECONDS unless a user forces refresh.
Useful? React with 👍 / 👎.
| feeds=current_app.config['FEEDS']; return current_app.config['USGS_FEED_URL'] if name=='custom' else feeds.get(name, feeds.get(current_app.config['DEFAULT_FEED_WINDOW'], current_app.config['USGS_FEED_URL'])) | ||
| def refresh_if_needed(feed='day', force=False): | ||
| db=current_app.config['SQLITE_DB_PATH']; ttl=current_app.config['CACHE_TTL_SECONDS']; last=int(get_meta(db,'last_successful_refresh_epoch','0') or 0) | ||
| if not force and int(time.time())-last <= ttl: return 'cache' |
There was a problem hiding this comment.
Key the refresh TTL by requested feed
After any feed refresh sets last_successful_refresh_epoch, this global TTL check returns cache for every other feed name. For example, visiting the dashboard's default day feed and then selecting 30day within five minutes never fetches all_month.geojson, while query_earthquakes does not filter by source_feed, so the feed selector can show data from the wrong feed until force refresh or TTL expiry.
Useful? React with 👍 / 👎.
| for idx,col in [('idx_quakes_time','time_ms'),('idx_quakes_mag','magnitude'),('idx_quakes_lat','latitude'),('idx_quakes_lon','longitude'),('idx_quakes_region','region')]: | ||
| c.execute(f'CREATE INDEX IF NOT EXISTS {idx} ON earthquakes({col})') |
There was a problem hiding this comment.
Migrate old cache tables before adding indexes
On deployments that already have the pre-refactor SQLite table, CREATE TABLE IF NOT EXISTS earthquakes leaves the old schema in place without the new region column. This index creation then raises sqlite3.OperationalError: no such column: region during app startup, so upgrading with an existing cache/persistent disk can fail before serving traffic.
Useful? React with 👍 / 👎.
Motivation
main.pyinto a modular Flask app with services, safer SQLite handling, and clearer configuration.Description
app/__init__.py,app/config.py,app/routes.py,app/services/{usgs_client,cache,analytics,model}.py, andapp/utils.py, while keepingmain.pycompatible withgunicorn main:appfor Render.id, refresh metadata, bootstrap/demo fallback data, and safe query helpers (app/services/cache.py).GET /api/earthquakes,/api/summary,/api/regions,/api/timeseries,/api/forecast,POST /api/model/train(admin-token protected),GET /api/model/status,/api/health/deep, and frontend pages/dashboard,/map,/globe,/forecast,/aboutwith modern UX (Chart.js, Leaflet, globe.gl).joblib, time-aware feature engineering (rolling counts, mags, depths, aftershock heuristics), calibrated outputs (risk score 0–100, probability bucket, confidence), and safe fallbacks when ML deps or data are insufficient (app/services/model.py).requirements.txt,.env.example,.python-version,render.yamlupdates,Procfilecompatibility,README.mdupdates,CHANGELOG.md, and a GitHub Actions workflow for tests.Testing
pytestand all tests passed:PYENV_VERSION=3.14.4 pytest -q→9 passed.python -m compileall .which completed successfully./health,/api/earthquakes,/api/summary,/api/forecast,/dashboard,/map,/globe, and/forecastall served correctly.pip install -r requirements.txtcould not be validated in this environment due to outbound package index access returning403 Forbidden, but therequirements.txtfile is updated and Render will install dependencies during build.Codex Task
Summary by CodeRabbit
New Features
Bug Fixes
Documentation
Tests