5.5. Continuous Queries
- Return all persons with an age between 18 and 25 (assuming the
Person
entity has an age property and is updated by the user application). - Return all transactions higher than $2000.
- Return all times where the lap speed of F1 racers were less than 1:45.00s (assuming the cache contains
Lap
entries and that laps are entered live during the race).
5.5.1. Continuous Query Evaluation
- An entry starts matching the specified query, represented by a
Join
event. - An entry stops matching the specified query, represented by a
Leave
event.
Join
events as described above. In addition, it will receive subsequent notifications when other entries begin matching the query, as Join
events, or stop matching the query, as Leave
events, as a consequence of any cache operations that would normally generate creation, modification, removal, or expiration events.
Join
or Leave
event the following logic is used:
- If the query on both the old and new values evaluate false, then the event is suppressed.
- If the query on both the old and new values evaluate true, then the event is suppressed.
- If the query on the old value evaluates false and the query on the new value evaluates true, then a
Join
event is sent. - If the query on the old value evaluates true and the query on the new value evaluates false, then a
Leave
event is sent. - If the query on the old value evaluates true and the entry is removed, then a
Leave
event is sent.
Note
5.5.2. Using Continuous Queries in Library Mode
To create a Continuous Query the Query
will be defined similar to other querying methods; however, ensure that the query is defined as a org.infinispan.query.continuous.ContinuousQuery
and a org.infinispan.query.continuous.ContinuousQueryListener
is in use.
ContinuousQueryListener
has been defined it may be added by using the addContinuousQueryListener
method of ContinuousQuery
:
continuousQuery.addContinuousQueryListener(query, listener)
ContinuousQuery
in Library mode:
Example 5.29. Defining and Adding a Continuous Query
import org.infinispan.query.continuous.ContinuousQuery; import org.infinispan.query.continuous.ContinuousQueryListener; import org.infinispan.query.Search; import org.infinispan.query.dsl.QueryFactory; import org.infinispan.query.dsl.Query; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; [...] // To begin we create a ContinuousQuery instance on the cache ContinuousQuery<Integer, Person> continuousQuery = new ContinuousQuery<Integer, Person>(cache); // Define our query. In this case we will be looking for any // Person instances under 21 years of age. QueryFactory queryFactory = Search.getQueryFactory(cache); Query query = queryFactory.from(Person.class) .having("age").lt(21) .toBuilder().build(); final Map<Integer, Person> matches = new ConcurrentHashMap<Integer, Person>(); // Define the ContinuousQueryListener ContinuousQueryListener<Integer, Person> listener = new ContinuousQueryListener<Integer, Person>() { @Override public void resultJoining(Integer key, Person value) { matches.put(key, value); } @Override public void resultLeaving(Integer key) { matches.remove(key); } }; // Add the listener and generated query continuousQuery.addContinuousQueryListener(query, listener); [...] // Remove the listener to stop receiving notifications continuousQuery.removeContinuousQueryListener(listener);
Person
instances are added to the cache that contain an Age less than 21 they will be placed into matches
, and when these entries are removed from the cache they will be also be removed from matches
.
To stop the query from further execution remove the listener:
continuousQuery.removeContinuousQueryListener(listener);
5.5.3. Using Continuous Queries in Remote Client-Server Mode
To create a Continuous Query the Query
will be defined similar to other querying methods; however, ensure that the query and a org.infinispan.client.hotrod.event.ContinuousQueryListener
are registered with ClientEvents
.
ContinuousQueryListener
has been defined it may be added by using the static addContinuousQueryListener
method of org.infinispan.client.hotrod.event.ClientEvents
:
ClientEvents.addContinuousQueryListener(cache, listener, query)
Example 5.30. Defining and Adding a Continuous Query
import org.infinispan.client.hotrod.event.ClientEvents; import org.infinispan.client.hotrod.event.ContinuousQueryListener; import org.infinispan.client.hotrod.Search; import org.infinispan.query.dsl.QueryFactory; import org.infinispan.query.dsl.Query; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; [...] // Define our query. In this case we will be looking for any // Person instances under 21 years of age. QueryFactory queryFactory = Search.getQueryFactory(cache); Query query = queryFactory.from(Person.class) .having("age").lt(21) .toBuilder().build(); final Map<Integer, Person> matches = new ConcurrentHashMap<Integer, Person>(); // Define the ContinuousQueryListener ContinuousQueryListener<Integer, Person> listener = new ContinuousQueryListener<Integer, Person>() { @Override public void resultJoining(Integer key, Person value) { matches.put(key, value); } @Override public void resultLeaving(Integer key) { matches.remove(key); } }; // Add the listener and generated query Object clientListener = ClientEvents.addContinuousQueryListener(cache, listener, query); [...] // Remove the listener to stop receiving notifications cache.removeClientListener(clientListener);
Person
instances are added to the cache that contain an Age less than 21 they will be placed into matches
, and when these entries are removed from the cache they will be also be removed from matches
.
To stop the query from further execution remove the listener from the cache:
cache.removeClientListener(clientListener);
5.5.4. Performance Considerations with Continuous Queries
ContinuousQueryListener
is designed to quickly process all received events.