Skip to content

Fix InMemoryMcpTaskStore TTL clocks, cancel CAS, and missing-task throws - #1965

Open
robertmclaws wants to merge 2 commits into
modelcontextprotocol:mainfrom
CloudNimble:fix/in-memory-task-store-ttl-windows
Open

robertmclaws wants to merge 2 commits into
modelcontextprotocol:mainfrom
CloudNimble:fix/in-memory-task-store-ttl-windows

Conversation

@robertmclaws

Copy link
Copy Markdown

Fixes #1963.

InMemoryMcpTaskStore mixed work and tracking into one CreatedAt + TTL clock, threw on missing mutations, could report a successful cancel that lost the CAS, swept the dictionary on the create thread before inserting, and ignored CancellationToken.

Changes

  1. SetCancelledAsync return value — transitioned is reset on the terminal/expired retry so a lost CAS against complete/fail no longer returns true.
  2. Missing tasks — TryUpdate returns false instead of throwing. Cancel returns false; complete/fail/input are no-ops.
  3. Work vs track clocks — IsActive is the work window (CreatedAt + TTL). Never-terminal rows stay visible until CreatedAt + 2×TTL so a late complete/fail/cancel can still be recorded. Terminal rows stay visible until LastUpdatedAt + TTL. GetTaskAsync serves a terminal snapshot and then drops the row. Null/non-positive TTL remains unlimited until a terminal get.
  4. Sweep — insert the new snapshot first, then sweep. GetTaskAsync pulses the same throttled walk. Sweep removes only HasExpired rows.
  5. CancellationToken — observed at the start of every public method, in TryUpdate, and during the sweep walk so a cancelled caller does not finish the dictionary scan or commit.

Also adds a TimeProvider constructor (default TimeProvider.System) so TTL and sweep can be tested with FakeTimeProvider.

Tests

xUnit coverage of InMemoryMcpTaskStore is 100% line and branch, including unhappy paths (missing keys, second-window work refused / settle allowed, serve-and-drop, cancelled tokens, CAS retry). Integration tests that polled a completed task and then got it again now expect the post-drop unknown-task error; cancel is still acknowledged and does not resurrect a row.

…ows (modelcontextprotocol#1963)

Split work vs tracking windows, serve-and-drop terminal Gets, insert then
sweep, honor CancellationToken, and treat missing mutations as no-ops.

This branch has not been deployed

No deployments
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.

Bugs in InMemoryMcpTaskStore lead to poor development / testing experience

1 participant