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

WIP: distribution interface improvements #193

Closed

Conversation

stevvooe
Copy link
Collaborator

This commit sketches out a series of proposed interface improvements for
defining interactions between distribution components. Please see doc.go for a
general overview.

Signed-off-by: Stephen J Day stephen.day@docker.com

Connects to #159
Closes #264

@stevvooe stevvooe added this to the Registry/Future milestone Feb 20, 2015
@stevvooe
Copy link
Collaborator Author

@stevvooe stevvooe force-pushed the distribution-interfaces branch from 97d22c4 to ea39179 Compare February 20, 2015 04:34
"github.com/docker/distribution/manifest"
"golang.org/x/net/context"
)
import "golang.org/x/net/context"
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think the interface should rely on an external package like this. I see that it's used in the Registry interface below to get a repository, but wouldn't it make more sense for an implementation of Registry to decide if it's going to use x/net/context?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@jlhawn The idea here is that we subscribe to x/net/context or we don't. Really, each method should start with a context argument. Perhaps, we could refactor this interface to be transaction oriented to capture that, making context an implementation detail of the transaction.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@jlhawn Please see #156 for a discussion of this issue. No one responded.

// Exists returns true if the blob exists.
Exists(dgst digest.Digest) (bool, error)

// Get the layer identifed by digest dgst.

Choose a reason for hiding this comment

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

If I understand correctly, the name "layer" in this comment is badly chosen (should include manifests and tags too).

Copy link
Contributor

Choose a reason for hiding this comment

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

yes, the interface used to be called "LayerService", so I think the comment just wasn't updated.

@stevvooe stevvooe force-pushed the distribution-interfaces branch 2 times, most recently from bcfbdfe to 1c48e76 Compare March 3, 2015 23:43
@stevvooe
Copy link
Collaborator Author

stevvooe commented Mar 3, 2015

@jlhawn I've removed the repository field from descriptor, per our discussion in https://github.com/docker/distribution/pull/62/files#r25635220. Please update the manifest proposal accordingly.

}

