Skip to content

Fix SessionManager write amplification causing lock contention#166

Merged
galatanovidiu merged 2 commits intotrunkfrom
fix/session-manager-write-amplification
Apr 8, 2026
Merged

Fix SessionManager write amplification causing lock contention#166
galatanovidiu merged 2 commits intotrunkfrom
fix/session-manager-write-amplification

Conversation

@galatanovidiu
Copy link
Copy Markdown
Contributor

Summary

Why: MCP initialization sends 4+ concurrent HTTP requests (initialize, tools/list, resources/list, prompts/list), each hitting SessionManager::validate_session() which unconditionally writes last_activity and runs cleanup_expired_sessions() — producing 4–8 writes to the same wp_usermeta row. This causes row-level lock contention that can cascade into database timeout failures.

What:

  • Throttle last_activity writes to once per 60 seconds (configurable via new mcp_adapter_session_activity_update_interval filter) — freshly-created sessions produce zero writes during the initialization burst
  • Remove redundant cleanup_expired_sessions() call from validate_session() — it already runs in create_session()

Test plan

  • Existing test_validation_updates_last_activity passes (adjusted to exceed throttle window)
  • New test_validation_skips_last_activity_update_within_throttle_window — no write within 60s
  • New test_validation_does_not_call_cleanup — expired sessions survive validation
  • All 1001 tests pass, PHPCS clean, PHPStan Level 8 zero errors

validate_session() was writing to the same wp_usermeta row on every MCP
request (last_activity update + cleanup_expired_sessions), causing InnoDB
row-level lock contention when 4+ concurrent requests hit simultaneously
during MCP initialization.

Two changes:
- Throttle last_activity writes to once per 60s (configurable via
  mcp_adapter_session_activity_update_interval filter)
- Remove cleanup_expired_sessions() call — it already runs in
  create_session() and is unnecessary on the validation hot path
Copilot AI review requested due to automatic review settings April 7, 2026 18:00
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 7, 2026

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: galatanovidiu <ovidiu-galatan@git.wordpress.org>
Co-authored-by: gziolo <gziolo@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR reduces database lock contention during MCP initialization by limiting how often session validation writes to the mcp_adapter_sessions usermeta row.

Changes:

  • Adds a configurable throttle (default 60s) for persisting last_activity updates during SessionManager::validate_session().
  • Removes opportunistic cleanup_expired_sessions() calls from validate_session() to avoid extra writes.
  • Updates/extends unit tests to reflect throttling behavior and the removal of cleanup-on-validate.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
includes/Transport/Infrastructure/SessionManager.php Introduces activity_update_interval config + throttled last_activity writes; removes cleanup call from validation.
tests/Unit/Transport/McpSessionManagerTest.php Adjusts existing timestamp-based validation test and adds tests for throttling and no-cleanup behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 7, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.25%. Comparing base (912c0ba) to head (13218b3).
⚠️ Report is 1 commits behind head on trunk.

Additional details and impacted files
@@             Coverage Diff              @@
##              trunk     #166      +/-   ##
============================================
+ Coverage     88.06%   88.25%   +0.18%     
- Complexity     1241     1243       +2     
============================================
  Files            54       54              
  Lines          4030     4035       +5     
============================================
+ Hits           3549     3561      +12     
+ Misses          481      474       -7     
Flag Coverage Δ
unit 88.25% <100.00%> (+0.18%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Prevents sessions from expiring despite active use when
inactivity_timeout is configured lower than the throttle interval.
Also normalizes negative intervals to zero.
Copy link
Copy Markdown
Member

@gziolo gziolo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checked this out locally — lint, PHPStan, and the full test suite all pass.

The fix lands in the right place and should mitigate the problem nicely. Fresh sessions start with last_activity set to now, so the init burst falls inside the throttle window and simply skips the writes that were hurting us.

@galatanovidiu galatanovidiu merged commit f1c3566 into trunk Apr 8, 2026
20 of 22 checks passed
@galatanovidiu galatanovidiu deleted the fix/session-manager-write-amplification branch April 8, 2026 11:38
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.

3 participants