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

ISPN-9922 New API modules #6656

Closed
wants to merge 2 commits into from
Closed

Conversation

karesti
Copy link
Contributor

@karesti karesti commented Feb 4, 2019

https://issues.jboss.org/browse/ISPN-9922

This is the first step. These modules are new, actual code should not be impacted by this work.
This PR contains:

  • New API module
  • New hotrod-client reactive module
  • Reactive key-value store with simple methods

Needs to be done - maybe not now but in a near future PR because this is very new

  • Javadocs
  • Documentation

This PR is part of an umbrella issue

@karesti karesti force-pushed the ISPN-9922 branch 3 times, most recently from 9bdbff7 to e1b3818 Compare February 5, 2019 09:30
@karesti
Copy link
Contributor Author

karesti commented Feb 5, 2019

failures not related

@karesti karesti changed the title ISPN-9922 New Reactive API ISPN-9922 New API modules Feb 5, 2019
@karesti
Copy link
Contributor Author

karesti commented Feb 5, 2019

This PR focus is adding the two new modules. APIs are not definitive at all. This will be treated in other pull requests

@karesti
Copy link
Contributor Author

karesti commented Feb 6, 2019

The failure is not related

@karesti
Copy link
Contributor Author

karesti commented Feb 7, 2019

I changed the base branch for tis PR

* New API module
* New hotrod-client reactive module
* Reactive key-value store with simple methods
@galderz
Copy link
Member

galderz commented Feb 12, 2019

I've said this @karesti before but I really want to lay it down here so that others can read:

I'd really like to see a plan on how we plan to evolve APIs over time. What recommendations should developers follow when they want to add/change/remove API methods? At which point they should come up with new interfaces and how do users migrate from one to the other? When should we create new modules? When can we reuse existing API modules?

The answers to these questions should take end user into consideration to see what makes their life easy when upgrading or changing things.

All this needs to be sketched out before deciding which APIs and which methods to include, because you're never going to get that right. So, the best way to future protect yourself against deciding between api A or B, or whether to include this or that method, is to have a clear plan on how to evolve things.

Not doing this when we started Infinispan is by far the biggest mistake we did API wise. I don't want us to repeat the same mistake again.

@karesti
Copy link
Contributor Author

karesti commented Feb 12, 2019

I've said this @karesti before but I really want to lay it down here so that others can read:

I'd really like to see a plan on how we plan to evolve APIs over time. What recommendations should developers follow when they want to add/change/remove API methods? At which point they should come up with new interfaces and how do users migrate from one to the other? When should we create new modules? When can we reuse existing API modules?

The answers to these questions should take end user into consideration to see what makes their life easy when upgrading or changing things.

All this needs to be sketched out before deciding which APIs and which methods to include, because you're never going to get that right. So, the best way to future protect yourself against deciding between api A or B, or whether to include this or that method, is to have a clear plan on how to evolve things.

Not doing this when we started Infinispan is by far the biggest mistake we did API wise. I don't want us to repeat the same mistake again.

ok.

Which concrete output would you like to see produced? A readme document?

Here is the issue related to the task: https://issues.jboss.org/browse/ISPN-9966

@galderz
Copy link
Member

galderz commented Feb 15, 2019

Which concrete output would you like to see produced? A readme document?

A section in the contribution guide. I also would like to see a separate repo with examples where we show contributors potential scenarios. E.g.

  • If you want to phase out a return type (e.g. reactivestreams APIs and use Java 9+ reactivestreams types), then do this.
  • If you want to add a new API do this.
  • If you want to add a new method, do this... (make sure it has default modifier)

@galderz
Copy link
Member

galderz commented Feb 15, 2019

It's important to do this sooner rather than later so that we know the foundations that put in place for new API is as future proof as possible (at the time of writing). I believe that unless we sit down and write these examples we'll miss things that might make our new API infrastructure not as future proof as we'd like and eventually we'll have to revisit parts in some kind of breaking change.

@galderz
Copy link
Member

galderz commented Feb 15, 2019

Btw, the moment we're based on Java 11 we should be able to use JDK's reactive streams classes.

@galderz
Copy link
Member

galderz commented Feb 15, 2019

Dealing with that would have an example when a new version of the API needs to be exposed.

@galderz
Copy link
Member

galderz commented Feb 15, 2019

Related to the topic of other APIs, are you expecting all APIs to live in the api/ module? Not sure this is a good idea from the PoV of isolating APIs and only depending on what are need.

Copy link
Member

@galderz galderz left a comment

Choose a reason for hiding this comment

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

I'm happy with the existing KeyValueStore API and I'm happy with the use of CompletionStage+Publisher. One thing I've noticed is that in Clement's document he specifies that CompletableFuture should be used as return type and here CompletionStage is used. I think the latter is better suited, but wondering why Clement mentions CompletableFuture in his reactive API doc. @karesti Can you double check with him?

I'm lacking some vision/design on how the rest of APIs would fit here, where would they go...etc. This is important from the POV of deciding whether the location of KeyValueStore API is the right one or not.

@karesti
Copy link
Contributor Author

karesti commented Feb 18, 2019

@galderz I've sent you a link with another doc

@karesti
Copy link
Contributor Author

karesti commented Feb 18, 2019

Related to the topic of other APIs, are you expecting all APIs to live in the api/ module? Not sure this is a good idea from the PoV of isolating APIs and only depending on what are need.

This is one of the things we talked about in the F2F. This is one of the strategies, we could not decide what to do without being able to see how it would potentially look. I decided to implement a first thing based on the idea we will have api jar + impl jar to use a particular API.

@karesti
Copy link
Contributor Author

karesti commented Feb 18, 2019

@galderz This first work could be experimental and just for us before promoting it to a new official way of doing things from now on in infinispan

* A Reactive Key Value Store provides a highly concurrent and distributed data structure, non blocking and using
* reactive streams.
* <p>
* TODO: Add more javadoc and examples
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this being added as part of this PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No. This PR is more about having 2 new modules

import org.infinispan.client.hotrod.configuration.ConfigurationBuilder;

/**
*
Copy link
Contributor

Choose a reason for hiding this comment

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

Docs needed


@Override
public <K, V> KeyValueStore<K, V> getKeyValueStore(String name) {
RemoteCache<K, V> cache = cacheManager.getCache(name, false);
Copy link
Contributor

Choose a reason for hiding this comment

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

Won't this throw a NPE if the ClientConfig passed to the constructor is not a instanceof ClientConfigurationLoader.ConfigurationWrapper?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

probably. this is not even tested yet, just a quick thing. I think this PR is causing more confusion than anything

}

/* TODO: Remove, visible for test now */
public void setCacheManager(RemoteCacheManager cacheManager) {
Copy link
Contributor

Choose a reason for hiding this comment

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

can be package-private if just for tests.


await(store.putMany(Flowable.fromIterable(entries)));

// store.findContinuously();
Copy link
Contributor

Choose a reason for hiding this comment

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

Remove?

<description>Infinispan Api</description>

<properties>
<version.reactivestreams>1.0.1</version.reactivestreams>
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this should be set in the build-configuration/pom.xml or pom.xml?

*/
public class InfinispanClient {

//TODO: Decide how to test and how to make this work
Copy link
Contributor

Choose a reason for hiding this comment

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

Remove?

import org.reactivestreams.Publisher;

/**
* I -> Infinispan xD
Copy link
Contributor

Choose a reason for hiding this comment

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

This might need to be a little more informative 😄

private final V value;

public KeyValueEntry(K key, V value) {

Copy link
Contributor

Choose a reason for hiding this comment

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

This is basically the same as org.infinispan.util.KeyValuePair .. if we're going to use this a lot, we should probably deprecate KeyValuePair.

Also, I can see this class being useful outside of just reactive contexts. Maybe we should put in a more generic package, such as org.infinispan.api.collections.util or just org.infinispan.api.collections, WDYT?

@galderz
Copy link
Member

galderz commented Feb 19, 2019

This is one of the things we talked about in the F2F. This is one of the strategies, we could not decide what to do without being able to see how it would potentially look. I decided to implement a first thing based on the idea we will have api jar + impl jar to use a particular API.

Fair enough...

However, I see two problems I found with this approach are:

  • How does one add a new API? Currently you'd have to modify the source API module and add your API to Infinispan object. This works if we're not interested in promoting APIs created by external users, which includes not only end users, but also consuming projects (e.g. OGM).
  • Say your API module exposes a RxJava APIs A.B.C and the user wants to use the plain KV API and it uses Rx Java APIs X.Y.Z. Such user might have issues mixing 3rd party libraries that the API brings indirectly (even though the user does not actually use them) with APIs that it uses.

@karesti You should write down the decisions/options you've made WRT API, write down the reasons why you choose that, and you should also track the potential problems. Only this way we can get a full picture of why things are the way they are and the problems we've decided not to solve.

@karesti
Copy link
Contributor Author

karesti commented Feb 19, 2019

This is one of the things we talked about in the F2F. This is one of the strategies, we could not decide what to do without being able to see how it would potentially look. I decided to implement a first thing based on the idea we will have api jar + impl jar to use a particular API.

Fair enough...

However, I see two problems I found with this approach are:

  • How does one add a new API? Currently you'd have to modify the source API module and add your API to Infinispan object. This works if we're not interested in promoting APIs created by external users, which includes not only end users, but also consuming projects (e.g. OGM).
  • Say your API module exposes a RxJava APIs A.B.C and the user wants to use the plain KV API and it uses Rx Java APIs X.Y.Z. Such user might have issues mixing 3rd party libraries that the API brings indirectly (even though the user does not actually use them) with APIs that it uses.

@karesti You should write down the decisions/options you've made WRT API, write down the reasons why you choose that, and you should also track the potential problems. Only this way we can get a full picture of why things are the way they are and the problems we've decided not to solve.

I wrote this down in the API manifesto. This PR is a previous one

@karesti karesti closed this Feb 19, 2019
@karesti
Copy link
Contributor Author

karesti commented Feb 19, 2019

closing in favor for #6690 for the first steps in the code, and the API manifesto #6678

@danberindei
Copy link
Member

danberindei commented Feb 27, 2019

I just saw @galderz's comment so I'm adding a late reply here.

  • How does one add a new API? Currently you'd have to modify the source API module and add your API to Infinispan object. This works if we're not interested in promoting APIs created by external users, which includes not only end users, but also consuming projects (e.g. OGM).

-1 from me to promote APIs created by external users, it would complicate things, and some (most?) consuming projects will want to hide the underlying caches/key-value stores anyway.

  • Say your API module exposes a RxJava APIs A.B.C and the user wants to use the plain KV API and it uses Rx Java APIs X.Y.Z. Such user might have issues mixing 3rd party libraries that the API brings indirectly (even though the user does not actually use them) with APIs that it uses.

Clement's reactive strategy proposal suggests exposing in our APIs only the Publisher from reactive streams. So the API module should only depend on reactive-streams and nothing else.

One thing I've noticed is that in Clement's document he specifies that CompletableFuture should be used as return type and here CompletionStage is used.

The newest version of the doc uses CompletionStage.

Btw, the moment we're based on Java 11 we should be able to use JDK's reactive streams classes.

The doc also suggests getPublisher() for the JDK version getRsPublisher() for the reactive-streams version. IDK if it would require multi-version jars or not, but I'm sure we can support Flow.Publisher right now.

@karesti
Copy link
Contributor Author

karesti commented Feb 28, 2019

@danberindei thank you! you are welcome to check the other two PR I've mentioned above 💃 🕺

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants