Skip to content

fix: close remaining race conditions (PR 91 continuation) - #91

Closed
aaxnet wants to merge 1 commit into
nightcore-team:mainfrom
aaxnet:fix/pr91-remaining-races
Closed

fix: close remaining race conditions (PR 91 continuation)#91
aaxnet wants to merge 1 commit into
nightcore-team:mainfrom
aaxnet:fix/pr91-remaining-races

Conversation

@aaxnet

@aaxnet aaxnet commented Aug 30, 2026

Copy link
Copy Markdown

This PR continues the race condition fixes from PR #90, addressing additional critical race conditions found during extended audit.

Summary of Fixes

Critical Race Conditions Fixed

  1. Clan Shop Double-Spend (clans/commands/manage/shop.py)

    • Added or_update=True when fetching clan for balance check
    • Prevents overspending clan reputation/coins
  2. Multiplayer Roulette Balance Lost Update ( asks/multiplayer_roulette.py)

    • Added SELECT ... FOR UPDATE on user rows before modifying balances
    • Prevents lost updates when multiple games settle concurrently
  3. Role Request Approve/Decline (
    ole_requests/handlers/approve.py, decline.py)

    • Fixed or_update typo (was passed to cast() instead of function)
    • Prevents double approval/decline race
  4. Compbuilder V2 Component Send (compbuilder/components/modal/choose_image.py)

    • Fixed interaction response order (respond first, then send to channel)
    • Fixed V2 component channel send duplicate response bug
  5. Valentine Cooldown (�alentine/commands/send.py)

    • Replaced in-memory cooldown dict with database-backed cooldown
    • Added �alentine_cooldown_until column to User model
    • Persistent across restarts, works across shards
  6. Rainbow Role Batch Update ( asks/rainbow_role.py)

    • Update DB schedule BEFORE Discord API call
    • Prevents schedule drift if bot crashes mid-iteration
  7. Unpunish Task ( asks/unpunish.py)

    • Dispatch unpunish events BEFORE deleting infractions
    • Prevents silent failure where user stays punished but DB record deleted
  8. Proposal Message Deletion (proposals/events/proposal.py)

    • Delete original message AFTER successful proposal creation
    • Prevents data loss if Discord send fails
  9. Clan Leave Role Removal (clans/commands/leave.py)

    • Remove Discord role BEFORE deleting DB record
    • Use or_update lock to prevent race with concurrent operations
  10. Temp Role/Multiplier Tasks ( asks/temp_role.py, emp_multiplier.py)

    • Added or_update with skip_locked for task locking
    • Prevents double-processing in multi-worker deployments
  11. Role Request Approve/Decline - Fixed or_update typo in cast() call

  12. Valentine Cooldown - Replaced in-memory dict with DB-backed cooldown

    • Added �alentine_cooldown_until column to User model
    • Persistent across restarts, works across shards
  13. Compbuilder V2 Component Send - Fixed interaction response order

    • Respond to interaction first, then send to channel
    • Fixed V2 component channel send duplicate response
  14. Rainbow Role Task - Update DB schedule BEFORE Discord API call

    • Prevents schedule drift if bot crashes mid-iteration
  15. Voice Gateway - Fixed function call formatting for line length

Database Helpers Extended

  • get_or_create_user(for_update=)
  • get_user_for_update()
  • ry_deduct_user_coins() - atomic CAS
  • get_clan_member/by_id/by_name/for_update
  • get_user_ticket/state/for_update
  • get_latest_user_role_request/for_update
  • get_casino_game_by_message_id/for_update
  • get_last_logging_revision/for_update
  • get_custom_component_by_id/for_update
  • get_specified_field/for_update
  • get_all_expired_* with SKIP LOCKED
  • get_active_casino_games with SKIP LOCKED

Regression Tests Added

  • ests/test_race_conditions.py - 11 tests covering concurrent scenarios

Verification

uff --select E,W,F src - All checks passed

  • pytest tests/test_race_conditions.py - 11 tests passed

Remaining Known Issues (Future Work)

  • Moderation commands: �an.py, mute.py, �mute.py, mpmute.py still have Discord-state TOCTOU
  • Clans manage/shop.py initial check still has minor TOCTOU (mitigated by approve handler lock)
  • Tickets create.py ickets_count increment not fully atomic

ole_requests modal send/create still has minor TOCTOU

  • asks/rainbow_role.py dual _apply_color call redundancy
  • API guild_state config updates can lose updates under high concurrency

Closes #90

- Fix rainbow_role task syntax error and batch update logic
- Fix unpunish task: dispatch events before deleting infractions
- Fix proposal message deletion after successful send
- Fix temp_role/temp_multiplier tasks: use FOR UPDATE with re-fetch
- Fix clan leave role removal: remove role before DB delete
- Fix valentine cooldown: use DB-backed cooldown instead of in-memory dict
- Fix compbuilder V2 component send interaction response order
- Fix role request approve/decline for_update typo
- Fix temp_multiplier/temp_role locking with FOR UPDATE SKIP LOCKED
- Fix voice gateway function call formatting
- Add regression tests for race conditions
- Run ruff and pytest: all pass
@aaxnet aaxnet closed this by deleting the head repository Aug 31, 2026
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.

1 participant