[infinispan-dev] Native Infinispan Multimap support

Galder Zamarreño galder at redhat.com
Thu Apr 13 17:31:03 EDT 2017


--
Galder Zamarreño
Infinispan, Red Hat

> On 6 Apr 2017, at 11:04, Radim Vansa <rvansa at redhat.com> wrote:
> 
> On 04/06/2017 12:15 AM, Katia Aresti wrote:
>> 
>> 
>> On Wed, Apr 5, 2017 at 9:56 AM, Radim Vansa <rvansa at redhat.com 
>> <mailto:rvansa at redhat.com>> wrote:
>> 
>>   On 04/04/2017 06:40 PM, William Burns wrote:
>>> 
>>> 
>>> On Tue, Apr 4, 2017 at 11:45 AM Katia Aresti <karesti at redhat.com
>>   <mailto:karesti at redhat.com>
>>> <mailto:karesti at redhat.com <mailto:karesti at redhat.com>>> wrote:
>>> 
>>>   Hi all,
>>> 
>>>   As you probably know, Will and I are working on the vert-x
>>>   infinispan integration [1], where the primary goal is to make
>>>   infinispan the default cluster management of vert-x. (yeah!)
>>>   Vert-x needs support for an Async Multimap. Today's
>>   implementation
>>>   is a wrapper on a normal Cache where only Cache Key's are
>>   used to
>>>   implement the multi map [2].
>>>   This is not very efficient, so after trying some other
>>   alternative
>>>   implementations [3] that don't fully work (injection not
>>   working),
>>>   Will and I have come to the conclusion that it might be a good
>>>   idea to start having our own native CacheMultimap. This first
>>>   multimap won't support duplicate values on key's.
>>> 
>>>   As a quick start, the smallest multimap we need should implement
>>>   the following interface :
>>> 
>>> I agree that having a very slim API to start should be better
>>   since we
>>> know how much trouble we get into implementing a very large API like
>>> ConcurrentMap :)
>>> 
>>>   public interface CacheMultimap<K,V> {
>>> 
>> 
>>   I don't see anything async in this interface. If that's async, provide
>>   CompletableFuture return values.
>>   I am also considering if we want any fire & forget variants for these
>>   operations, but since we have to do retries to achieve consistency
>>   (and
>>   therefore we need some messages from owners to originator), I wouldn't
>>   include them.
>> 
>> 
>> Today's vert-x API calls the vertx.executeBlocking(future => cache...)
>> 
>> I considered the option of CompletableFuture, but for simplicity I 
>> suggested the basic method.
>> Today's CacheAPI makes a difference between "put" and "putAsync". 
>> Would you call the interface CacheMultimapAsync or CacheMultimap with 
>> addAsyc method ?
> 
> "In a perfect world, there will be no war or hunger, all APIs will be 
> written asynchronously and bunny rabbits will skip hand-in-hand with 
> baby lambs across sunny green meadows." (quoting Vert.x docs)
> 
> While minimalistic API is a good way to start, it shouldn't contain 
> anything we'd want to get rid of in close future. And especially since 
> the main drive for multimaps is Vert.x which consumes asynchronous APIs 
> (and has support for legacy synchronous APIs, the executeBlocking 
> method), we should have the design adapted to that from the beginning.

Amen!

> CompletableFuture is not a rocket science, and you can use the already 
> asynchronous Infinispan internals.

Indeed! 

CompletableFuture is good. 

In hindsight, I would have maybe chosen java.util.concurrent.CompletionStage since it's more flexible (interface vs class), and doesn't bring in java.util.concurrent.Future which contains blocking methods.

CompletableFuture/CompletionStage works for single returns. The bigger problem is when you want multiple returns asynchronously. Here a can of worms opens up, e.g. do you push the results? do you pull the results?

For the functional map API, we experimented with a pull model using Traversable. A push model is harder to implement and  non-trivial, and there you're getting into Rx territory.

> I don't think we should have two interfaces, I believe that single 
> interface with async methods only is absolutely sufficient.

^ I'm not so sure actually... Both sets of methods are used for different use cases. Conceptually and from a user's perspective, I'd rather have separate interfaces since I'd not expect calls to both use cases to be interleaved.

> Though I 
> wouldn't add the *Async suffix at all there. If someone wants to execute 
> the methods synchronously he can call .get() or .join() - just 6/7 
> characters more.

^ We shouldn't promote calling Future.get() for asynchronous APIs since it goes against everything that async APIs stand for ;)

> 
>> 
>>>       V put(K key,V value);
>>> 
>>> This should probably return a boolean or Void. I am leaning towards
>>> the first, but I am open either way.
>> 
>>   I would rather call this "add", as vert-x does. CompletableFuture as
>>   return type here will allow to easily register the handler
>> 
>> 
>> -1 I prefer keeping "put" name because it is still a Map and makes 
>> more sense to me considering the actual Cache API too. The return type 
>> V was a transcription mistake, it should be void for me, as Will 
>> pointed out.
> 
> To me "put" is linked with overwriting the previous value, while you add 
> to the underlying collection or create a new single-element one. But 
> whatever, I care more about the return values :)
> 
> R.
> 
>> 
>> 
>>>       Collection<V> get(K key);
>>> 
>>>       boolean remove(K key,V value);
>>> 
>>> We probably want a `boolean remove(K key)` method as well that
>>   removes
>>> all values mapped to the given key.
>> 
>>   What about "reset(key)"? 
>> 
>> 
>>>   }
>>> 
>>>   CacheMultimapImpl will be a wrapper on a normal Cache,
>>   similar to [3].
>>> 
>>>   We could add a new method in EmbeddedCacheManager.java
>>> 
>>>   <K, V> CacheMultimap<K, V> getCacheMultimap(String cacheName,
>>>   boolean createIfAbsent);
>>> 
>>> 
>>> I was thinking maybe this would exist in a separate module
>>   (outside of
>>> core)? or class that wraps (similar to DistributedExecutor) instead.
>>> My worry is about transactions, since the entry point to that is
>>> through Cache interface. The other option is we could add a
>>   `getCache`
>>> method on the `CacheMultiMap`.
>> 
>>   +1 Since the names of multimaps and maps will clash, we shouldn't hide
>>   that the underlying implementation is a Cache, so I'd suggest
>>   something like
>> 
>>   static <K, V> CacheMultimap<K, V> CacheMultimapFactory.get(Cache<K,
>>   Object> c) { ... }
>> 
>>> 
>>> 
>>>   Implementation will create a cache as always and return a new
>>>   CacheMultimapImpl(cache).
>>> 
>>>   What do you think ? Please fell free to suggest any other
>>>   alternative or idea.
>>> 
>>>   Cheers
>>> 
>>>   Katia
>>> 
>>>   [1] https://github.com/vert-x3/vertx-infinispan
>>   <https://github.com/vert-x3/vertx-infinispan>
>>> 
>>>   [2]
>>> 
>>   https://github.com/vert-x3/vertx-infinispan/blob/master/src/main/java/io/vertx/ext/cluster/infinispan/impl/InfinispanAsyncMultiMap.java
>>   <https://github.com/vert-x3/vertx-infinispan/blob/master/src/main/java/io/vertx/ext/cluster/infinispan/impl/InfinispanAsyncMultiMap.java>
>>> 
>>>   [3]
>>   https://gist.github.com/karesti/194bb998856d4a2828d83754130ed79c
>>   <https://gist.github.com/karesti/194bb998856d4a2828d83754130ed79c>
>>>   _______________________________________________
>>>   infinispan-dev mailing list
>>> infinispan-dev at lists.jboss.org
>>   <mailto:infinispan-dev at lists.jboss.org>
>>   <mailto:infinispan-dev at lists.jboss.org
>>   <mailto:infinispan-dev at lists.jboss.org>>
>>> https://lists.jboss.org/mailman/listinfo/infinispan-dev
>>   <https://lists.jboss.org/mailman/listinfo/infinispan-dev>
>>> 
>>> 
>>> 
>>> _______________________________________________
>>> infinispan-dev mailing list
>>> infinispan-dev at lists.jboss.org
>>   <mailto:infinispan-dev at lists.jboss.org>
>>> https://lists.jboss.org/mailman/listinfo/infinispan-dev
>>   <https://lists.jboss.org/mailman/listinfo/infinispan-dev>
>> 
>> 
>>   --
>>   Radim Vansa <rvansa at redhat.com <mailto:rvansa at redhat.com>>
>>   JBoss Performance Team
>> 
>>   _______________________________________________
>>   infinispan-dev mailing list
>>   infinispan-dev at lists.jboss.org <mailto:infinispan-dev at lists.jboss.org>
>>   https://lists.jboss.org/mailman/listinfo/infinispan-dev
>>   <https://lists.jboss.org/mailman/listinfo/infinispan-dev>
>> 
>> 
>> 
>> 
>> _______________________________________________
>> infinispan-dev mailing list
>> infinispan-dev at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/infinispan-dev
> 
> 
> -- 
> Radim Vansa <rvansa at redhat.com>
> JBoss Performance Team
> 
> _______________________________________________
> infinispan-dev mailing list
> infinispan-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/infinispan-dev




More information about the infinispan-dev mailing list