All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.infinispan.commons.api.functional.FunctionalMap Maven / Gradle / Ivy

There is a newer version: 9.1.7.Final
Show newest version
package org.infinispan.commons.api.functional;

import org.infinispan.commons.api.functional.EntryView.ReadEntryView;
import org.infinispan.commons.api.functional.EntryView.ReadWriteEntryView;
import org.infinispan.commons.api.functional.EntryView.WriteEntryView;
import org.infinispan.commons.api.functional.Listeners.ReadWriteListeners;
import org.infinispan.commons.api.functional.Listeners.WriteListeners;
import org.infinispan.commons.marshall.MarshallableFunctions;
import org.infinispan.commons.util.Experimental;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentMap;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * Top level functional map interface offering common functionality for the
 * read-only, read-write, and write-only operations that can be run against a
 * functional map asynchronously.
 *
 * 

Lambdas passed in as parameters to functional map methods define the * type of operation that is executed, but since lambdas are transparent to * the internal logic, it was decided to separate the API into three types * of operation: read-only, write-only, and read-write. This separation helps * the user understand the group of functions and their possibilities. * *

This conscious decision to separate read-only, write-only and * read-write interfaces helps type safety. So, if a user gets a read-only * map, it can't write to it by mistake since no such APIs are exposed. * The same happens with write-only maps, the user can only write and cannot * make the mistake of reading from the entry view because read operations * are not exposed. * *

Lambdas passed in to read-write and write-only operations, when * running in a cluster, must be marshallable. One option to do so is to * mark them as being {@link java.io.Serializable} but this is expensive * in terms of payload size. Alternatively, you can provide an Infinispan * {@link org.infinispan.commons.marshall.Externalizer} for it which * drastically reduces the payload size. Marshallable lambdas for some of * the most popular lambda functions used by {@link ConcurrentMap} and * javax.cache.Cache are available via the * {@link MarshallableFunctions} helper class. * *

Being an asynchronous API, all methods that return a single result, * return a {@link CompletableFuture} which wraps the result. To avoid * blocking, it offers the possibility to receive callbacks when the * {@link CompletableFuture} has completed, or it can be chained or composes * with other {@link CompletableFuture} instances. * *

