0068: Python asset scans belong to a retained view¶
Status: accepted for development.
Decision¶
Replace the eager Production.assets collection with
ReadSession.assets(page_size=100). The caller explicitly opens and closes
the pinned view. Traversal loads at most one asset page, using the existing
session-scoped cursor. Page size is checked at iterator creation; every
advance through buffered values checks the session lifetime. Exhausted
iterators remain exhausted. Copied asset values survive session closure.
Iterator closure never closes its session. Errors retain their existing structured exception data. The iterator adds no total limit or implicit cancellation/I/O; existing page APIs remain available for manual continuation. The view retains its SQLite snapshot until the caller closes it, so callers should close it before long host work. It is not an indefinitely pinned connection acquired by a hidden generator.
Membership becomes the typed point query Production.asset_exists(asset_id).
Remove the old collection’s traversal, length and membership implementations;
do not provide compatibility aliases. Callers that need a complete list
explicitly collect the session iterator.
ReadSession.revisions(after=0, page_size=100) applies the same lifetime and
page-size rules to ascending revision summaries. It is a finite scan of the
pinned history, rather than a live subscription. The iterator advances using
the last copied sequence, retains native errors and adds no total cap. Manual
changes_since pages and revision waiters remain available.
Rust ProductionReadSession::assets(page_size) and
revisions(after, page_size) borrow the retained view and yield fallible,
owned values. Rust prevents dropping the view while either iterator is in
use. They validate size eagerly, fetch lazily and end after a single backend
error. Low-level pages remain available. No new C ABI operation is needed.
Migration and standards impact¶
Replace tuple(production.assets) with a scan inside read_session() and
id in production.assets with production.asset_exists(id). Live point
queries and pinned scans deliberately have different consistency boundaries.
Reviewed against the contributor standards policy: this changes Python and Rust source/lifetime semantics. UUIDs, domain meaning, storage, C ABI, cursor framing and portable exchange formats remain unchanged. No external standards mapping or normalization is introduced.