Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: share SnapshotProvider through ProviderFactory #5249

Merged
merged 14 commits into from
Nov 14, 2023

Conversation

joshieDo
Copy link
Collaborator

  • Adds a shared SnapshotProvider to ProviderFactory & DatabaseProvider
  • Share it to all reth components on boot-up

@joshieDo joshieDo added C-enhancement New feature or request A-static-files Related to static files labels Oct 31, 2023
@@ -295,7 +295,9 @@ impl<Ext: RethCliExt> NodeCommand<Ext> {
let head = self.lookup_head(Arc::clone(&db)).wrap_err("the head block is missing")?;

// setup the blockchain provider
let factory = ProviderFactory::new(Arc::clone(&db), Arc::clone(&self.chain));
let (highest_snapshots_tx, highest_snapshots_rx) = watch::channel(None);
let factory = ProviderFactory::new(Arc::clone(&db), Arc::clone(&self.chain))
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

am i correct to understand that this will be shared across all components that might create providers?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

through blockchain_db

Copy link
Collaborator

Choose a reason for hiding this comment

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

yes

Copy link
Collaborator

@mattsse mattsse left a comment

Choose a reason for hiding this comment

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

It's getting a bit harder for me to maintain an overview of all components and how they'll fit together.
we need a proper overview and docs.

The Snapshotter::new needs more docs, unclear what the watch channel does.

after having a closer look at how the channel is currently used
do we care if the value changed or if is sufficient to just get the current highest snapshot?

because this is essentially an Rwlock that keeps track of changes

Comment on lines +41 to +42
/// Snapshot Provider
snapshot_provider: Option<Arc<SnapshotProvider>>,
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think this is a reasonable location for the snapshot integration, otherwise we'd need to integrate it into the BlockchainProvider, which I guess would also be suitable.

@joshieDo
Copy link
Collaborator Author

joshieDo commented Nov 1, 2023

ref #5270 <- overview docs

@joshieDo
Copy link
Collaborator Author

joshieDo commented Nov 1, 2023

do we care if the value changed or if is sufficient to just get the current highest snapshot?

It should be sufficient to get the current one. Even if a new one comes the moment i'm reading the old one, it just means that the new snapshot files were just created. Data hasn't been deleted yet, that's the Pruners job after it gets the very same notification.

@@ -1071,6 +1071,7 @@ impl<DB: Database, EF: ExecutorFactory> BlockchainTree<DB, EF> {
let provider = DatabaseProvider::new_rw(
self.externals.db.tx_mut()?,
self.externals.chain_spec.clone(),
None,
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't like that this extra argument is now required

@@ -295,7 +295,9 @@ impl<Ext: RethCliExt> NodeCommand<Ext> {
let head = self.lookup_head(Arc::clone(&db)).wrap_err("the head block is missing")?;

// setup the blockchain provider
let factory = ProviderFactory::new(Arc::clone(&db), Arc::clone(&self.chain));
let (highest_snapshots_tx, highest_snapshots_rx) = watch::channel(None);
Copy link
Collaborator

Choose a reason for hiding this comment

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

where does the sender go here, looks unused now.

I think we should consider hiding this channel and move instantiation to the Snapshotter instead, it can keep both halfs and return a new receiver on demand

Copy link
Collaborator

Choose a reason for hiding this comment

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

let _snapshotter = reth_snapshot::Snapshotter::new(
db,
self.chain.clone(),
self.chain.snapshot_block_interval,
highest_snapshots_tx,
);

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

i think it still makes sense to move it inside

crates/snapshot/src/snapshotter.rs Outdated Show resolved Hide resolved
crates/snapshot/src/snapshotter.rs Outdated Show resolved Hide resolved
crates/storage/provider/src/providers/snapshot/manager.rs Outdated Show resolved Hide resolved

/// SnapshotProvider
#[derive(Debug, Default)]
pub struct SnapshotProvider {
/// Maintains a map which allows for concurrent access to different `NippyJars`, over different
/// segments and ranges.
map: DashMap<(BlockNumber, SnapshotSegment), LoadedJar>,
/// Tracks the latest and highest snapshot of every segment.
highest_tracker: Option<watch::Receiver<Option<HighestSnapshots>>>,
Copy link
Collaborator

Choose a reason for hiding this comment

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

can we reuse HighestSnapshotsTracker here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

that would mean adding tokio as a dependency to primitives, and I didn't want to add that tbh

Copy link
Collaborator

Choose a reason for hiding this comment

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

that would mean adding tokio as a dependency to primitives

sorry I don't understand, HighestSnapshotsTracker is in reth-snapshot crate that we already use as a dependency in reth-provider, no?

joshieDo and others added 3 commits November 13, 2023 11:40
Co-authored-by: Alexey Shekhirin <a.shekhirin@gmail.com>
Co-authored-by: Alexey Shekhirin <a.shekhirin@gmail.com>
Co-authored-by: Alexey Shekhirin <a.shekhirin@gmail.com>
Copy link
Collaborator

@mattsse mattsse left a comment

Choose a reason for hiding this comment

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

suggesting to replace the watch channel with SnapshotTracker {Arc<Rwlock>} wrapper type

crates/snapshot/src/snapshotter.rs Show resolved Hide resolved
Comment on lines +113 to 116
let _ = self.highest_snapshots_notifier.send(Some(self.highest_snapshots)).map_err(|_| {
warn!(target: "snapshot", "Highest snapshots channel closed");
});
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

this error can safely be ignored because it's kept open by having both as fields

highest_snapshots: HighestSnapshots,
highest_snapshots_tracker: watch::Sender<Option<HighestSnapshots>>,
/// Channel sender to notify other components of the new highest snapshots
highest_snapshots_notifier: watch::Sender<Option<HighestSnapshots>>,
Copy link
Collaborator

Choose a reason for hiding this comment

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

do we expect features that need to listen for changed snapshots?

if not perhaps we could just use an rwlock wrapper type? because a watch channel is also just an rwlock with some add ons.

if we need listeners for snapshots we can add this separately

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yeah, agree. i'll do it in a further PR if that's okay

Copy link
Collaborator

@mattsse mattsse left a comment

Choose a reason for hiding this comment

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

lgtm,

okay with doing the rwlock refactor separately.

pending @shekhirin

@@ -295,7 +295,9 @@ impl<Ext: RethCliExt> NodeCommand<Ext> {
let head = self.lookup_head(Arc::clone(&db)).wrap_err("the head block is missing")?;

// setup the blockchain provider
let factory = ProviderFactory::new(Arc::clone(&db), Arc::clone(&self.chain));
let (highest_snapshots_tx, highest_snapshots_rx) = watch::channel(None);
let factory = ProviderFactory::new(Arc::clone(&db), Arc::clone(&self.chain))
Copy link
Collaborator

Choose a reason for hiding this comment

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

yes

@joshieDo joshieDo added this pull request to the merge queue Nov 14, 2023
Merged via the queue into main with commit d21e346 Nov 14, 2023
25 checks passed
@joshieDo joshieDo deleted the joshie/db-snap-provider branch November 14, 2023 18:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-static-files Related to static files C-enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants