Conversation
| To make the implementing locking on the lfs-test-server as well as other servers | ||
| in the future easier, it makes sense to create a `lfs/lock` package that can be | ||
| depended upon from any server. This will go along with Steve's refactor which | ||
| touches the `lfs` package quite a bit. |
There was a problem hiding this comment.
I think the idea is that github.com/github/git-lfs/lfs is not a package that we want 3rd parties to use. This should be extracted to a top level package like github.com/github/git-lfs/lock. May make sense to call it github.com/github/git-lfs/lfslock so that it's obvious when callers use it:
lfslock.Lock{Path: "img/foo.psd", ...}I dont'e care about the name so much, but I do want it as a top level package under the repo.
There was a problem hiding this comment.
I agree, but I think just lock should be fine. The generic nature of that package's name is more of a concern of any code that depends on it, not the LFS client itself. If someone that depends on this package and needs a more specific name, they can just rename their import:
import (
lfslock github.com/github/git-lfs/lock
)(Addressed in a7945e0).
docs/proposals/locking.md
Outdated
| // a lock associated with the given UUID. | ||
| type UnlockRequest struct { | ||
| // UUID is the identifier of the lock that the client wishes to remove. | ||
| UUID string `json:"path"` |
|
Demoting this PR to a Pagination is a bit of a tricky subject, since there is no guarantee that a client will get all of the locks they requested if a multipage response is returned and a new lock was created while paginating through the n-th page of that response. @technoweenie and I discussed that perhaps the best way around this was to eliminate the notion of "pages" and instead make it a requirement that the server return results in a reverse-chronological ordering. Clients could instead send the last UUID that they received and the server would send them The other thing I have yet to decide upon is the filtering mechanism. The current filter definition that I proposed: type Filter struct {
// Prop is the property to search against.
Prop Property `json:"prop"`
// Value is the value that the property must take.
Value string `json:"value"`
}works well for equality operations, but fails for |
|
I like the type definitions, but I think it'd be helpful thinking about the API too. For example, I'm not sure unlocking will require a struct like this: Given an LFS base url of Also, I think the spec should recommend that server implementations keep locks for auditing purposes. This is why the unlock action is a POST to the resource, and not a DELETE. |
docs/proposals/locking.md
Outdated
| // time that the lock stopped being active. If the lock is still active, | ||
| // the server can either a) not send this field, or b) send the | ||
| // zero-value of time.Time. | ||
| ExpiresAt time.Time `json:"expired_at,omitempty"` |
There was a problem hiding this comment.
I'm not clear on how this field is intended to work. The past tense on "time that the lock stopped being active" suggests it's only for historical reporting, so it would only be filled in after the user had deliberately unlocked the file? Or, are you intending on making locks time-limited so they unlock on their own? I think the latter would cause some issues, files unlocking on a time limit could increase the likelihood of accidental parallel changes - the 'break lock' function is intended to recover from cases where a lock is left active by someone else by accident.
There was a problem hiding this comment.
I wonder if the key name should be UnlockedAt or something then? It'd likely only be shown when viewing an old lock by its UUID.
There was a problem hiding this comment.
@sinbad good point. I had mentioned to @technoweenie that I thought having a lock with a given expiry time would be tricky, since that adds an extra layer of complexity to the locking mechanism. My original intention with this field was make it so clients (and the server) would be able to determine which locks were active or not, while also maintaining a historical list of locks that had been placed for posterity.
The tense is a little weird here, so I think I'll adopt @technoweenie's suggestion and rename it to UnlockedAt, and still retain the omitempty property of the JSON tag. That way, we're not using nil as a value (by changing this field's type to *time.Time), and we have the benefit of Go's zero-type initialization that we can take advantage of with the time.IsZero method.
|
On second thought, the currently proposed filter API might be alright for V1. I'm not sure the |
9fef524 to
ce0abcf
Compare
|
Merging this. Great job finishing the proposal, time to get crackin on a prototype 🤘 |
|
Thanks, @technoweenie! Let's do it. |
This PR adds to @sinbad's original proposal and extends it to document some particular commands that we will have to teach the LFS client.
All of the documentation surrounding these new commands and API methods are in the contents of this PR, so I will keep this description brief 😄
Thanks in advance for reading! 👋