Skip to content

fix: explicit DM router and admin session exclusivity (#111, #112)#136

Merged
adrunkhuman merged 5 commits intomasterfrom
fix/dm-routing-and-admin-exclusivity
Mar 21, 2026
Merged

fix: explicit DM router and admin session exclusivity (#111, #112)#136
adrunkhuman merged 5 commits intomasterfrom
fix/dm-routing-and-admin-exclusivity

Conversation

@adrunkhuman
Copy link
Owner

Summary

  • Make DM workflow routing precedence explicit #112 – Create DMRouter in typer_bot/services/dm_router.py as the single source of truth for DM routing precedence (fixture session → results session → prediction handler). Bot's on_message routes DMs directly through the router; both cog-level on_message listeners removed, eliminating the implicit listener-registration-order dependency.
  • Decide and enforce admin DM workflow exclusivity #111 – Admin DM workflows are now mutually exclusive. _start_fixture_dm rejects (with a DM to the admin) if a results-entry session is active; results_enter rejects (with an ephemeral error) if a fixture-creation session is active. Both DM-send failure paths now cancel the session on any exception, not just discord.Forbidden.

Test plan

  • tests/test_dm_router.py — 7 new tests covering routing precedence and guard conditions
  • TestAdminSessionExclusivity in test_admin_commands.py — 4 new tests for allowed/blocked session-start combinations
  • TestOnMessageDMRouting in test_bot.py — 4 new tests verifying DM→router, guild→skip, None-router warning, thread-handler priority
  • Removed stale tests that tested behavior now owned by the router
  • Full suite: 304 passed, 1 skipped (pre-existing timezone env-var skip)

Closes #111
Closes #112

🤖 Generated with Claude Code

adrunkhuman and others added 3 commits March 21, 2026 23:20
**#112 – explicit DM routing precedence**
- Add `DMRouter` in `typer_bot/services/dm_router.py` as the single
  source of truth for DM routing order: fixture session → results
  session → prediction handler.
- Bot's `on_message` routes DMs through the router directly; cog-level
  `on_message` listeners removed from `AdminCommands` and `UserCommands`
  so routing no longer depends on listener registration order.
- Remove the ad-hoc `has_results_session` guard buried in
  `DMPredictionHandler.handle_dm`; the router now owns that invariant.

**#111 – admin DM workflow exclusivity**
- `_start_fixture_dm` rejects the request if a results-entry session is
  already active, sending a clear DM to the admin.
- `results_enter` rejects the request if a fixture-creation session is
  already active, responding with an ephemeral error.
- Add `WorkflowStateStore.has_admin_session()` helper that covers both
  admin session types.

Tests:
- New `tests/test_dm_router.py` covers all routing precedence cases.
- New `TestAdminSessionExclusivity` in `test_admin_commands.py` covers
  allowed and blocked session-start combinations.
- Removed stale on_message listener tests that moved to the router.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Log and return when dm_router is None instead of silently dropping DMs
- Catch all exceptions (not just HTTPException) when sending fixture-create
  DM so orphaned sessions are always cancelled on send failure
- Remove dead has_admin_session() helper (never called)
- Add TestOnMessageDMRouting tests covering DM→router, guild→skip,
  None-router warning, and thread-handler priority

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Catch all exceptions (not just discord.Forbidden) in results_enter DM
  send so orphaned results sessions are always cancelled on failure,
  matching the fix already applied to _start_fixture_dm
- Patch discord.ext.commands.Bot.on_message in guild-message routing
  test instead of process_commands, so the test asserts the correct
  super() call path and stays robust against discord.py internals

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@railway-app railway-app bot temporarily deployed to patient-quietude / matchday-typer-pr-136 March 21, 2026 22:26 Destroyed
@railway-app
Copy link

railway-app bot commented Mar 21, 2026

🚅 Deployed to the matchday-typer-pr-136 environment in patient-quietude

Service Status Web Updated (UTC)
matchday-typer ✅ Success (View Logs) Mar 21, 2026 at 10:34 pm

- Add exclusivity check in fixture_create *before* the 'Check your DMs'
  response so conflicting-session errors are a single clear message,
  not a success ack followed by an error; the _start_fixture_dm fallback
  guard remains for the view-triggered path
- Widen contextlib.suppress scope to Exception so any send failure in
  the conflict-rejection DM path still reaches return False
- Split exclusivity test into command-path and _start_fixture_dm-path
  cases to cover both call sites

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@railway-app railway-app bot temporarily deployed to patient-quietude / matchday-typer-pr-136 March 21, 2026 22:31 Destroyed
Move has_results_session guard before the open_fixtures check so the
exclusivity error is shown for both the direct path (no open fixtures)
and the warning-view path (open fixtures exist). Previously the guard
was dead when fixtures were open — the view was shown instead, and
clicking 'Yes' sent 'Check your DMs!' before _start_fixture_dm could
block it.

The _start_fixture_dm fallback guard remains for the narrow race window
between the command check and the DM send.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@railway-app railway-app bot temporarily deployed to patient-quietude / matchday-typer-pr-136 March 21, 2026 22:33 Destroyed
@adrunkhuman adrunkhuman merged commit 31e67ac into master Mar 21, 2026
2 checks passed
@adrunkhuman adrunkhuman deleted the fix/dm-routing-and-admin-exclusivity branch March 21, 2026 22:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make DM workflow routing precedence explicit Decide and enforce admin DM workflow exclusivity

1 participant