Skip to content

Conversation

michalkucharczyk
Copy link

@michalkucharczyk michalkucharczyk commented Sep 23, 2025

Refactor TrieDBMut to avoid implicit commit on drop.

This PR refactors the TrieDBMut implementation to provide better control over when changes are committed to the database.

Changes:

  • TrieDBMut was split into two components:
    • TrieDBMutBase: core trie functionality without automatic commit on drop,
    • CommitOnDrop: a wrapper that provides the original auto-commit on drop behavior,
    • TrieDBMut is now a type alias for CommitOnDrop to maintain backward compatibility,
  • Added build_base() method to TrieDBMutBuilder that creates a TrieDBMutBase instance for cases where commit on drop is undesired.

Part of: paritytech/polkadot-sdk#6020

[package]
name = "trie-db"
version = "0.30.0"
version = "0.31.0"
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: I generally prefer having a dedicated "chore" release PR with no/minimal changes, we'll also need to add this PR to the trie-db changelog 🤔

Copy link
Author

@michalkucharczyk michalkucharczyk Sep 23, 2025

Choose a reason for hiding this comment

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

well, just copied the "modus operandi" from some other commit in this repo :), which makes a change and bumps version.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think that works too, proly need a few more bumps? 🤔

///
/// Note that no changes are committed to the database until `commit` is called.
///
/// Querying the root or dropping the instance will commit automatically.
Copy link
Contributor

@lexnv lexnv Sep 23, 2025

Choose a reason for hiding this comment

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

Is the fn root() ++ fn drop() a noop in case no keys were added in-between?

In other words:

let mut trie = CommitOnDrop..;

trie.insert(key, val);

// T0. At this point we perform a `commit` under the hood?
let root = trie.root();

// T1. Do we redo the `commit` at this point although the trie is already commited and it suffered no changes?
drop(trie);

Copy link
Author

Choose a reason for hiding this comment

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

drop always calls commit, exactly as it was before this PR.

Copy link
Author

Choose a reason for hiding this comment

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

and, yeah commit should be no-op at least from what I understand.

Copy link
Contributor

@lexnv lexnv left a comment

Choose a reason for hiding this comment

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

LGTM! I think we can add the release to a dedicated PR and tiny question around the root ++ commit op 🙏

/// implicitly.
///
/// Refer to [`TrieDBMutBase`] for `Trie` implementation that does not perform `commit` on `drop`.
pub type TrieDBMut<'a, L> = CommitOnDrop<'a, L>;
Copy link
Contributor

Choose a reason for hiding this comment

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

Did you point polkadot-sdk to this branch an confirm everything still properly compiles, to make sure no unpleasant surprises appear after merge.

Copy link
Author

Choose a reason for hiding this comment

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

Yes. But we still need to release and bump version in polkadot-sdk, so we have time to handle surprises.


impl<'a, L> TrieDBMut<'a, L>
/// Wrapper around [`TrieDBMutBase`] that commits changes on drop.
pub struct CommitOnDrop<'a, L: TrieLayout>(TrieDBMutBase<'a, L>);
Copy link
Contributor

Choose a reason for hiding this comment

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

The naming here could be better CommitOnDrop doesn't tell you much this is still a TrieDbMutWithCommitOnDrop.

Copy link
Author

Choose a reason for hiding this comment

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

Basically this one one-liner type is self-explanatory, but, yeah I can make it longer if you wish so. There is also legacy alias which is supposed to be used.

{
fn drop(&mut self) {
self.commit();
self.0.commit();
Copy link
Contributor

Choose a reason for hiding this comment

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

Personally, I would've just went with a flag here on TrieDbMut, commit_on_drop,

if commit_on_drop self.0.commit(),

Copy link
Author

Choose a reason for hiding this comment

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

Yes, that's also a way to go. Somehow I concluded that typed approach will be more explicit.

Still can change this, any other opinions on this? (@lexnv @skunert)

Copy link

Choose a reason for hiding this comment

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

I think both are fine, but I tend to lean towards flag approach. Simply because it should be less code to digest and inspect. And as reader a commit_on_drop flag is kind of easy to understand. Ofc default should keep the old behaviour.

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.

4 participants