--- title: Major Domo Database Release — 2026.3.17 description: Database migration and schema changes for Major Domo v2 on 2026-03-17. type: reference domain: server-configs tags: [major-domo, deployment, release-notes, database] --- # Major Domo Database Release — 2026.3.17 **Date:** 2026-03-17 **Branch:** next-release → main (PR #64, 11 commits) **Repo:** cal/major-domo-database **Server:** akamai (`sba_db_api` container, port 801) ## Release Summary 11 commits from `next-release` rebased onto `main`. Mix of query performance improvements, bug fixes, and code quality cleanup. No schema migrations — safe drop-in deploy. ## Performance - **Push limit/offset to DB in `PlayerService.get_players`** (#37): Previously fetched all rows then sliced in Python. Now passes `LIMIT`/`OFFSET` directly to the Peewee query, eliminating full-table reads on paginated requests. - **Eliminate N+1 queries in batch POST endpoints** (#25): Replaced per-row `get_or_none()` loops in `battingstats`, `results`, `schedules`, and `transactions` batch insert endpoints with a single bulk set-lookup before the write loop. ## Bug Fixes - **Fix `lob_2outs` and `rbipercent` calculation in `SeasonPitchingStats`** (#28): Both fields were returning incorrect values due to wrong formula inputs. Now computed correctly from the underlying stat columns. - **Invalidate cache after `PlayerService` write operations** (#32): Cache was being populated on reads but never invalidated on writes, causing stale player data to persist until the next restart. - **Validate `sort_by` parameter with `Literal` type in `views.py`** (#36): Unvalidated `sort_by` could cause silent no-ops or unexpected ordering. Now enforced with a `Literal` type annotation, raising a 422 on invalid values. ## Code Quality - **Replace bare `except:` with `except Exception:`** (#29): Silencing `KeyboardInterrupt`, `SystemExit`, and `GeneratorExit` is an antipattern. All 6 instances updated. - **Remove unused imports in `standings.py` and `pitchingstats.py`** (#30): Dead imports removed (`pydantic` in `standings.py`). - **Replace `print(req.scope)` with `logger.debug` in `/api/docs`** (#21): Debug print statement that logged full request scope on every docs page load replaced with a conditional logger call. - **Remove empty `WEEK_NUMS` dict from `db_engine.py`** (#34): Unused stub dict removed. - **Remove unimplementable skipped caching tests** (#33): Tests marked `@pytest.mark.skip` for a caching interface that was never built. Removed rather than leaving permanently skipped. ## Conflict Resolution Branch was rebased (not squash-merged) onto main. Six files had textual conflicts from two main-branch fixes that landed after `next-release` diverged: **Trailing slash regression (6 router files)** - PR #61 on main fixed a production bug: `aiohttp` converts POST→GET on 307 redirects, silently dropping request bodies. The fix changed all `@router.post("")` → `@router.post("/")`. - next-release's batch N+1 and bare-except PRs all touched the same files with the old `""` signature. - Resolution: kept `@router.post("/")` from main, applied next-release's functional changes on top. **Case-insensitive `team_abbrev` filter (`transactions.py`)** - PR #60 on main fixed affiliate roster transactions being silently dropped due to case mismatch (input uppercased, DB column mixed-case). Fix used `fn.UPPER(Team.abbrev)`. - next-release's version of `transactions.py` predated this fix. - Resolution: preserved `fn.UPPER(Team.abbrev)` from main alongside next-release's N+1 fix. **`requirements.txt`** - Main has fully pinned deps including `starlette==0.52.1` (from 2026-03-09 outage) and a new `requirements-dev.txt`. - next-release had loose pins and no `requirements-dev.txt`. - Resolution: took main's fully-pinned version entirely.