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

Make proposals owned by API caller #161

Merged
merged 1 commit into from
Jul 20, 2023
Merged

Conversation

rkuris
Copy link
Collaborator

@rkuris rkuris commented Jul 19, 2023

Doing this simplifies the implementation significantly, and only adds some complexity at commit time. Also use Arc everywhere so they can be cloned and referenced by other proposals easily.

Doing this simplifies the implementation significantly, and only adds
some complexity at commit time. Also use Arc<Proposal> everywhere so
they can be cloned and referenced by other proposals easily.
Copy link
Contributor

@richardpringle richardpringle 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 have a question regarding commit that I'd like you to take a look at, but I'm good with landing these changes as is.

@@ -111,9 +115,9 @@ pub trait Db {
/// [BatchOp::Delete] operations to apply
///
async fn propose<K: KeyType, V: ValueType>(
&mut self,
self: Arc<Self>,
Copy link
Contributor

Choose a reason for hiding this comment

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

🙌

/// Commit this revision
///
/// # Return value
///
/// * A weak reference to a new historical view
async fn commit(self) -> Result<Weak<T>, Error>;
async fn commit(self) -> Result<T, Error>;
Copy link
Contributor

@richardpringle richardpringle Jul 19, 2023

Choose a reason for hiding this comment

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

What happens when two threads try to commit two conflicting proposals at the same time?
Scenario:

P1 = R1 + [Put(K1, V1)]
P2 = R1 + [Put(K2, V2)]

t0 -> P1.commit() 
t0 -> P2.commit()

Just to be clear, these are two competing but not conflicting proposals.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

You actually can't create a proposal from two different revisions, unless a commit happens between them, so I'm not sure how you are creating P1 and P2.

Copy link
Contributor

Choose a reason for hiding this comment

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

edited, should have said R1 in both cases

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

In this case, when P2 commits, it will see the base revision is not R1 (it is now R2) and will return an invalid proposal.

@@ -39,40 +38,27 @@ impl api::Db for Db {
}

async fn propose<K: KeyType, V: ValueType>(
Copy link
Contributor

Choose a reason for hiding this comment

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

Why propose on the database at all, why not limit proposal creating to be based on revisions?

Copy link
Collaborator Author

@rkuris rkuris Jul 19, 2023

Choose a reason for hiding this comment

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

Ah, because then you get the scenario above! You cannot propose anything except against the most recent version of the database or another proposal (which is based on the most recent version of the database). If you did, the proposal would immediately be invalid, so what would be the point?

Copy link
Contributor

Choose a reason for hiding this comment

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

I've talked about this on calls and on slack, just wanted to get it down in GitHub somewhere as well. We should be consistent. We either put all the onus on the user to ensure they're working with valid data OR we only allow them to create valid proposals.

Currently, we enforce valid proposal creation on the database, but don't enforce anything when creating proposals on top of proposals.

I think we could actually do both, allowing the more flexible creation of proposals on top of revisions or other proposals without validating the data through trait implementations behind a commit-only-validation feature flag.

With the feature flag off, I suggest the default behaviour is a Db::propose_on(parent: Proposal, batch: Batch) -> Proposal that validates that the parent proposal is valid before creating a new proposal.


Ok(Arc::downgrade(&proposal))
Ok(Arc::new(proposal))
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

@rkuris rkuris merged commit 9aff915 into main Jul 20, 2023
@rkuris rkuris deleted the rkuris/proposal-owned-by-caller branch July 20, 2023 15:54
rkuris added a commit that referenced this pull request Aug 1, 2023
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.

2 participants