-
Notifications
You must be signed in to change notification settings - Fork 13.9k
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
KAFKA-6018: Make KafkaFuture.Future an interface #4033
Conversation
cc @cmccabe |
Yes it does. As discussed in KAFKA-6018 the interface is marked as
If you want I can create a KIP for this. But is this change big enough for this? |
Yeah, a KIP is definitely required for any change with compatibility impact. And we can't do it until Kafka 2.0. We will definitely drop support for Java 7 by then and if we are going to break compatibility, we should take that into account as well. |
So you propose me to create a KIP, or wait with the KIP for Kafka 2.0? Btw, Java 8 is not required for this, so from that perspective it does not need to be lined up with the deprecation of Java 7. |
You can propose the KIP now, that's independent of the release where the code change is included. I understand that Java 8 is not required for this. My point is that if we have to break compatibility and we can rely on Java 8 classes, then the solution may be different than if we can't rely on Java 8 classes. For example, |
How about just creating a new interface, which |
@cmccabe I think you'd have to have methods that take the new interface as the parameter instead of the existing abstract class. |
You could add a separate function overload which took the interface, rather than the concrete class. Then we could deprecate the variant which took the concrete class. |
Yeah, that's a possibility and the kind of thing that should be in the KIP. |
6c630af
to
7f5396f
Compare
Just updated the pull request, so the change becomes a backwards compatible change. This is now all tracked under KIP-218 |
ea745e6
to
693ac25
Compare
/** | ||
* A function which takes objects of type A and returns objects of type B. | ||
* | ||
* Replaced by {@link FunctionInterface}. |
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.
You need an @deprecated
javadoc tag here as well as the annotation.
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.
Missed it, update coming.
public abstract <R> KafkaFuture<R> thenApply(FunctionInterface<T, R> function); | ||
|
||
/** | ||
* @see KafkaFuture#thenApply(FunctionInterface) |
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.
You need an @deprecated
javadoc tag here as well as the annotation.
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.
Ack
KafkaFutureImpl<R> future = new KafkaFutureImpl<R>(); | ||
addWaiter(new Applicant<>(function, future)); | ||
return future; | ||
} | ||
|
||
/** | ||
* @See KafkaFutureImpl#thenApply(FunctionInterface) |
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.
You need an @deprecated
javadoc tag here as well as the annotation.
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.
Ack
public <R> KafkaFuture<R> thenApply(Function<T, R> function) { | ||
return thenApply((FunctionInterface<T, R>) function); | ||
} | ||
|
||
@Override | ||
protected synchronized void addWaiter(BiConsumer<? super T, ? super Throwable> action) { |
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.
For this to be useful to me in my work on KIP-183 I also need addWaiter()
to be made public
on KafkaFuture
.
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.
Ok, I will take it in this commit.
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.
First pass review.
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.
Thanks for the review Tom. Adapting my changes in the coming minutes.
/** | ||
* A function which takes objects of type A and returns objects of type B. | ||
* | ||
* Replaced by {@link FunctionInterface}. |
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.
Missed it, update coming.
public abstract <R> KafkaFuture<R> thenApply(FunctionInterface<T, R> function); | ||
|
||
/** | ||
* @see KafkaFuture#thenApply(FunctionInterface) |
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.
Ack
KafkaFutureImpl<R> future = new KafkaFutureImpl<R>(); | ||
addWaiter(new Applicant<>(function, future)); | ||
return future; | ||
} | ||
|
||
/** | ||
* @See KafkaFutureImpl#thenApply(FunctionInterface) |
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.
Ack
public <R> KafkaFuture<R> thenApply(Function<T, R> function) { | ||
return thenApply((FunctionInterface<T, R>) function); | ||
} | ||
|
||
@Override | ||
protected synchronized void addWaiter(BiConsumer<? super T, ? super Throwable> action) { |
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.
Ok, I will take it in this commit.
693ac25
to
b63e0df
Compare
Looks good overall (and good call, @tombentley , on the missing deprecated annotations) |
@steven-aerts someone just pointed this out to me. I was about to suggest we make the |
b63e0df
to
b953654
Compare
The Kafka streams project in this repo already has both of these functional interfaces with identical signatures
Ideally, the project would just use the JDK8 interfaces and not redefine it's own implementations. AFAIK, the next major version of Kafka is dropping JDK7 support anyway.
If JDK7 compatibility is still required for future versions of Kafka, then you can't use those. Even then there's no good reason to have redundant identical versions of BiConsumer/Function in the Kafka code base. The Kafka Streams API has several function types that have identical JDK8 versions. Ideally, the Kafka project would just use the JDK8 versions for all of these:
|
* Returns a new KafkaFuture with the same result or exception as this future, that executes the given action | ||
* when this future completes. | ||
* | ||
* When this future is id done, the given action is invoked with the result (or null if none) and the exception |
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.
extraneous id
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.
Ack
* exceptionally with the supplied action's exception. | ||
* Or, if this future completed exceptionally and the supplied action throws an exception, then the returned future | ||
* completes exceptionally with this future's exception. | ||
* |
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.
For completeness I would add
The action may be invoked by the thread that calls {@code whenComplete} or it may be invoked
by the thread that completes the future.
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.
and also add it to thenApply while we're at it
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.
Ack, will update the PR.
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.
@kurtostfeld I see your point that the streams library has interfaces with a
signature equal to the FunctionInterface
and the BiConsumer
.
I still propose to keep them separate and stick to the current proposal of the
KIP for the following reasons:
- The names used in the kafka streams for those interfaces are very use
case specific, e.g.#whenComplete(ForeachAction)
sounds rather strange to me. - To prevent a circular dependency those interfaces have to be moved to a different jar.
- The interfaces we define now are inner class interfaces, so it is clear that they are linked to KafkaFuture.
I totally agree that once JDK7 is dropped we have to migrate to standard java classes.
I think this is rather easy to do this in a backwards compatible way, by letting the kafka
specific classes implement the JDK8 classes. So KafkaFuture.BiConsumer
will then
implement the java.util.function.BiConsumer
and KafkaFuture could then implement
CompletableFuture
. But that is for me all work to be done under KIP-118.
* Returns a new KafkaFuture with the same result or exception as this future, that executes the given action | ||
* when this future completes. | ||
* | ||
* When this future is id done, the given action is invoked with the result (or null if none) and the exception |
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.
Ack
* exceptionally with the supplied action's exception. | ||
* Or, if this future completed exceptionally and the supplied action throws an exception, then the returned future | ||
* completes exceptionally with this future's exception. | ||
* |
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.
Ack, will update the PR.
b953654
to
2742184
Compare
Just updated the commit to take in the latest review comments of xavier fixed one of my own in the code of colin. |
Thank you for the reply. Two quick follow on comments:
|
@kurtostfeld even if the interfaces have the same signatures, I think the specific naming in streams helps clarify the intent. And for someone using Java 8 lambdas, the name doesn't really matter, so renaming interfaces in this context seems a bit counterproductive and does not provide much value other than deduplicating the BiConsumer signature. Until we drop support for JDK7, I think it's simpler to keep things as is and revisit the APIs at that point. |
The KIP for this PR was accepted. @xvrl can you merge this PR? Or do you still see some work which needs to be done? |
Looks good to me. We need a committer to merge it though.
…On Mon, Dec 18, 2017 at 11:46 PM Steven Aerts ***@***.***> wrote:
The KIP for this PR was accepted.
@xvrl <https://github.com/xvrl> can you merge this PR? Or do you still
see some work which needs to be done?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#4033 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAxwK8RNJkYfBaux9MhWe7HCEyyR8Asmks5tB2nSgaJpZM4PwSeD>
.
|
Interestingly, when using Java's
Prints this:
In other words, the exception thrown by the So I think your exception handling here is reasonable (because it matches up with what people will expect from CF) |
+1 (non-binding) |
@ijuma are we waiting on anything from you to +1 this? I would like to see this merged for the next release. |
@steven-aerts, it looks like @ijuma mentioned a few minor things he'd like to get addressed:
See the KIP discussion thread for more details. Once those are addressed we can get this merged. |
Replace the abstract class KafkaFuture.Function with an interface, so it becomes a java 8 @FuncionalInterface and can be used with a lambda.
2742184
to
ea10060
Compare
LGTM, merging to trunk for 1.1.0. Thanks for the contribution @steven-aerts! |
Changing KafkaFuture.Future and KafkaFuture.BiConsumer into an interface makes
them a functional interface. This makes them Java 8 lambda compatible.