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

Revamp CreateCommits to just create Commits and add specialized Push and Rebase endpoints #43

Merged
merged 25 commits into from
Dec 4, 2023

Conversation

saquibmian
Copy link
Contributor

@saquibmian saquibmian commented Nov 30, 2023

There are two things going on in this PR:

  1. CreateCommits is updated so that it simply creates Commits for Modules without pushing them onto any Branch or assigning any Tags to them.
    • The idea is that Commits can be "uploaded" to the BSR before they are placed in their correct places in Branch history or assigned Tags. This is very useful for sync, where potentially 1000s of Commits need to be created before pushing them on a Branch. Because Branch history should be patched atomically and with a lock, creating Commits in-band becomes untenable.
    • These Commits can only be referenced by their ID, Digest, or a VCSCommitRef if there was any AssociatedVCSCommit.
  2. Two new RPCs are added to mutate a Branch's history: BranchService.Push and BranchService.Rebase.
    • Push provides no assertions on the final state of a Branch's history. This is the model that buf push currently uses, where all concurrent writes win, but the last write is king and becomes the latest commit.
    • Rebase allows the caller to assert on the final state of a Branch's history. Concurrent writes are idempotent as long as they assert the same final state. If they don't, the first write wins and all others lose. This is the model that buf sync will use.

@saquibmian saquibmian requested a review from bufdev as a code owner November 30, 2023 16:17
// returned. Additionally, each patch in the request asserts the expected state of the branch. If
// the actual state does not match the expected state, the patch is rejected and an error is
// returned.
rpc PatchBranchHistories(PatchBranchHistoriesRequest) returns (PatchBranchHistoriesResponse);
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 didn't put any idempotentcy annotations on these two RPCs yet. I think that PatchBranchHistories is IDEMPOTENT but I'm unclear on what PushCommits is. I also don't understand why CreateCommits is IDEMPOTENT... it will fail if invoked repeatedly.

@bufdev
Copy link
Member

bufdev commented Dec 1, 2023

I updated with some edits - for ease of reference, here's the entire diff: 6d72e67...ad64ae8

Some main points:

  • RPCs are now Push and Rebase.
  • The concept of "head commit" now replaces the concept of "latest commit" - latest implies time, while "head" has clearer meaning.
  • PushRequest.Value now takes mulltiple commit_ids, thereby batching a single Branch update into a single Value. This gets rid of potential duplicates, and makes it possible to have the response length match the request length. I think it's also just clearer for the caller as to what is happening.
  • Push and Rebase now just return Branches, which are the only entity that actually gets modified I believe.
  • Operation, Operation.CreateBranch, Operation.UpdateBranch are now the names of the operations on RebaseRequest. CreateBranch and UpdateBranch now nested inside Operation.
  • missing_blobs moved top-level.
  • Various other naming updates.
  • Protobuf validation put in place for repeated fields.
  • BUF_VERSION updated to v1.28.1 to make sure we are incorporating PROTOVALIDATE rules (I can't remember what the commit points to, and good to update anyways).
  • Some extra documentation spec'ing out behavior.

Please double-check that I didn't miss anything and that the comments make sense and reflect the correct behavior, but assuming I didn't miss anything this is good to go from my end (but please triple-check).

@bufdev bufdev changed the title Add Branch history mutation APIs Revamp CreateCommits to just create Commits and add specialized Push and Rebase endpoints Dec 1, 2023
buf/registry/module/v1beta1/branch_service.proto Outdated Show resolved Hide resolved
buf/registry/module/v1beta1/branch_service.proto Outdated Show resolved Hide resolved
buf/registry/module/v1beta1/branch_service.proto Outdated Show resolved Hide resolved
buf/registry/module/v1beta1/branch_service.proto Outdated Show resolved Hide resolved
// a BranchRef that refers to the same Branch. An error will be returned if any
// two BranchRefs refer to the same Branch.
repeated Value values = 1 [(buf.validate.field).repeated.min_items = 1];
}
Copy link
Member

Choose a reason for hiding this comment

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

@saquibmian do we need to support pushing to multiple branches simultaneously - push is last writer wins anyways, so maybe it's not worthwhile? If we got rid of that, we'd be able to simplify this RPC and get rid of the nested Value message entirely.

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 do not, but not supporting batching is inconsistent with the rest of the schema. Every RPC today supports batching, except the List* RPCs (which in theory could support batching trivially).

buf/registry/module/v1beta1/branch_service.proto Outdated Show resolved Hide resolved
// - If a Digest is referenced, this is interpreted to mean the latest released Commit that has this Digest.
// Digests referencing unreleased Commits cannot be referenced.
//
// TODO: what is "latest released Commit" if we now have "head Commit"?
Copy link
Member

Choose a reason for hiding this comment

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

I think we need to re-evaluate everywhere in this API we use the word "released" given our new buf sync model

Is "released" a property of a BSR commit?

  • If a BSR commit can be on multiple branches, then I don't think we can make released a property on a BSR commit (because "released" only makes sense within the context of a history).
  • If a BSR commit can only ever be on a single branch, they it would maybe be ok to model it this way

Also need to take a look at branches service and probably rename references to "release branch" to "default branch"

Copy link
Member

Choose a reason for hiding this comment

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

Yes we need to re-evaluate this

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is this something we can do separate from this PR, or do we want to formalize "released" now and rope it into this PR?

Copy link
Member

Choose a reason for hiding this comment

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

I think we should try to land this PR and save this bigger TODO for a followup

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Perfect, I'll leave this here for now and we can clean up/formalize "release" after this.

bufdev and others added 3 commits December 1, 2023 14:17
// The id of the latest Commit created on the Branch.
string latest_commit_id = 10 [
// The id of the head Commit created on the Branch.
string head_commit_id = 10 [
(buf.validate.field).required = true,
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 noticed this is required. Does this imply that an empty Branch does not exist, or should we relax this constraint?

Copy link
Member

Choose a reason for hiding this comment

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

Unless this causes a problem elsewhere, it makes sense to me that an empty branch doesn't exist because this is true in Git (a branch pointer has to point to a commit).

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 updated the docs to reflect this.

@nicksnyder
Copy link
Member

Please clean up PR description to reflect the actual implementation/names we landed on (and remove the TODO list). Basically make the PR description what the merged commit description should look like.

@saquibmian saquibmian requested a review from nicksnyder December 4, 2023 20:49
@nicksnyder
Copy link
Member

Akshay lgtm'd in Slack and Peter told me live today that minor changes are fine and don't need his re-review, so I am going to click the merge button on this.

The only changes that happened since Peter took a look were docs changes and idempotency (which Akshay reviewed).

@nicksnyder nicksnyder merged commit f17f700 into main Dec 4, 2023
6 checks passed
@nicksnyder nicksnyder deleted the smian/proposed-atomic-branch-history-api branch December 4, 2023 22:20
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.

5 participants