// TagService provides access to information about tagged objects.
type TagService interface {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Let's simplify the tag service to be a mapping between tag name to a Descriptor.

@stevvooe stevvooe force-pushed the distribution-interfaces branch 2 times, most recently from 987b69d to a7703fd Compare March 9, 2015 21:40
@dmcgowan
Copy link
Collaborator

@stevvooe I think that is a fair way to look at it, since this is the top level interface it will likely get wrapped by the final implementations in such functionality. Let's re-address in a few weeks when we have a firmer picture of the Trust architecture, any change I would image is small or additive.

@stevvooe stevvooe force-pushed the distribution-interfaces branch 2 times, most recently from f34e3e6 to 6f6f459 Compare March 16, 2015 22:47
This commit sketches out a series of proposed interface improvements for
defining interactions between distribution components. Please see doc.go for a
general overview.

Signed-off-by: Stephen J Day <stephen.day@docker.com>
@stevvooe stevvooe force-pushed the distribution-interfaces branch from 6f6f459 to 9c28431 Compare March 16, 2015 23:28
Signed-off-by: Stephen J Day <stephen.day@docker.com>
@stevvooe stevvooe removed this from the Registry/Future milestone Mar 18, 2015
Signed-off-by: Stephen J Day <stephen.day@docker.com>
@stevvooe
Copy link
Collaborator Author

@dmcgowan Added the Namespace object.

// Scope defines the set of items that match a namespace.
type Scope interface {
// Contains returns true if the name belongs to the namespace.
Contains(name string) (bool, error)
Copy link
Collaborator

Choose a reason for hiding this comment

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

What's the case you would expect this to throw an error if its just doing a string or set comparison?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We can probably remove this. It really depends on how we define scope. If it is just a syntax-based set (ie, glob or equiv), then we don't need the error here.

What if the implementation has to ask a registry?

Copy link
Collaborator

Choose a reason for hiding this comment

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

If the Scope object needs to make a request elsewhere, its implementation is more complex than Scope should be. This should really be a simple string function, not a membership check.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Agreed.

@dmcgowan
Copy link
Collaborator

+1 to Namespace change, when do you foresee this PR getting ready to merge?

@stevvooe
Copy link
Collaborator Author

@dmcgowan When 1.6 settles, this is going to be my primary goal. Realistically, we'll have to phase these changes in. For instance, changing Registry to Namespace could be a relatively small PR.

// Index returns an IndexService that provides search across the
// namespace, supporting content discovery and collective information
// about available images.
// Index(ctx context.Context) (IndexService, error)
Copy link
Collaborator

Choose a reason for hiding this comment

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

We should take this into consideration now since we are defining the registry service as an implementation of Namespace. If namespace covers more than repositories (which I think we agree it does), then what does it mean for Registry to be a partial implementation? Should a registry throw an error when an Index is retrieved, or should Namespace be a composed type.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@dmcgowan Right now, the search/index proposal is too new. I think we can make this decision in the future. A compositional type with interfaces might make sense, but let's get a few in place before going too far.

@ncdc
Copy link

ncdc commented Apr 9, 2015

@stevvooe do you anticipate this going in for 2.0?

@stevvooe
Copy link
Collaborator Author

stevvooe commented Apr 9, 2015

@ncdc No. This will happen after 2.0.

I am going to stage the changes in, starting with the blob store and working my way up.

io.ReaderAt
io.Closer

Reader() (ReadSeekCloser, error)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@dmcgowan @tibor What do you think about removing this method completely and just supporting io.ReaderAt on blob. It allows us to abstract blobs as a series of distributed chunks and defers the io.Reader implementation to the caller (ie NewReadSeeker(length int64, blob io.ReaderAt) (io.ReadCloser, error)).

Copy link
Collaborator

Choose a reason for hiding this comment

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

Why not NewReadSeeker(blob io.ReaderAt) (io.ReadSeekCloser, error) then every read becomes a ReadAt and the underlying ReadSeeker will need to keep track of the read state.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I generally like the idea as long as we are not losing any optimizations from Seek + ReadAll

@vbatts
Copy link

vbatts commented May 6, 2015

/cc @vbatts

type BlobWriter interface {
io.WriteSeeker
io.WriterAt
io.ReaderFrom // TODO(stevvooe): This should be optional.
Copy link

Choose a reason for hiding this comment

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

can't you just not put it here, and level up with a

type BlobWriterFrom interface {
    BlobWriter
    io.ReaderFrom
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

// TODO(stevvooe): This should be optional.

io.ReaderFrom is probably the most important optimization from the client perspective. Without it either making a request per write is necessary or having an open request in which Write sends to the request body.

Copy link

Choose a reason for hiding this comment

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

Understandable. Then let's drop the comment? :-)
On May 6, 2015 9:28 AM, "Derek McGowan" notifications@github.com wrote:

In blobs.go
#193 (comment):

  • io.Closer
  • Reader() (ReadSeekCloser, error)
  • // Handler returns an HTTP handler which serves the blob content, either
  • // by redirection or directly serving the content itself.
  • Handler(r *http.Request) (http.Handler, error)
    +}

+// BlobWriter provides a handle for working with a blob store. Instances
+// should be obtained from BlobService.Writer and BlobService.Resume. If
+// supported by the store, a writer can be recovered with the id.
+type BlobWriter interface {

  • io.WriteSeeker
  • io.WriterAt
  • io.ReaderFrom // TODO(stevvooe): This should be optional.

// TODO(stevvooe): This should be optional.

io.ReaderFrom is probably the most important optimization from the client
perspective. Without it either making a request per write is necessary or
having an open request in which Write sends to the request body.


Reply to this email directly or view it on GitHub
https://github.com/docker/distribution/pull/193/files#r29775602.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@vbatts Agreed.

@stevvooe
Copy link
Collaborator Author

I believe this is being picked up by @RichardScothern.

@stevvooe stevvooe closed this Nov 12, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add golang/x/net/context.Context to storage driver method calls
9 participants