For those operations that return multiple results, the API returns * instances of a {@link Traversable} interface which offers a lazy pull­style * API for working with multiple results. Although push­style interfaces for * handling multiple results, such as RxJava, are fully asynchronous, they're * harder to use from a user’s perspective. {@link Traversable},​ being a lazy * pull­style API, can still be asynchronous underneath since the user can * decide to work on the {@link Traversable} at a later stage, and the * implementation itself can decide when to compute those results. * * @since 8.0 */ @Experimental public interface FunctionalMap extends AutoCloseable { /** * Tweak functional map executions providing {@link Param} instances. */ FunctionalMap withParams(Param... ps); /** * Functional map's name. */ String getName(); /** * Functional map's status. */ Status getStatus(); /** * Exposes read-only operations that can be executed against the functional map. * The information that can be read per entry in the functional map is * exposed by {@link ReadEntryView}. * *

Read-only operations have the advantage that no locks are acquired * for the duration of the operation and so it makes sense to have them * a top-level interface dedicated to them. * *

Browsing methods that provide a read-only view of the cached data * are available via {@link #keys()} and {@link #entries()}. * Having {@link #keys()} makes sense since that way keys can be traversed * without having to bring values. Having {@link #entries()} makes sense * since it allows traversing both keys, values and any meta parameters * associated with them, but this is no extra cost to exposing just values * since keys are the main index and hence will always be available. * Hence, adding a method to only browse values offers nothing extra to * the API. * * @since 8.0 */ @Experimental interface ReadOnlyMap extends FunctionalMap { /** * Tweak read-only functional map executions providing {@link Param} instances. */ ReadOnlyMap withParams(Param... ps); /** * Evaluate a read-only function on the value associated with the key * and return a {@link CompletableFuture} with the return type of the function. * If the user is not sure if the key is present, {@link ReadEntryView#find()} * can be used to find out for sure. Typically, function implementations * would return value or {@link MetaParam} information from the cache * entry in the functional map. * *

By returning {@link CompletableFuture} instead of the function's * return type directly, the method hints at the possibility that to * execute the function might require to go remote to retrieve data in * persistent store or another clustered node. * *

This method can be used to implement read-only single-key based * operations in {@link ConcurrentMap} and javax.cache.Cache * such as: * *

    *
  • {@link ConcurrentMap#get(Object)}
  • *
  • {@link ConcurrentMap#containsKey(Object)}
  • *
  • {@code javax.cache.Cache#get(Object)}
  • *
  • {@code javax.cache.Cache#containsKey(Object)}
  • *
* * @param key the key associated with the {@link ReadEntryView} to be * passed to the function. * @param f function that takes a {@link ReadEntryView} associated with * the key, and returns a value. * @param function return type * @return a {@link CompletableFuture} which will be completed with the * returned value from the function */ CompletableFuture eval(K key, Function, R> f); /** * Evaluate a read-only function on a key and potential value associated in * the functional map, for each of the keys in the set passed in, and * returns an {@link Traversable} to work on each computed function's result. * *

The function passed in will be executed for as many keys * present in keys collection set. Similar to {@link #eval(Object, Function)}, * if the user is not sure whether a particular key is present, * {@link ReadEntryView#find()} can be used to find out for sure. * *

This method can be used to implement operations such as * {@code javax.cache.Cache#getAll(Set)}. * * DESIGN RATIONALE: *

    *
  • It makes sense to expose global operation like this instead of * forcing users to iterate over the keys to lookup and call get * individually since Infinispan can do things more efficiently. *
  • *
* * @param keys the keys associated with each of the {@link ReadEntryView} * passed in the function callbacks * @param f function that takes a {@link ReadEntryView} associated with * the key, and returns a value. It'll be invoked once for each key * passed in * @param function return type * @return a sequential {@link Traversable} that can be navigated to * retrieve each function return value */ Traversable evalMany(Set keys, Function, R> f); /** * Provides a {@link Traversable} that allows clients to navigate all cached keys. * *

This method can be used to implement operations such as: *

    *
  • {@link ConcurrentMap#size()}
  • *
  • {@link ConcurrentMap#keySet()}
  • *
  • {@link ConcurrentMap#isEmpty()}
  • *
* * @return a sequential {@link Traversable} to navigate each cached key */ Traversable keys(); /** * Provides a {@link Traversable} that allows clients to navigate all cached entries. * *

This method can be used to implement operations such as: *

    *
  • {@link ConcurrentMap#containsValue(Object)}
  • *
  • {@link ConcurrentMap#values()}
  • *
  • {@link ConcurrentMap#entrySet()}
  • *
  • {@code javax.cache.Cache#iterator()}
  • *
* * @return a sequential {@link Traversable} to navigate each cached entry */ Traversable> entries(); } /** * Exposes write-only operations that can be executed against the functional map. * The write operations that can be applied per entry are exposed by * {@link WriteEntryView}. * *

Write-only operations require locks to be acquired but crucially * they do not require reading previous value or metadata parameter * information associated with the cached entry, which sometimes can be * expensive since they involve talking to a remote node in the cluster * or the persistence layer So, exposing write-only operations makes it * easy to take advantage of this important optimisation. * *

Method parameters for write-only operations, including lambdas, * must be marshallable when running in a cluster. * * @since 8.0 */ @Experimental interface WriteOnlyMap extends FunctionalMap { /** * Tweak write-only functional map executions providing {@link Param} instances. */ WriteOnlyMap withParams(Param... ps); /** * Evaluate a write-only {@link BiConsumer} operation, with a value * passed in and a {@link WriteEntryView} of the value associated with * the key, and return a {@link CompletableFuture} which will be * completed when the operation completes. * *

Since this is a write-only operation, no entry attributes can be * queried, hence the only reasonable thing can be returned is Void. * *

This method can be used to implement single-key write-only operations * which do not need to query previous value, such as * {@code javax.cache.Cache#put(Object, Object)} * *

This operation is very similar to {@link #eval(Object, Consumer)} * and in fact, the functionality provided by this function could indeed * be implemented with {@link #eval(Object, Consumer)}, but there's a * crucial difference. If you want to store a value and reference the * value to be stored from the passed in operation, * {@link #eval(Object, Consumer)} needs to capture that value. * Capturing means that each time the operation is called, a new lambda * needs to be instantiated. By offering a {@link BiConsumer} that * takes user provided value as first parameter, the operation does not * capture any external objects when implementing simple operations * such as {@code javax.cache.Cache#put(Object, Object)}, and hence, the * {@link BiConsumer} could be cached and reused each time it's invoked. * * @param key the key associated with the {@link WriteEntryView} to be * passed to the operation * @param value value to write, passed in as first parameter to the * {@link BiConsumer} operation. * @param f operation that takes a user defined value, and a * {@link WriteEntryView} associated with the key, and writes * to the {@link WriteEntryView} passed in without returning anything * @return a {@link CompletableFuture} which will be completed when the * operation completes */ CompletableFuture eval(K key, V value, BiConsumer> f); /** * Evaluate a write-only {@link Consumer} operation with a * {@link WriteEntryView} of the value associated with the key, * and return a {@link CompletableFuture} which will be * completed with the object returned by the operation. * *

Since this is a write-only operation, no entry attributes can be * queried, hence the only reasonable thing can be returned is Void. * *

This operation can be used to either remove a cached entry, * or to write a constant value along with optional metadata parameters. * * @param key the key associated with the {@link WriteEntryView} to be * passed to the operation * @param f operation that takes a {@link WriteEntryView} associated with * the key and writes to the it without returning anything * @return a {@link CompletableFuture} which will be completed when the * operation completes */ CompletableFuture eval(K key, Consumer> f); /** * Evaluate a write-only {@link BiConsumer} operation, with a value * passed in and a {@link WriteEntryView} of the value associated with * the key, for each of the keys in the set passed in, and returns a * {@link CompletableFuture} that will be completed when the write-only * operation has been executed against all the entries. * * This method can be used to implement operations such as: * *

    *
  • {@link ConcurrentMap#putAll(Map)}
  • *
  • {@code javax.cache.Cache#putAll(Map)}
  • *
* *

These kind of operations are preferred to traditional end user * iterations because the internal logic can often iterate more * efficiently since it knows more about the system. * *

Since this is a write-only operation, no entry attributes can be * queried, hence the only reasonable thing can be returned is Void. * * @param entries the key/value pairs associated with each of the * {@link WriteEntryView} passed in the function callbacks * @param f operation that consumes a value associated with a key in the * entries collection and the {@link WriteEntryView} associated * with that key in the cache * @return a {@link CompletableFuture} which will be completed when * the {@link BiConsumer} operation has been executed against * all entries */ CompletableFuture evalMany(Map entries, BiConsumer> f); /** * Evaluate a write-only {@link Consumer} operation with the * {@link WriteEntryView} of the value associated with the key, for each * of the keys in the set passed in, and returns a * {@link CompletableFuture} that will be completed when the write-only * operation has been executed against all the entries. * *

This method can be used to implement operations such as * {@code javax.cache.Cache#removeAll(Set)}. * *

These kind of operations are preferred to traditional end user * iterations because the internal logic can often iterate more * efficiently since it knows more about the system. * *

Since this is a write-only operation, no entry attributes can be * queried, hence the only reasonable thing can be returned is Void. * * @param keys the keys associated with each of the {@link WriteEntryView} * passed in the function callbacks * @param f operation that the {@link WriteEntryView} associated with * one of the keys passed in * @return a {@link CompletableFuture} which will be completed when * the {@link Consumer} operation has been executed against all * entries */ CompletableFuture evalMany(Set keys, Consumer> f); /** * Evaluate a write-only {@link Consumer} operation with the * {@link WriteEntryView} of the value associated with the key, for all * existing keys in functional map, and returns a {@link CompletableFuture} * that will be completed when the write-only operation has been executed * against all the entries. * *

This method can be used to implement operations such as * {@code javax.cache.Cache#removeAll()}. * * @param f operation that the {@link WriteEntryView} associated with * one of the keys passed in * @return a {@link CompletableFuture} which will be completed when * the {@link Consumer} operation has been executed against all * entries */ CompletableFuture evalAll(Consumer> f); /** * Truncate the contents of the cache, returning a {@link CompletableFuture} * that will be completed when the truncate process completes. * * This method can be used to implement: * *

    *
  • {@link ConcurrentMap#clear()}
  • *
  • {@code javax.cache.Cache#clear()}
  • *
* * @return a {@link CompletableFuture} that completes when the truncat * has finished */ CompletableFuture truncate(); /** * Allows to write-only listeners to be registered. */ WriteListeners listeners(); } /** * Exposes read-write operations that can be executed against the functional map. * The read-write operations that can be applied per entry are exposed by * {@link ReadWriteEntryView}. * *

Read-write operations offer the possibility of writing values or * metadata parameters, and returning previously stored information. * Read-write operations are also crucial for implementing conditional, * compare-and-swap (CAS) like operations. * *

Locks are acquired before executing the read-write lambda. * *

Method parameters for read-write operations, including lambdas, * must be marshallable when running in a cluster. * * @since 8.0 */ @Experimental interface ReadWriteMap extends FunctionalMap { /** * Tweak read-write functional map executions providing {@link Param} instances. */ ReadWriteMap withParams(Param... ps); /** * Evaluate a read-write function on the value and metadata associated * with the key and return a {@link CompletableFuture} with the return * type of the function. If the user is not sure if the key is present, * {@link ReadWriteEntryView#find()} can be used to find out for sure. * * This method can be used to implement single-key read-write operations * in {@link ConcurrentMap} and {@code javax.cache.Cache} that do not * depend on value information given by the user such as: * *

    *
  • {@link ConcurrentMap#remove(Object)}
  • *
  • {@code javax.cache.Cache#remove(Object)}
  • *
  • {@code javax.cache.Cache#getAndRemove(Object)}
  • *
  • {@code javax.cache.Cache#invoke(Object, EntryProcessor, Object...)}
  • *
* * @param key the key associated with the {@link ReadWriteEntryView} to be * passed to the function. * @param f function that takes a {@link ReadWriteEntryView} associated with * the key, and returns a value. * @param function return type * @return a {@link CompletableFuture} which will be completed with the * returned value from the function */ CompletableFuture eval(K key, Function, R> f); /** * Evaluate a read-write function, with a value passed in and a * {@link WriteEntryView} of the value associated with the key, and * return a {@link CompletableFuture} which will be completed with the * returned value by the function. * *

This method provides the the capability to both update the value and * metadata associated with that key, and return previous value or metadata. * *

This method can be used to implement the vast majority of single-key * read-write operations in {@link ConcurrentMap} and {@code javax.cache.Cache} * such as: * *

    *
  • {@link ConcurrentMap#put(Object, Object)}
  • *
  • {@link ConcurrentMap#putIfAbsent(Object, Object)}
  • *
  • {@link ConcurrentMap#replace(Object, Object)}
  • *
  • {@link ConcurrentMap#replace(Object, Object, Object)}
  • *
  • {@link ConcurrentMap#remove(Object, Object)}
  • *
  • {@code javax.cache.Cache#getAndPut(Object, Object)}
  • *
  • {@code javax.cache.Cache#putIfAbsent(Object, Object)}
  • *
  • {@code javax.cache.Cache#remove(Object, Object)}
  • *
  • {@code javax.cache.Cache#replace(Object, Object, Object)}
  • *
  • {@code javax.cache.Cache#replace(Object, Object)}
  • *
  • {@code javax.cache.Cache#getAndReplace(Object, Object)}
  • *
* *

The functionality provided by this function could indeed be * implemented with {@link #eval(Object, Function)}, but there's a * crucial difference. If you want to store a value and reference the * value to be stored from the passed in operation, * {@link #eval(Object, Function)} needs to capture that value. * Capturing means that each time the operation is called, a new lambda * needs to be instantiated. By offering a {@link BiFunction} that * takes user provided value as first parameter, the operation does * not capture any external objects when implementing * simple operations such as {@code javax.cache.Cache#getAndPut(Object, Object)}, * and hence, the {@link BiFunction} could be cached and reused each * time it's invoked. * * @param key the key associated with the {@link ReadWriteEntryView} to be * passed to the operation * @param value value to write, passed in as first parameter to the {@link BiFunction}. * @param f operation that takes a user defined value, and a * {@link ReadWriteEntryView} associated with the key, and writes * to the {@link ReadWriteEntryView} passed in, possibly * returning previously stored value or metadata information * @param type of the function's return * @return a {@link CompletableFuture} which will be completed with the * returned value from the function */ CompletableFuture eval(K key, V value, BiFunction, R> f); /** * Evaluate a read-write {@link BiFunction}, with a value passed in and * a {@link ReadWriteEntryView} of the value associated with * the key, for each of the keys in the set passed in, and * returns an {@link Traversable} to navigate each of the * {@link BiFunction} invocation returns. * *

This method can be used to implement operations that store a set of * keys and return previous values or metadata parameters. * *

These kind of operations are preferred to traditional end user * iterations because the internal logic can often iterate more * efficiently since it knows more about the system. * * @param entries the key/value pairs associated with each of the * {@link ReadWriteEntryView} passed in the function callbacks * @param f function that takes in a value associated with a key in the * entries collection and the {@link ReadWriteEntryView} associated * with that key in the cache * @return a {@link Traversable} to navigate each {@link BiFunction} return */ Traversable evalMany(Map entries, BiFunction, R> f); /** * Evaluate a read-write {@link Function} operation with the * {@link ReadWriteEntryView} of the value associated with the key, for each * of the keys in the set passed in, and returns a {@link Traversable} * to navigate each of the {@link Function} invocation returns. * *

This method can be used to implement operations such as * {@code javax.cache.Cache#invokeAll(Set, EntryProcessor, Object...)}, * or a remove a set of keys returning previous values or metadata * parameters. * * @param keys the keys associated with each of the {@link ReadWriteEntryView} * passed in the function callbacks * @param f function that the {@link ReadWriteEntryView} associated with * one of the keys passed in, and returns a value * @return a {@link Traversable} to navigate each {@link Function} return */ Traversable evalMany(Set keys, Function, R> f); /** * Evaluate a read-write {@link Function} operation with the * {@link ReadWriteEntryView} of the value associated with the key, for all * existing keys, and returns a {@link Traversable} to navigate each of * the {@link Function} invocation returns. * *

This method can be used to an operation that removes all cached * entries individually, and returns previous value and/or metadata * parameters. * * @return a {@link Traversable} to navigate each {@link Function} return */ Traversable evalAll(Function, R> f); /** * Allows to read-write listeners to be registered. */ ReadWriteListeners listeners(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy