-
Notifications
You must be signed in to change notification settings - Fork 57
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
client: public API #261
client: public API #261
Conversation
@anpep Would you be able to give more context and description about what problem this change is trying to solve, and how it does that? (And specifics like why |
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 understand how this helps. The ClientMixin
still uses the concrete client type, it's just behind a method which returns a concrete *client.Client
. Can you show a small example of how this would be used to explain how it helps?
This patch, similar in spirit to canonical#238, introduces a new public API for extending the Pebble client. The basic idea behind this patch is the client mixin struct embedded in commands' structs no longer holds an instance of the Pebble-specific `client.Client` struct, but instead take a `ClientGetter` interface that implements a `Client()` method. `ClientGetter.Client()` always returns a Pebble-specific `client.Client` struct. For applications that indent to extend Pebble, this means that either the Pebble client or a new, application-specific client can be used. In the latter case, the application-specific client must implement the `ClientGetter` interface so that a Pebble-specific `client.Client` struct can always be derived by the facilities consuming the `ClientGetter` interface. The easiest way to implement this is to embed the Pebble client: type PebbleClient = client.Client type MyClient struct { *PebbleClient } Since the Pebble-specific `client.Client` is embedded, and the `ClientGetter` interface requires `Client()` to be implemented with a pointer receiver, the snippet above suffices to implement a client based off the Pebble-supplied one without much hassle, and that provides lower-level facilities for communicating with the daemon, such as `DoSync()`, `DoAsync()` and `DoAsyncFull()`.
7f49900
to
37e993b
Compare
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.
@anpep I did a detailed review as a patch on your proposal and sent it to you. I did it this way to test the proposal as its very difficult without the kernos side :)
I think the changes to export However, I don't like the Side notes: it's also weird that a new client is created even for commands that don't need it (though it looks like I wonder if instead of getting further entrenched in this hard-to-understand implicit wiring, we can create and wire up the client more directly. I think there are several ways we could do this, but I think the most obvious is just to create the client in the command's For example, consider func (c *cmdChanges) Execute(args []string) error {
// These few lines are the new code:
cl, err := client.New(clientConfigFromEnv())
if err != nil {
return err
}
defer maybePresentWarnings(cl)
// This is existing code:
changes, err := queryChanges(cl, &opts)
if err != nil {
return err
}
// ...
} The The This approach means a few lines of boilerplate in every What do you think? I have Tuesday evening meetings (EU morning time) today anyway, so I'm going to try to schedule a meeting today for us to chat further. |
Closing because this approach was ruled out (: |
This patch, similar in spirit to #238, introduces a new public API for
extending the Pebble client. The basic idea behind this patch is the client mixin
struct embedded in commands' structs no longer holds an instance of the
Pebble-specific
client.Client
struct, but instead take aClientGetter
interfacethat implements a
Client()
method.ClientGetter.Client()
always returns aPebble-specific
client.Client
struct.For applications that intend to extend Pebble, this means that either the Pebble
client or a new, application-specific client can be used. In the latter case,
the application-specific client must implement the
ClientGetter
interface sothat a Pebble-specific
client.Client
struct can always be derived by thefacilities consuming the
ClientGetter
interface. The easiest way to implementthis is to embed the Pebble client:
Since the Pebble-specific
client.Client
is embedded, and theClientGetter
interface requires
Client()
to be implemented with a pointer receiver, thesnippet above suffices to implement a client based off the Pebble-supplied one
without much hassle, and that provides lower-level facilities for communicating
with the daemon, such as
DoSync()
,DoAsync()
andDoAsyncFull()
.