Commit Graph

333 Commits

Author SHA1 Message Date
cal
ee2387a385 Merge pull request 'perf: parallelize independent API calls (#90)' (#106) from ai/major-domo-v2-90 into next-release
Some checks failed
Build Docker Image / build (push) Has been cancelled
Reviewed-on: #106
2026-03-20 17:48:27 +00:00
Cal Corum
6f3339a42e perf: parallelize independent API calls (#90)
Closes #90

Replace sequential awaits with asyncio.gather() in all locations identified
in the issue:

- commands/gameplay/scorebug.py: parallel team lookups in publish_scorecard
  and scorebug commands; also fix missing await on async scorecard_tracker calls
- commands/league/submit_scorecard.py: parallel away/home team lookups
- tasks/live_scorebug_tracker.py: parallel team lookups inside per-scorecard
  loop (compounds across multiple active games); fix missing await on
  get_all_scorecards
- commands/injuries/management.py: parallel get_current_state() +
  search_players() in injury_roll, injury_set_new, and injury_clear
- services/trade_builder.py: parallel per-participant roster validation in
  validate_trade()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 17:48:10 +00:00
cal
498fcdfe51 Merge pull request 'perf: cache inspect.signature() at decoration time (#97)' (#107) from ai/major-domo-v2-97 into next-release
All checks were successful
Build Docker Image / build (push) Successful in 1m23s
Reviewed-on: #107
2026-03-20 17:45:51 +00:00
Cal Corum
a3e63f730f perf: cache inspect.signature() at decoration time (#97)
Move inspect.signature(func) calls from inside wrapper functions to the
outer decorator function so the introspection cost is paid once at
decoration time instead of on every invocation.

- logged_command: sig, param_names, and exclude_set computed at decoration time;
  wrapper.__signature__ reuses the pre-computed sig
- cached_api_call: sig moved to decorator scope; bound_args still computed
  per-call (requires runtime args)
- cached_single_item: same as cached_api_call

Closes #97

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 17:45:06 +00:00
cal
f0934937cb Merge pull request 'perf: use channel.purge() instead of per-message delete loops (#93)' (#108) from ai/major-domo-v2#93 into next-release
All checks were successful
Build Docker Image / build (push) Successful in 1m21s
Reviewed-on: #108
2026-03-20 17:44:29 +00:00
cal
4775c175c5 Merge pull request 'ci: only build Docker images on merge to main/next-release' (#110) from ci/remove-pr-trigger into next-release
Some checks failed
Build Docker Image / build (push) Has been cancelled
Reviewed-on: #110
2026-03-20 17:44:11 +00:00
Cal Corum
ce2c47ca0c ci: remove pull_request trigger from Docker build workflow
The PR trigger caused Docker builds on every push to PR branches,
wasting CI resources. Only build on merge to main/next-release.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 12:43:38 -05:00
cal
0c041bce99 Merge pull request 'perf: replace json.dumps serialization test with isinstance fast path (#96)' (#109) from ai/major-domo-v2-96 into next-release
All checks were successful
Build Docker Image / build (push) Successful in 1m13s
Reviewed-on: #109
2026-03-20 17:38:57 +00:00
Cal Corum
70c4555a74 perf: replace json.dumps serialization test with isinstance fast path (#96)
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m22s
Closes #96

Replaces the per-field `json.dumps(value)` probe — which fully serialized
and discarded the result just to check serializability — with a type-check
fast path using `isinstance()`. The `_SERIALIZABLE_TYPES` tuple is defined
at module level so it's not recreated on every log call.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 12:32:34 -05:00
Cal Corum
8878ce85f7 perf: use channel.purge() instead of per-message delete loops (#93)
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m16s
Closes #93

Replace sequential message.delete() loops with channel.purge() bulk
delete in three locations:
- commands/admin/management.py: admin_clear_scorecards (up to 100 msgs)
- tasks/live_scorebug_tracker.py: _post_scorebugs_to_channel (25 msgs)
- tasks/live_scorebug_tracker.py: _clear_live_scores_channel (25 msgs)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 12:02:26 -05:00
cal
18ab1393c0 Merge pull request 'fix: split read-only data volume to allow state file writes (#85)' (#86) from ai/major-domo-v2-85 into next-release
All checks were successful
Build Docker Image / build (push) Successful in 1m9s
Reviewed-on: #86
2026-03-20 15:28:13 +00:00
cal
8862850c59 Merge pull request 'perf: cache user team lookup in player_autocomplete, reduce limit to 25' (#100) from ai/major-domo-v2#99 into next-release
Some checks failed
Build Docker Image / build (push) Has been cancelled
Reviewed-on: #100
2026-03-20 15:27:32 +00:00
cal
8d97e1dd17 Merge pull request 'perf: replace Redis KEYS with SCAN for cache invalidation (#98)' (#101) from ai/major-domo-v2-98 into next-release
Some checks failed
Build Docker Image / build (push) Has been cancelled
Reviewed-on: #101
2026-03-20 15:26:42 +00:00
cal
52fa56cb69 Merge pull request 'perf: parallelize schedule_service API calls with asyncio.gather' (#103) from ai/major-domo-v2-88 into next-release
All checks were successful
Build Docker Image / build (push) Successful in 1m16s
Reviewed-on: #103
2026-03-20 15:16:40 +00:00
Cal Corum
d4e7246166 cleanup: remove unused weeks_ahead parameter from get_upcoming_games
The parameter was already ignored (body hardcodes range(1, 19)).
Remove from signature and the one caller that passed it.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 10:11:18 -05:00
Cal Corum
0992acf718 refactor: use GameFactory/TeamFactory in schedule service tests
All checks were successful
Build Docker Image / build (pull_request) Successful in 58s
Replace custom _make_game/_make_team helpers with existing test
factories for consistency with the rest of the test suite.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 10:05:28 -05:00
Cal Corum
b480120731 perf: parallelize schedule_service week fetches with asyncio.gather (#88)
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m20s
Closes #88

Replaced sequential for-loops in get_team_schedule(), get_recent_games(),
and get_upcoming_games() with asyncio.gather() to fire all per-week HTTP
requests concurrently. Also adds import asyncio which was missing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 10:02:11 -05:00
cal
6d3c7305ce Merge pull request 'perf: replace sequential awaits with asyncio.gather()' (#102) from fix/sequential-awaits into next-release
All checks were successful
Build Docker Image / build (push) Successful in 1m25s
Reviewed-on: #102
2026-03-20 14:22:48 +00:00
Cal Corum
9df8d77fa0 perf: replace sequential awaits with asyncio.gather() for true parallelism
Fixes #87

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 09:14:14 -05:00
Cal Corum
df9e9bedbe perf: replace Redis KEYS with SCAN in clear_prefix (#98)
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m22s
Closes #98

Replace blocking `client.keys(pattern)` with non-blocking
`client.scan_iter(match=pattern)` to avoid full-keyspace scans
that block the Redis server during cache invalidation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 09:02:22 -05:00
Cal Corum
c8ed4dee38 perf: cache user team lookup in player_autocomplete, reduce limit to 25
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m16s
Closes #99

- Add module-level `_user_team_cache` dict with 60-second TTL so
  `get_user_major_league_team` is called at most once per minute per
  user instead of on every keystroke.
- Reduce `search_players(limit=50)` to `limit=25` to match Discord's
  25-choice display cap and avoid fetching unused results.
- Add `TestGetCachedUserTeam` class covering cache hit, TTL expiry, and
  None caching; add `clear_user_team_cache` autouse fixture to prevent
  test interference via module-level state.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 08:34:32 -05:00
Cal Corum
03dd449551 fix: split read-only data volume to allow state file writes (#85)
All checks were successful
Build Docker Image / build (pull_request) Successful in 57s
The data/ volume was mounted :ro to protect Google Sheets credentials,
but this also prevented all state trackers from persisting JSON files
(scorecards, voice channels, trade channels, soak data), causing silent
save failures and stale data accumulating across restarts.

- Mount only the credentials file as :ro (file-level mount)
- Add a separate :rw storage/ volume for runtime state files
- Move all tracker default paths from data/ to storage/
- Add STATE_HOST_PATH env var (defaults to ./storage)
- Update SHEETS_CREDENTIALS_HOST_PATH semantics: now a file path
  (e.g. ./data/major-domo-service-creds.json) instead of a directory
- Add storage/ to .gitignore

Closes #85

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 13:34:43 -05:00
cal
6c49233392 Merge pull request 'fix: replace broken interaction_check decorator with MaintenanceAwareTree subclass' (#83) from fix/maintenance-mode-interaction-check into main
All checks were successful
Build Docker Image / build (push) Successful in 49s
Reviewed-on: #83
2026-03-17 17:34:15 +00:00
Cal Corum
9a4ecda564 Merge origin/main into fix branch to resolve conflict
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m3s
Keep both the type: ignore annotation and the logger.info call
in admin_maintenance.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 12:32:38 -05:00
Cal Corum
d295f27afe fix: replace broken @self.tree.interaction_check with MaintenanceAwareTree subclass
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m11s
The previous code attempted to register a maintenance mode gate via
@self.tree.interaction_check inside setup_hook.  That pattern is invalid
in discord.py — interaction_check is an overridable method on CommandTree,
not a decorator.  The assignment was silently dropped, making maintenance
mode a no-op and producing a RuntimeWarning about an unawaited coroutine.

Changes:
- Add MaintenanceAwareTree(discord.app_commands.CommandTree) that overrides
  interaction_check: blocks non-admins when bot.maintenance_mode is True,
  always passes admins through, no-op when maintenance mode is off
- Pass tree_cls=MaintenanceAwareTree to super().__init__() in SBABot.__init__
- Add self.maintenance_mode: bool = False to SBABot.__init__
- Update /admin-maintenance command to actually toggle bot.maintenance_mode
- Add tests/test_bot_maintenance_tree.py with 8 unit tests covering all
  maintenance mode states, admin pass-through, DM context, and missing attr

Closes #82

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 12:25:01 -05:00
cal
0a2df0f36e Merge pull request 'Merge next-release into main' (#81) from next-release into main
All checks were successful
Build Docker Image / build (push) Successful in 53s
Reviewed-on: #81
2026-03-17 16:44:42 +00:00
Cal Corum
910a27e356 Merge main into next-release
All checks were successful
Build Docker Image / build (push) Successful in 3m26s
Build Docker Image / build (pull_request) Successful in 58s
Resolve conflict in views/trade_embed.py: keep main's hotfix
(emoji-stripped UI, inline validation errors) and apply next-release's
import refactor (lazy imports hoisted to top-level).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 11:28:05 -05:00
cal
541380acdf Merge pull request 'fix: re-fetch existing transactions on each validation' (#72) from fix/refresh-existing-transactions-on-validation into next-release
All checks were successful
Build Docker Image / build (push) Successful in 1m24s
Build Docker Image / build (pull_request) Successful in 57s
Reviewed-on: #72
2026-03-11 16:27:55 +00:00
cal
514797b787 Merge pull request 'fix: prevent partial DB writes on scorecard submission failure' (#80) from fix/scorecard-submission-resilience-v2 into next-release
Some checks failed
Build Docker Image / build (push) Has been cancelled
Reviewed-on: #80
2026-03-11 16:27:28 +00:00
Cal Corum
461112b2f8 fix: prevent partial DB writes and show detailed errors on scorecard submission failure
Read all spreadsheet data (plays, box score, pitching decisions) before any
database writes so formula errors like #N/A don't leave the DB in a partial
state. Also preserve SheetsException detail through the error chain and show
users the specific cell/error instead of a generic failure message.

Closes #78

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 20:55:10 -05:00
cal
bebe25b9dd Merge pull request 'fix: prefix trade validation errors with team abbreviation' (#71) from fix/trade-errors-show-team-abbrev into next-release
All checks were successful
Build Docker Image / build (push) Successful in 3m5s
Reviewed-on: #71
2026-03-10 15:46:42 +00:00
cal
2f7b82e377 Merge pull request 'chore: pin all Python dependency versions in requirements.txt (#76)' (#77) from ai/major-domo-v2-76 into main
All checks were successful
Build Docker Image / build (push) Successful in 58s
Reviewed-on: #77
2026-03-10 14:05:47 +00:00
Cal Corum
88edd1fa10 chore: pin all Python dependency versions in requirements.txt (#76)
All checks were successful
Build Docker Image / build (pull_request) Successful in 2m58s
- Pin redis==7.3.0 and move to requirements.txt (production)
- Create requirements-dev.txt with all dev/test deps pinned to exact versions
  (pytest-mock==3.15.1, black==26.1.0, ruff==0.15.0)
- Remove dev/test tools from requirements.txt (not needed in Docker image)
- Document pinning policy and requirements-dev.txt usage in CLAUDE.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 01:03:27 -05:00
cal
9ba0713887 Merge pull request 'fix: trailing slash on all collection POST calls' (#75) from fix/trailing-slash-307-redirect into main
All checks were successful
Build Docker Image / build (push) Successful in 51s
Reviewed-on: #75
2026-03-10 00:42:16 +00:00
Cal Corum
ba55ed3109 fix: add trailing slashes to all collection POST calls
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m16s
Ensures all client.post() calls to collection endpoints include
trailing slashes, matching the standardized database API routes.
Covers BaseService.create(), TransactionService, InjuryService,
and DraftListService POST calls.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 19:34:36 -05:00
cal
269429254f Merge pull request 'fix: targeted trailing slashes for POST endpoints (hotfix)' (#74) from fix/trailing-slash-307-redirect into main
All checks were successful
Build Docker Image / build (push) Successful in 52s
Reviewed-on: #74
2026-03-09 22:52:29 +00:00
Cal Corum
f6a25aa16d fix: use targeted trailing slashes instead of universal (hotfix)
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m7s
Reverts universal trailing slash in _build_url which broke custom_commands
endpoints (401 on /execute/). Instead, add trailing slashes only to the
two batch POST endpoints (plays/, decisions/) that need them to avoid
307 redirects dropping request bodies.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 17:50:58 -05:00
cal
52ab92523c Merge pull request 'fix: add trailing slashes to prevent 307 redirects dropping POST bodies' (#73) from fix/trailing-slash-307-redirect into main
All checks were successful
Build Docker Image / build (push) Successful in 53s
Reviewed-on: #73
2026-03-09 22:26:52 +00:00
Cal Corum
9379ba587a fix: add trailing slashes to API URLs to prevent 307 redirects dropping POST bodies
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m13s
The FastAPI server returns 307 redirects for URLs without trailing slashes.
aiohttp follows these redirects but converts POST to GET, silently dropping
the request body. This caused play-by-play and decision data from
/submit-scorecard to never be persisted to the database despite the API
returning success.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 17:25:08 -05:00
cal
4314b67537 Merge pull request 'feat: add is_admin() helper to utils/permissions.py (#55)' (#64) from ai/major-domo-v2#55 into next-release
All checks were successful
Build Docker Image / build (push) Successful in 1m11s
Reviewed-on: #64
2026-03-09 14:38:07 +00:00
Cal Corum
c41166d53c feat: add is_admin() helper to utils/permissions.py (#55)
Add centralized `is_admin(interaction)` helper that includes the
`isinstance(interaction.user, discord.Member)` guard, preventing
AttributeError in DM contexts.

Use it in `can_edit_player_image()` which previously accessed
`guild_permissions.administrator` directly without the isinstance
guard. Update the corresponding test to mock the user with
`spec=discord.Member` so the isinstance check passes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 09:37:22 -05:00
Cal Corum
556a30c397 fix: re-fetch existing transactions on each validation
The TransactionBuilder cached pre-existing transactions on first load
and never refreshed them. This meant transactions submitted by other
sessions (or newly visible after API fixes) were invisible for the
lifetime of the builder session, causing incorrect roster projections.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 08:10:22 -05:00
Cal Corum
db08d0eaa4 fix: auto-fetch next_week for trade validation against projected roster
Trade validation now automatically fetches the current week from
league_service and validates against next week's projected roster
(including pending transactions), matching /dropadd behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 11:48:15 -05:00
Cal Corum
8ee35e564c fix: prefix trade validation errors with team abbreviation
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m5s
Roster-level errors, warnings, and suggestions now display as
"[BSG] Too many ML players" so users know which team each issue
applies to.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 11:37:39 -05:00
cal
b3b8cd9683 Merge pull request 'fix: show validation errors in trade embed Quick Status' (#70) from fix/trade-embed-errors-and-cleanup into main
All checks were successful
Build Docker Image / build (push) Successful in 50s
Reviewed-on: #70
2026-03-08 16:29:06 +00:00
Cal Corum
58fe9f22de fix: trade validation now checks against next week's projected roster
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m5s
validate_trade() was passing next_week=None to each team's
validate_transaction(), which skipped load_existing_transactions()
entirely. Trades were validated against the current roster only,
ignoring pending /dropadd transactions for next week.

Now auto-fetches current week from league_service and passes
next_week=current_week+1, matching /dropadd validation behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 16:27:03 +00:00
Cal Corum
e98a658fde fix: show actual validation errors in trade embed Quick Status
Quick Status previously only showed "X errors found" with no details.
Now lists each error and suggestion inline. Also stripped all emoji
from embed titles, field names, values, buttons, and messages.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 16:27:03 +00:00
cal
ee324693b1 Merge pull request 'ci: Use docker-tags composite action for multi-channel release support' (#68) from ci/docker-tags-multi-channel into next-release
All checks were successful
Build Docker Image / build (push) Successful in 1m6s
Reviewed-on: #68
2026-03-07 03:33:26 +00:00
cal
1a6300854e Merge pull request 'test: implement test_validate_transaction_exception_handling (#35)' (#67) from ai/major-domo-v2#35 into next-release
Reviewed-on: #67
2026-03-07 03:32:22 +00:00
cal
b6b997c15e Merge pull request 'fix: reuse persistent aiohttp.ClientSession in GiphyService (#26)' (#66) from ai/major-domo-v2-26 into next-release
Reviewed-on: #66
2026-03-07 03:31:02 +00:00