You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Refresh the first page when draining paginated listings
The SEP-2549 response cache (2026-07-28) can serve a list verb's first
page from cache, while continuation pages always go to the wire. A drain
that started from a cached first page would pair that page's stale cursor
with freshly fetched later pages and return a listing the server never
served, which is the same silent-wrong-list failure the drains exist to
prevent.
The four list_all_* / iter_all_* pairs now take cache_mode and default it
to "refresh" rather than inheriting the single-page "use", so a drain
always starts from a current first page. "refresh" still writes that page
back to the cache, so single-page callers keep the freshness-hint benefit.
Pass cache_mode="use" to accept a cached first page instead.
The existing drain tests run with mode="legacy", where the ttlMs hint is
stripped on the wire and nothing is ever cached, so the two new tests run
on the default 2026-07-28 path.
AI disclosure: developed with AI assistance (Claude, Opus 5).
Copy file name to clipboardExpand all lines: docs/advanced/pagination.md
+21Lines changed: 21 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -71,6 +71,27 @@ That loop is the same one in every client that pages, so `Client` ships it. The
71
71
repeats. A repeated cursor is a broken server, and a loud failure beats a silent hang or a
72
72
half-read list.
73
73
74
+
### Drains and the response cache
75
+
76
+
A server may attach a `ttlMs` freshness hint to a list result (**[Caching](../client/caching.md)**), and the
77
+
client will serve a later `list_*` call for that method from cache instead of going back to the
78
+
server. Only the first page is ever cached; a call carrying a cursor always goes to the wire.
79
+
80
+
That split matters for a drain. If it started from a cached first page, it would take that
81
+
page's `next_cursor` — minted against a listing that may since have changed — and pair it with
82
+
freshly fetched later pages, returning a stitched-together listing the server never served. So
83
+
the drains default to `cache_mode="refresh"`: the first page is re-fetched, and the fresh copy
84
+
is written back to the cache for later single-page callers.
85
+
86
+
```python
87
+
asyncdeflist_the_tools(client: Client) -> None:
88
+
fresh =await client.list_all_tools() # re-fetches the first page: always current
89
+
saved =await client.list_all_tools(cache_mode="use") # one fewer request, may be stale
90
+
```
91
+
92
+
Pass `cache_mode="use"` when you would rather have the saved copy than the current one. The
93
+
single-page `list_*` methods still default to `"use"`, unchanged.
94
+
74
95
## The three rules
75
96
76
97
**Cursors are opaque.** A client must never parse, build, or guess one. The only legal source of a cursor is the previous page's `next_cursor`, verbatim.
0 commit comments