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

Add persistent record storage for the DSN. #862

Merged
merged 11 commits into from
Oct 18, 2022

Conversation

shamil-gadelshin
Copy link
Contributor

This PR adds a code supporting pieces cache for the DSN. It adds a persistent implementation of the Kademlia record storage.

Changes

  • add ParityDb record storage (with BTreeIterator wrapper)
  • add put_value operation for Node
  • refactor record storage configuration

Comments

  • expiration Record field should be implemented separately

Code contributor checklist:

@shamil-gadelshin shamil-gadelshin added the networking Subspace networking (DSN) label Oct 14, 2022
@shamil-gadelshin shamil-gadelshin self-assigned this Oct 14, 2022
Copy link
Member

@nazar-pc nazar-pc left a comment

Choose a reason for hiding this comment

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

Some questions and nits.

Please try to rebase against main before opening PR and make sure all commits compile, pass checks and, ideally, all changes are as close to the final version as possible from the beginning.

crates/subspace-farmer/src/lib.rs Show resolved Hide resolved
crates/subspace-networking/src/behavior.rs Show resolved Hide resolved
crates/subspace-networking/src/create.rs Show resolved Hide resolved
Comment on lines +328 to +342
pub async fn put_value(&self, key: Multihash, value: Vec<u8>) -> Result<bool, PutValueError> {
let (result_sender, result_receiver) = oneshot::channel();

self.shared
.command_sender
.clone()
.send(Command::PutValue {
key,
value,
result_sender,
})
.await?;

Ok(result_receiver.await?)
}
Copy link
Member

Choose a reason for hiding this comment

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

I thought we discussed that we'll not have puts, instead we'll do announcements and it will be up to the target of the announcement to download and cache something or not.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We discussed it offline: I will test L2 cache using puts and later test pull solution to match "get-closest and then send add-provider" algorithm.

Comment on lines 404 to 406
error!(?err, "Can't create Parity DB record storage iterator.");

ParityDbRecordIterator::empty()
Copy link
Member

Choose a reason for hiding this comment

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

Why returning empty iterator instead of an error? Silencing these doesn't seem nice.

Copy link
Contributor

Choose a reason for hiding this comment

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

I also don't like that it doesn't fail here. You can at least discard errors and return an option as an api.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't like it either. However, libp2p interface is suboptimal here. The only alternative I see is to panic. Please, let me know whether I should panic here.

Copy link
Member

Choose a reason for hiding this comment

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

Please add TODO about this with link to upstream issue that these should be made fallible to allow more backend implementations.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Comment on lines 338 to 366
match result {
Ok(data) => {
if let Some(data) = data {
let db_rec_result = serde_json::from_slice::<ParityDbRecord>(&data);

match db_rec_result {
Ok(db_rec) => {
trace!(?key, "Record loaded successfully from DB");

Some(Cow::Owned(db_rec.into()))
}
Err(err) => {
debug!(?key, ?err, "Parity DB record deserialization error");

None
}
}
} else {
trace!(?key, "No Parity DB record for given key");

None
}
}
Err(err) => {
debug!(?key, ?err, "Parity DB record storage error");

None
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

You can match for literally any value:

match result {
    Ok(Some(data)) => {
        let db_rec_result = serde_json::from_slice::<ParityDbRecord>(&data);

        match db_rec_result {
            Ok(db_rec) => {
                trace!(?key, "Record loaded successfully from DB");

                Some(Cow::Owned(db_rec.into()))
            }
            Err(err) => {
                debug!(?key, ?err, "Parity DB record deserialization error");

                None
            }
        }
    }
    Ok(None) => {
        trace!(?key, "No Parity DB record for given key");

        None
    }
    Err(err) => {
        debug!(?key, ?err, "Parity DB record storage error");

        None
    }
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agree. This option is better. Thanks.

Comment on lines 321 to 323
let tx = vec![(self.column_id, key, data)];

let result = self.db.commit(tx);
Copy link
Contributor

Choose a reason for hiding this comment

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

Vector is heap allocated. You can use either of those instead:

self.db.commit(Some((self.column_id, key, data)));
self.db.commit(std::iter::once((self.column_id, key, data)));

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok. I will change to Option but with a separate line for it.

Copy link
Member

Choose a reason for hiding this comment

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

I believe you can also just use [] or &[], Option is not natural here even though it happens to implement IntoIterator.

Comment on lines 404 to 406
error!(?err, "Can't create Parity DB record storage iterator.");

ParityDbRecordIterator::empty()
Copy link
Contributor

Choose a reason for hiding this comment

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

I also don't like that it doesn't fail here. You can at least discard errors and return an option as an api.

@shamil-gadelshin shamil-gadelshin linked an issue Oct 17, 2022 that may be closed by this pull request
@shamil-gadelshin shamil-gadelshin merged commit f901f75 into main Oct 18, 2022
@shamil-gadelshin shamil-gadelshin deleted the dsn2-push-pieces-from-node branch October 18, 2022 11:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
networking Subspace networking (DSN)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

DSN. Add piece publishing to cache (L2) for farmers.
3 participants