Skip to content

Commit

Permalink
Infinispan Cache Extension
Browse files Browse the repository at this point in the history
* Deprecates custom annotations
* Implements the cache extension SPI
  • Loading branch information
karesti committed Apr 22, 2024
1 parent 96007c9 commit b6285a6
Show file tree
Hide file tree
Showing 37 changed files with 1,789 additions and 27 deletions.
4 changes: 2 additions & 2 deletions .github/native-tests.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@
},
{
"category": "Cache",
"timeout": 65,
"test-modules": "infinispan-cache-jpa, infinispan-client, cache, redis-cache",
"timeout": 75,
"test-modules": "infinispan-cache-jpa, infinispan-client, cache, redis-cache, infinispan-cache",
"os-name": "ubuntu-latest"
},
{
Expand Down
10 changes: 10 additions & 0 deletions bom/application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1265,6 +1265,16 @@
<artifactId>quarkus-infinispan-client-deployment</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-infinispan-cache</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-infinispan-cache-deployment</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-db2</artifactId>
Expand Down
13 changes: 13 additions & 0 deletions devtools/bom-descriptor-json/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -889,6 +889,19 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-infinispan-cache</artifactId>
<version>${project.version}</version>
<type>pom</type>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-infinispan-client</artifactId>
Expand Down
13 changes: 13 additions & 0 deletions docs/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,19 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-infinispan-cache-deployment</artifactId>
<version>${project.version}</version>
<type>pom</type>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-infinispan-client-deployment</artifactId>
Expand Down
138 changes: 138 additions & 0 deletions docs/src/main/asciidoc/cache-infinispan-reference.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
////
This guide is maintained in the main Quarkus repository
and pull requests should be submitted there:
https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc
////
= Infinispan Cache
:extension-status: preview
include::_attributes.adoc[]
:categories: data
:summary: Use Infinispan as the Quarkus cache backend
:topics: infinispan,cache,data
:extensions: io.quarkus:quarkus-infinispan-cache,io.quarkus:quarkus-infinispan-client

By default, Quarkus Cache uses Caffeine as backend.
It's possible to use Infinispan instead.

include::{includes}/extension-status.adoc[]

== Infinispan as cache backend

When using Infinispan as the backend for Quarkus cache, each cached item will be stored in Infinispan:

- The backend uses the _<default>_ Infinispan client (unless configured differently), so ensure its configuration is
set up accordingly (or use the xref:infinispan-dev-services.adoc[Infinispan Dev Service])
- Both the key and the value are marshalled using Protobuf with Protostream.

== Use the Infinispan backend

First, add the `quarkus-infinispan-cache` extension to your project:

[source,xml,role="primary asciidoc-tabs-target-sync-cli asciidoc-tabs-target-sync-maven"]
.pom.xml
----
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-infinispan-cache</artifactId>
</dependency>
----

[source,gradle,role="secondary asciidoc-tabs-target-sync-gradle"]
.build.gradle
----
implementation("io.quarkus:quarkus-infinispan-cache")
----

Then, use the `@CacheResult` and other cache annotations as detailed in the xref:cache.adoc[Quarkus Cache guide]:

[source, java]
----
@GET
@Path("/{keyElement1}/{keyElement2}/{keyElement3}")
@CacheResult(cacheName = "expensiveResourceCache")
public ExpensiveResponse getExpensiveResponse(@PathParam("keyElement1") @CacheKey String keyElement1,
@PathParam("keyElement2") @CacheKey String keyElement2, @PathParam("keyElement3") @CacheKey String keyElement3,
@QueryParam("foo") String foo) {
invocations.incrementAndGet();
ExpensiveResponse response = new ExpensiveResponse();
response.setResult(keyElement1 + " " + keyElement2 + " " + keyElement3 + " too!");
return response;
}
@POST
@CacheInvalidateAll(cacheName = "expensiveResourceCache")
public void invalidateAll() {
}
----

[[infinispan-cache-configuration-reference]]
== Configure the Infinispan backend

The Infinispan backend uses the `<default>` Infinispan client.
Refer to the xref:infinispan-client-reference.adoc[Infinispan reference] for configuring the access to Infinispan.

TIP: In dev mode, you can use the xref:infinispan-dev-services.adoc[Infinispan Dev Service].

If you want to use another Infinispan for your cache, configure the `client-name` as follows:

[source, properties]
----
quarkus.cache.infinispan.client-name=another
----

== Marshalling

When interacting with Infinispan in Quarkus, you can easily marshal and unmarshal
Java simple types when writing to or reading from the cache. However, when dealing
with Plain Old Java Objects (POJOs), users of Infinispan need to provide the marshalling
schema.

[source, java]
----
@Proto
public record ExpensiveResponse(String result) {
}
@ProtoSchema(includeClasses = { ExpensiveResponse.class })
interface Schema extends GeneratedSchema {
}
----

Read more about it in the xref:infinispan-client-reference.adoc[Infinispan reference] in the Annotation
based serialization section.

== Expiration

You have the option to configure two properties for data expiration: *lifespan* and *max-idle*.

=== Lifespan

In Infinispan, *lifespan* refers to a configuration parameter that determines the maximum time an
entry (or an object) can remain in the cache since it was created or last accessed before it is
considered expired and removed from the cache.

When you configure the *lifespan* parameter for entries in an Infinispan cache,
you specify a time duration. After an entry has been added to the cache or accessed
(read or written), it starts its lifespan countdown. If the time since the entry
was created or last accessed exceeds the specified "lifespan" duration, the entry
is considered expired and becomes eligible for eviction from the cache.

[source, properties]
----
quarkus.cache.infinispan.my-cache.lifespan=10s
----

=== Max Idle
When you configure the *max-idle* parameter for entries in an Infinispan cache, you specify a time
duration. After an entry has been accessed (read or written) in the cache, if there are no subsequent
accesses to that entry within the specified duration, it is considered idle. Once the idle time
exceeds the *max-idle* duration, the entry is considered expired and eligible for eviction from
the cache.

[source, properties]
----
quarkus.cache.infinispan.my-cache.max-idle=100s
----

include::{generated-dir}/config/quarkus-cache-infinispan.adoc[opts=optional, leveloffset=+1]
41 changes: 16 additions & 25 deletions docs/src/main/asciidoc/infinispan-client-reference.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -318,36 +318,19 @@ some additional steps that are detailed here. Let's say we have the following us
.Author.java
[source,java]
----
public class Author {
private final String name;
private final String surname;
public Author(String name, String surname) {
this.name = Objects.requireNonNull(name);
this.surname = Objects.requireNonNull(surname);
}
// Getter/Setter/equals/hashCode/toString omitted
public record Author(String name, String surname) {
}
----

.Book.java
[source,java]
----
public class Book {
private final String title;
private final String description;
private final int publicationYear;
private final Set<Author> authors;
private final BigDecimal price;
public Book(String title, String description, int publicationYear, Set<Author> authors, BigDecimal price) {
this.title = Objects.requireNonNull(title);
this.description = Objects.requireNonNull(description);
this.publicationYear = publicationYear;
this.authors = Objects.requireNonNull(authors);
this.price = price;
}
// Getter/Setter/equals/hashCode/toString omitted
public record Book(String title,
String description,
int publicationYear,
Set<Author> authors,
Type bookType,
BigDecimal price) {
}
----

Expand Down Expand Up @@ -711,7 +694,15 @@ https://infinispan.org/docs/stable/titles/rest/rest.html#rest_v2_protobuf_schema
https://infinispan.org/docs/stable/titles/encoding/encoding.html#registering-sci-remote-caches_marshalling[Hot Rod Java Client].

[[infinispan-annotations-api]]
== Caching using annotations
=== Caching using annotations

[IMPORTANT]
====
Infinispan Caching annotations are deprecated *in this extension* and will be removed.
Use or replace your annotations by using the xref:cache-infinispan-reference.adoc[Infinispan Cache extension].
Update your import statements to use the annotations from `io.quarkus.cache` package instead of
`io.quarkus.infinispan.client`.
====

The Infinispan Client extension offers a set of annotations that can be used in a CDI managed bean to enable caching abilities with Infinispan.

Expand Down
94 changes: 94 additions & 0 deletions extensions/infinispan-cache/deployment/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>quarkus-infinispan-cache-parent</artifactId>
<groupId>io.quarkus</groupId>
<version>999-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>quarkus-infinispan-cache-deployment</artifactId>
<name>Quarkus - Infinispan - Cache - Deployment</name>

<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-infinispan-client-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-cache-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-infinispan-cache</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5-internal</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${project.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>

<profiles>
<profile>
<id>test-infinispan</id>
<activation>
<property>
<name>test-containers</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>false</skip>
</configuration>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<skip>false</skip>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
Loading

0 comments on commit b6285a6

Please sign in to comment.