BTW, the idea to share NetworkClient is suggested by Radai and I like this
idea.

On Wed, Feb 8, 2017 at 6:39 PM, Dong Lin <lindon...@gmail.com> wrote:

> Hey Colin,
>
> Thanks for updating the KIP. I have two followup questions:
>
> - It seems that setCreationConfig(...) is a bit redundant given that most
> arguments (e.g. topic name, partition num) are already passed to
> TopicsContext.create(...) when user creates topic. Should we pass
> the creationConfig as a parameter to TopicsContext.create(..)?
>
> - I am wondering if we should also specify the constructor of the
> AdminClient in the KIP. Previously we agreed that AdminClient should have
> its own thread to poll NetworkClient to send/receive messages. Should we
> also allow AdminClient to use an existing NetworkClient that is provided to
> the constructor? This would allow AdminClient to share NetworkClient with
> producer or consumer in order to reduce the total number of open sockets on
> both client and server.
>
> Thanks,
> Dong
>
> On Wed, Feb 8, 2017 at 5:00 PM, Colin McCabe <cmcc...@apache.org> wrote:
>
>> Hi all,
>>
>> I made some major revisions to the proposal on the wiki, so please check
>> it out.
>>
>> The new API is based on Ismael's suggestion of grouping related APIs.
>> There is only one layer of grouping.  I think that it's actually pretty
>> intuitive.  It's also based on the idea of using Futures, which several
>> people commented that they'd like to see.
>>
>> Here's a simple example:
>>
>>  > AdminClient client = new AdminClientImpl(myConfig);
>>  > try {
>>  >   client.topics().create("foo", 3, (short) 2, false).get();
>>  >   Collection<String> topicNames = client.topics().list(false).get();
>>  >   log.info("Found topics: {}", Utils.mkString(topicNames, ", "));
>>  >   Collection<Node> nodes = client.nodes().list().get();
>>  >   log.info("Found cluster nodes: {}", Utils.mkString(nodes, ", "));
>>  > } finally {
>>  >   client.close();
>>  > }
>>
>> The good thing is, there is no Try, no 'get' prefixes, no messing with
>> batch APIs.  If there is an error, then Future#get() throws an
>> ExecutionException which wraps the relevant exception in the standard
>> Java way.
>>
>> Here's a slightly less simple example:
>>
>> > AdminClient client = new AdminClientImpl(myConfig);
>> > try {
>> >   List<Future<Void>> futures = new LinkedList<>();
>> >   for (String topicName: myNewTopicNames) {
>> >     creations.add(client.topics().
>> >         setClientTimeout(30000).setCreationConfig(myTopicConfig).
>> >           create(topicName, 3, (short) 2, false));
>> >   }
>> >   Futures.waitForAll(futures);
>> > } finally {
>> >   client.close();
>> > }
>>
>> I went with Futures because I feel like ought to have some option for
>> doing async.  It's a style of programming that has become a lot more
>> popular with the rise of Node.js, Twisted python, etc. etc.  Also, as
>> Ismael commented, Java 8 CompletableFuture is going to make Java's
>> support for fluent async programming a lot stronger by allowing call
>> chaining and much more.
>>
>> If we are going to support async, the simplest thing is just to make
>> everything return a future and let people call get() if they want to run
>> synchronously.  Having a mix of async and sync APIs is just going to be
>> confusing and redundant.
>>
>> I think we should try to avoid creating single functions that start
>> multiple requests if we can.  It makes things much uglier.  It means
>> that you have to have some kind of request class that wraps up the
>> request the user is trying to create, so that you can handle an array of
>> those requests.  The return value has to be something like Map<Node,
>> Try<Value>> to represent which nodes failed and succeeded.  This is the
>> kind of stuff that, in my opinion, makes people scratch their heads.
>>
>> If we need to, we can still get some of the efficiency benefits of batch
>> APIs by waiting for a millisecond or two before sending out a topic
>> create() request to see if other create() requests arrive.  If so, we
>> can coalesce them.  It might be better to figure out if this is an
>> actual performance issue before implementing it, though.
>>
>> I think it would be good to get something out there, annotate it as
>> @Unstable, and get feedback from people building against trunk and using
>> it.  We have removed or changed @Unstable APIs in streams before, so I
>> don't think we should worry that it will get set in stone prematurely.
>> The AdminClient API should get much less developer use than anything in
>> streams, so changing an unstable API should be much easier.
>>
>> best,
>> Colin
>>
>>
>> On Wed, Feb 8, 2017, at 07:49, Ismael Juma wrote:
>> > Thanks for elaborating Jay. I totally agree that we have to be very
>> > careful
>> > in how we use our complexity budget. Easier said than done when people
>> > don't agree on what is complex and what is simple. :) For example, I
>> > think
>> > batch APIs are a significant source of complexity as you have to do a
>> > bunch
>> > of ceremony to group things before sending the request and error
>> handling
>> > becomes more complex due to partial failures (things like `Try` or other
>> > mechanisms that serve a similar role are then needed).
>> >
>> > Maybe a way forward is to write API usage examples to help validate that
>> > the suggested API is indeed easy to use.
>> >
>> > Ismael
>> >
>> > On Wed, Feb 8, 2017 at 4:40 AM, Jay Kreps <j...@confluent.io> wrote:
>> >
>> > > Totally agree on CompletableFuture. Also agree with some of the rough
>> edges
>> > > on the Consumer.
>> > >
>> > > I don't have much of a leg to stand on with the splitting vs not
>> splitting
>> > > thing, really hard to argue one or the other is better. I guess the
>> one
>> > > observation in watching us try to make good public apis over the
>> years is I
>> > > am kind of in favor of a particular kind of simple. In particular I
>> think
>> > > since the bar is sooo high in support and docs and the community of
>> users
>> > > so broad in the range of their capabilities, it makes it so there is
>> a lot
>> > > of value in dead simple interfaces that don't have a lot of conceptual
>> > > weight, don't introduce a lot of new classes or concepts or general
>> > > patterns that must be understood to use them correctly. So things like
>> > > nesting, or the Try class, or async apis, or even just a complex set
>> of
>> > > classes representing arguments or return values kind of all stack
>> > > conceptual burdens on the user to figure out correct usage. So like,
>> for
>> > > example, the Try class is very elegant and represents a whole
>> generalized
>> > > class of possibly completed actions, but the flip side is maybe I'm
>> just a
>> > > working guy who needs to list his kafka topics but doesn't know Rust,
>> take
>> > > pity on me! :-)
>> > >
>> > > Nit picking aside, super excited to see us progress on this.
>> > >
>> > > -Jay
>> > >
>> > > On Tue, Feb 7, 2017 at 3:46 PM Ismael Juma <ism...@juma.me.uk> wrote:
>> > >
>> > > > Hi Jay,
>> > > >
>> > > > Thanks for the feedback. Comments inline.
>> > > >
>> > > > On Tue, Feb 7, 2017 at 8:18 PM, Jay Kreps <j...@confluent.io> wrote:
>> > > > >
>> > > > >    - I think it would be good to not use "get" as the prefix for
>> things
>> > > > >    making remote calls. We've tried to avoid the java getter
>> convention
>> > > > >    entirely (see code style guide), but for remote calls in
>> particular
>> > > it
>> > > > > kind
>> > > > >    of blurs the line between field access and remote RPC in a way
>> that
>> > > > > leads
>> > > > >    people to trouble. What about, e.g., fetchAllGroups() vs
>> > > > getAllGroups().
>> > > > >
>> > > >
>> > > > Agreed that we should avoid the `get` prefix for remote calls.
>> There are
>> > > a
>> > > > few possible prefixes for the read operations: list, fetch,
>> describe.
>> > > >
>> > > >
>> > > > >    - I think futures and callbacks are a bit of a pain to use. I'd
>> > > second
>> > > > >    Becket's comment: let's ensure there a common use case
>> motivating
>> > > > these
>> > > > >    that wouldn't be just as easily satisfied with batch operations
>> > > (which
>> > > > > we
>> > > > >    seem to have at least for some things). In terms of flexibility
>> > > > > Callbacks >
>> > > > >    Futures > Batch Ops but I think in terms of usability it is the
>> > > exact
>> > > > >    opposite so let's make sure we have worked out how the API
>> will be
>> > > > used
>> > > > >    before deciding. In particular I think java Futures are often
>> an
>> > > > >    uncomfortable half-way point since calling get() and blocking
>> the
>> > > > > thread is
>> > > > >    often not what you want for chaining sequences of operations
>> in a
>> > > > truly
>> > > > >    async way, so 99% of people just use the future as a way to
>> batch
>> > > > calls.
>> > > > >
>> > > >
>> > > > We should definitely figure out how the APIs are going to be used
>> before
>> > > > deciding. I agree that callbacks are definitely painful and there's
>> > > little
>> > > > reason to expose them in a modern API unless it's meant to be very
>> low
>> > > > level. When it comes to Futures, I think it's important to
>> distinguish
>> > > what
>> > > > is available in Java 7 and below versus what is available from Java
>> 8
>> > > > onwards. CompletableFuture makes it much easier to compose/chain
>> > > operations
>> > > > (in a similar vein to java.util.Stream, our own Streams API, etc.)
>> and it
>> > > > gives you the ability to register callbacks if you really want to
>> > > (avoiding
>> > > > the somewhat odd situation in the Producer where we return a Future
>> _and_
>> > > > allow you to pass a callback).
>> > > >
>> > > >
>> > > > >    - Personally I don't think splitting the admin methods up
>> actually
>> > > > makes
>> > > > >    things more usable. It just makes you have to dig through our
>> > > > > hierarchy. I
>> > > > >    think a flat class with a bunch of operations (like the
>> consumer
>> > > api)
>> > > > is
>> > > > >    probably the easiest for people to grok and find things on. I
>> am
>> > > kind
>> > > > > of a
>> > > > >    dumb PHP programmer at heart, though.
>> > > > >
>> > > >
>> > > > I am not sure it's fair to compare the AdminClient with the
>> Consumer. The
>> > > > former has APIs for a bunch of unrelated APIs (topics, ACLs,
>> configs,
>> > > > consumer groups, delegation tokens, preferred leader election,
>> partition
>> > > > reassignment, etc.) where the latter is pretty specialised. For
>> each of
>> > > the
>> > > > resources, you may have 3-4 operations, it will get confusing fast.
>> Also,
>> > > > do you really think an API that has one level of grouping will mean
>> that
>> > > > users have to "dig through our hierarchy"? Or are you concerned
>> that once
>> > > > we go in that direction, there is a danger of making the hierarchy
>> more
>> > > > complicated?
>> > > >
>> > > > Finally, I am not sure I would use the consumer as an example of
>> > > something
>> > > > that is easy to grok. :) The fact that methods behave pretty
>> differently
>> > > > (some are blocking while others only have an effect after poll)
>> with no
>> > > > indication from the type signature or naming convention makes it
>> harder,
>> > > > not easier, to understand.
>> > > >
>> > > > Ismael
>> > > >
>> > >
>>
>
>

Reply via email to