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 context to storagedriver.(Filewriter).Commit() #4109
Conversation
@@ -1338,6 +1338,7 @@ func (b *buffer) Clear() { | |||
// cleanly resumed in the future. This is violated if Close is called after less | |||
// than a full chunk is written. | |||
type writer struct { | |||
ctx context.Context |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I know this is sad. Please read the whole thread in the discussion linked in the PR description. It's also why this PR is marked as a Draft. @corhere and I wanted to chat some things through and broken code is the best place to discuss them 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That doesn't really explain it for me. Why have the context in the object instead of adding a ctx param to every method of writer that makes an s3 call?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because writer
is created in S3 driver dynamically in the (driver).Writer()
call
return d.newWriter(key, *resp.UploadId, nil), nil return d.newWriter(key, *multi.UploadId, allParts), nil
Now, it ten calls a bunch of AWS SDK funcs (that fire API reqs to AWS) that need to have context
passed down to them from the upstream consumer so they can be called etc,.. The biggest problem is the Write
method that must implement io.Writer
:
distribution/registry/storage/driver/s3-aws/s3.go
Line 1406 in d242437
if _, aErr := w.driver.S3.AbortMultipartUpload(&s3.AbortMultipartUploadInput{
And then there is also flush
which also needs the upstream context because it makes upload finalising API calls and is called from the above-mentioned Write
and from Close
(which is there to implement io.Closer
IIRC).
How else do imagine this should work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have a better solution, but I will need to read a little more code before I understand it enough to review confidently :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SGTM. I hope you don't get too horrified by all that code 😁 No rush on this one
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Had a look, apologies for just pointing at generic doc instead of reading properly the first time.
I guess this is similar to solutions like https://pkg.go.dev/github.com/dolmen-go/contextio
One thing that could be a nice addition is a test that starts a writer and then cancels it to make sure we get back a context cancellation error, but that's not blocking for me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since v3.0.0 has not been tagged, we currently have a rare opportunity to make breaking API changes. While there is nothing we can do about the standard library io.WriteCloser
interface, the driver.FileWriter
interface is under our control. Now's our chance to add a context argument to (FileWriter).Commit()
!
distribution/registry/storage/driver/storagedriver.go
Lines 123 to 126 in 915ad2d
// Commit flushes all content written to this FileWriter and makes it | |
// available for future calls to StorageDriver.GetContent and | |
// StorageDriver.Reader. | |
Commit() error |
I have spotted other candidate interfaces to be made more context-aware. But to avoid derailing this PR or expanding its scope too much, I have opened #4110 to host that discussion.
@@ -1536,7 +1537,7 @@ func (w *writer) Cancel(ctx context.Context) error { | |||
return fmt.Errorf("already committed") | |||
} | |||
w.cancelled = true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aside: does this (and the other flags) need to be be changed to atomics—in its own PR, of course—so Cancel()
is safe to be called concurrently with Write()
and friends?
This PR has got a bit chunkier. Thanks @corhere 🤣 I should probably rephrase the PR message now that we've taken a bit of a turn. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
if err := w.checkClosed(); err != nil { | ||
return err | ||
} | ||
w.closed = true | ||
ctx := context.TODO() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's always nice to see TODOs melt away.
@@ -1338,6 +1338,7 @@ func (b *buffer) Clear() { | |||
// cleanly resumed in the future. This is violated if Close is called after less | |||
// than a full chunk is written. | |||
type writer struct { | |||
ctx context.Context |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Had a look, apologies for just pointing at generic doc instead of reading properly the first time.
I guess this is similar to solutions like https://pkg.go.dev/github.com/dolmen-go/contextio
One thing that could be a nice addition is a test that starts a writer and then cancels it to make sure we get back a context cancellation error, but that's not blocking for me.
I will squash the commits before merging if that's ok with you @Jamstah There are some "broken" commits in this PR so would be good to squash them to a single one. |
Yes of course, squash away. And use a conventional commit ;) |
d925665
to
3d30611
Compare
This commit changes storagedriver.Filewriter interface by adding context.Context as an argument to its Commit func. We pass the context appropriately where need be throughout the distribution codebase to all the writers and tests. S3 driver writer unfortunately must maintain the context passed down to it from upstream so it contnues to implement io.Writer and io.Closer interfaces which do not allow accepting the context in any of their funcs. Co-authored-by: Cory Snider <corhere@gmail.com> Signed-off-by: Milos Gajdos <milosthegajdos@gmail.com>
3d30611
to
cb0d083
Compare
This PR changes
storagedriver.Filewriter
interface by addingcontext.Context
as an argument to theCommit
interface func.We pass the context appropriately where need be throughout the
distribution
codebase to all the writers and tests.In the case of the S3 storage driver we pass the
context
down to the driverwriter
and update all the AWS SDK calls in thewriter
with theirWithContext
variant. See this PR for more context (pun intended): #4066PTAL @corhere, would love to get your thoughts/ideas on this.