Skip to content

Remove the broken read-only get() accessors behind experimental-api-5 - #1343

Merged
cberner merged 1 commit into
masterfrom
claude/remove-readonly-accessors-api-5
Aug 9, 2026
Merged

cberner merged 1 commit into
masterfrom
claude/remove-readonly-accessors-api-5

Conversation

@cberner

@cberner cberner commented Aug 9, 2026 •

Copy link
Copy Markdown
Owner

Follow-up to #1306; companion to #1307, which adds deprecation notices for default-feature builds.

Change

The inherent ReadOnlyTable::get() and ReadOnlyMultimapTable::get() return 'static guards and iterators that, contrary to their documentation, do not keep the read transaction alive: holding one after dropping the ReadTransaction lets a concurrent writer reclaim the referenced pages, which panics the writer's commit() on a debug assertion.

redb 5 will drop them in favor of the Readable* trait accessors (zero cost, lifetime-bound) and the _owned() variants from #1306. This PR previews that removal under experimental-api-5, the same way the KeyRange change already removed the inherent range() methods under the flag: the two get() methods do not exist when it is enabled, and calls resolve to the trait accessor instead.

Supporting changes:

  • get_owned() previously delegated to the removed methods; it now goes through the tree directly / a private get_inner() helper, matching how range_owned routes through the private range_in_bounds().
  • Tests that read through the inherent methods incidentally keep their get() calls, which resolve to the non-'static trait accessor under the feature. Files that didn't have ReadableTable in scope gain a cfg-gated import; the redb-derive tests, which cannot cfg on redb's features, import it under #[allow(unused_imports)] since the inherent method shadows it on default features. get_arc_lifetime, which exercises the removed behavior itself, switches to get_owned() under the feature like range_arc already does.
  • Since CI builds with --all-features, CI no longer compiles or runs the two methods after this change; they remain in default-feature builds until redb 5.

Testing

  • cargo test --all --all-features passes; the arc-lifetime tests also pass under default features
  • clippy (default and --all-features), fmt, and cargo doc are clean under --deny warnings

🤖 Generated with Claude Code

https://claude.ai/code/session_01YCYPuM4nb94pF36ZX7R8sa

@codecov

codecov Bot commented Aug 9, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.02%. Comparing base (aa17d12) to head (231368b).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1343      +/-   ##
==========================================
- Coverage   91.02%   91.02%   -0.01%     
==========================================
  Files          37       37              
  Lines       18146    18220      +74     
==========================================
+ Hits        16518    16584      +66     
- Misses       1628     1636       +8     
Files with missing lines Coverage Δ
src/multimap_table.rs 94.43% <100.00%> (+0.02%) ⬆️
src/table.rs 83.95% <100.00%> (-0.70%) ⬇️
src/transactions.rs 88.95% <ø> (ø)
src/tree_store/page_store/header.rs 96.35% <ø> (ø)

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@cberner cberner left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Apply my comments to all the other locations too. Also, don't we need to remove the broken range() method?

Comment thread src/multimap_table.rs Outdated
Comment on lines +1136 to +1138
///
/// This method does not exist when the `experimental-api-5` feature is enabled, and will be
/// removed in redb 5. Use [`ReadableMultimapTable::get()`] or [`Self::get_owned()`] instead.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Don't add this

Comment thread tests/check_integrity_nondurable.rs Outdated
let table = read.open_table(TABLE).unwrap();
assert_eq!(table.len().unwrap(), 5);
assert!(table.get(&999u64).unwrap().is_none());
assert!(table.get_owned(&999u64).unwrap().is_none());

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

A lot of these don't need to be converted -- they can just use the non-'static version

@cberner
cberner force-pushed the claude/remove-readonly-accessors-api-5 branch from 8d5a8b0 to 335a211 Compare August 9, 2026 04:18
@cberner cberner changed the title Remove the broken read-only accessors behind experimental-api-5 Remove the broken read-only get() accessors behind experimental-api-5 Aug 9, 2026

cberner commented Aug 9, 2026

Copy link
Copy Markdown
Owner Author

Applied both comments to all locations in 335a211: the doc notes are gone from both get() methods, and the tests keep plain get() calls that resolve to the non-'static trait accessor under the feature (via a cfg-gated ReadableTable import; the redb-derive tests use explicit ReadableTable::get(&table, ...) since they can't cfg on redb's features).

On range(): it's already removed under the flag — the KeyRange change (76365a3) put #[cfg(not(feature = "experimental-api-5"))] on the inherent ReadOnlyTable::range() and ReadOnlyMultimapTable::range(). That's why this PR shrank to the get() half after rebasing; title and description updated to match.


Generated by Claude Code

let read_txn = db.begin_read().unwrap();
let table = read_txn.open_table(table_def).unwrap();
let retrieved = table.get(1).unwrap().unwrap();
let retrieved = ReadableTable::get(&table, 1).unwrap().unwrap();

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Why is this explicit syntax necessary?? I don't like it

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

It isn't, dropped in 4a0d673 — plain table.get(...) everywhere now. The reason it existed: redb-derive can't cfg on redb's features, and on default features the inherent 'static get() shadows the trait method, leaving a plain use redb::ReadableTable unused (which -Dwarnings rejects). The import now carries #[allow(unused_imports)] with a comment instead, and the call sites stay untouched.


Generated by Claude Code

@cberner
cberner force-pushed the claude/remove-readonly-accessors-api-5 branch from 335a211 to 4a0d673 Compare August 9, 2026 04:52
Comment thread tests/backward_compatibility.rs Outdated
Comment on lines +2 to +3
// With experimental-api-5 the inherent 'static get() does not exist, so calls resolve to the
// trait method

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Remove this. And in the other imports too

The inherent ReadOnlyTable::get() and ReadOnlyMultimapTable::get()
return 'static guards and iterators that, contrary to their
documentation, do not keep the read transaction alive. Holding one
after dropping the ReadTransaction lets a concurrent writer reclaim
the pages it references, which panics the writer's commit() on a debug
assertion.

redb 5 will drop them in favor of the Readable* trait accessors (no
cost, lifetime-bound) and the get_owned() variants (reference counted,
keep the transaction alive). Preview that removal under the
experimental-api-5 feature, like the KeyRange change already does for
the inherent range() methods: the two get() methods do not exist when
it is enabled, and calls resolve to the trait accessor instead.

get_owned() previously delegated to the removed methods, so route it
through the tree and a private get_inner() helper instead. Tests that
read through the inherent methods incidentally keep their get() calls,
resolving to the non-'static trait accessor under the feature;
get_arc_lifetime, which exercises the removed behavior itself, switches
to get_owned() under the feature like range_arc already does.

Assisted-by: Claude Code <noreply@anthropic.com>

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YCYPuM4nb94pF36ZX7R8sa
@cberner
cberner force-pushed the claude/remove-readonly-accessors-api-5 branch from 4a0d673 to 231368b Compare August 9, 2026 13:48
@cberner
cberner merged commit 4182849 into master Aug 9, 2026
8 checks passed
@cberner
cberner deleted the claude/remove-readonly-accessors-api-5 branch August 9, 2026 14:15
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