From 17991fb0e7d58b24a3a9ad330421917e1dff9df3 Mon Sep 17 00:00:00 2001 From: Vladimir Buhtoyarov Date: Mon, 29 Apr 2024 00:45:09 +0300 Subject: [PATCH] #461 implement flexible per entry expiration --- README.md | 4 ++-- .../grid/coherence/Bucket4jCoherence.java | 5 +++++ .../grid/coherence/CoherenceProcessor.java | 15 ++++++++++++++- .../grid/coherence/CoherenceProxyManager.java | 5 +++++ .../java/CoherenceWithJdkSerializationTest.java | 2 +- .../java/CoherenceWithPofSerializationTest.java | 2 +- 6 files changed, 28 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 16d919ce..458bed88 100644 --- a/README.md +++ b/README.md @@ -77,13 +77,13 @@ Its key advantage lies in the configuration via properties or yaml files, elimin ### Supported JCache compatible(or similar) back-ends In addition to local in-memory buckets, the Bucket4j supports clustered usage scenario on top of following back-ends: -| Back-end | Async supported | Flexible Per-entry expiration | Optimized serialization | Thin-client support | Documentation link | +| Back-end | Async supported | Flexible per-entry expiration | Optimized serialization | Thin-client support | Documentation link | | :--- | :---: |:-----------------------------:|:-----------------------:|:-------------------:|:-------------------------------------------------------------------------------------:| | ```JCache API (JSR 107)``` | No | No | No | No | [bucket4j-jcache](https://bucket4j.github.io/8.12.0/toc.html#bucket4j-jcache) | | ```Hazelcast``` | Yes | Yes | Yes | No | [bucket4j-hazelcast](https://bucket4j.github.io/8.12.0/toc.html#bucket4j-hazelcast) | | ```Apache Ignite``` | Yes | No | n/a | Yes | [bucket4j-ignite](https://bucket4j.github.io/8.12.0/toc.html#bucket4j-ignite) | | ```Inifinispan``` | Yes | TODO | Yes | No | [bucket4j-infinispan](https://bucket4j.github.io/8.12.0/toc.html#bucket4j-infinispan) | -| ```Oracle Coherence``` | Yes | TODO | Yes | No | [bucket4j-coherence](https://bucket4j.github.io/8.12.0/toc.html#bucket4j-coherence) | +| ```Oracle Coherence``` | Yes | Yes | Yes | No | [bucket4j-coherence](https://bucket4j.github.io/8.12.0/toc.html#bucket4j-coherence) | ### Redis back-ends | Back-end | Async supported | Redis cluster supported | Documentation link | diff --git a/bucket4j-coherence/src/main/java/io/github/bucket4j/grid/coherence/Bucket4jCoherence.java b/bucket4j-coherence/src/main/java/io/github/bucket4j/grid/coherence/Bucket4jCoherence.java index da0e0d2b..3b7e0845 100644 --- a/bucket4j-coherence/src/main/java/io/github/bucket4j/grid/coherence/Bucket4jCoherence.java +++ b/bucket4j-coherence/src/main/java/io/github/bucket4j/grid/coherence/Bucket4jCoherence.java @@ -55,6 +55,11 @@ public CoherenceProxyManager build() { return new CoherenceProxyManager<>(this); } + @Override + public boolean isExpireAfterWriteSupported() { + return true; + } + } } diff --git a/bucket4j-coherence/src/main/java/io/github/bucket4j/grid/coherence/CoherenceProcessor.java b/bucket4j-coherence/src/main/java/io/github/bucket4j/grid/coherence/CoherenceProcessor.java index 4e309d97..e7c22367 100644 --- a/bucket4j-coherence/src/main/java/io/github/bucket4j/grid/coherence/CoherenceProcessor.java +++ b/bucket4j-coherence/src/main/java/io/github/bucket4j/grid/coherence/CoherenceProcessor.java @@ -19,8 +19,11 @@ */ package io.github.bucket4j.grid.coherence; +import com.tangosol.util.BinaryEntry; import com.tangosol.util.InvocableMap; import com.tangosol.util.processor.AbstractProcessor; + +import io.github.bucket4j.distributed.ExpirationAfterWriteStrategy; import io.github.bucket4j.distributed.remote.AbstractBinaryTransaction; import io.github.bucket4j.distributed.remote.RemoteBucketState; import io.github.bucket4j.distributed.remote.Request; @@ -29,6 +32,7 @@ import java.io.Serial; import java.util.Arrays; +import java.util.concurrent.TimeUnit; public class CoherenceProcessor extends AbstractProcessor implements ComparableByContent { @@ -65,7 +69,16 @@ protected byte[] getRawState() { @Override protected void setRawState(byte[] newStateBytes, RemoteBucketState newState) { - entry.setValue(newStateBytes); + ExpirationAfterWriteStrategy expirationStrategy = getExpirationStrategy(); + long ttlMillis = expirationStrategy == null ? -1 : expirationStrategy.calculateTimeToLiveMillis(newState, getCurrentTimeNanos()); + if (ttlMillis > 0) { + BinaryEntry binaryEntry = entry.asBinaryEntry(); + binaryEntry.setValue(newStateBytes); + binaryEntry.expire(ttlMillis); + entry.setValue(newStateBytes); + } else { + entry.setValue(newStateBytes); + } } }.execute(); } diff --git a/bucket4j-coherence/src/main/java/io/github/bucket4j/grid/coherence/CoherenceProxyManager.java b/bucket4j-coherence/src/main/java/io/github/bucket4j/grid/coherence/CoherenceProxyManager.java index 2606b581..be179bc2 100644 --- a/bucket4j-coherence/src/main/java/io/github/bucket4j/grid/coherence/CoherenceProxyManager.java +++ b/bucket4j-coherence/src/main/java/io/github/bucket4j/grid/coherence/CoherenceProxyManager.java @@ -124,4 +124,9 @@ protected CompletableFuture removeAsync(K key) { return cache.async().remove(key).thenApply(oldState -> null); } + @Override + public boolean isExpireAfterWriteSupported() { + return true; + } + } diff --git a/bucket4j-coherence/src/test/java/CoherenceWithJdkSerializationTest.java b/bucket4j-coherence/src/test/java/CoherenceWithJdkSerializationTest.java index 92ac0835..66f177af 100644 --- a/bucket4j-coherence/src/test/java/CoherenceWithJdkSerializationTest.java +++ b/bucket4j-coherence/src/test/java/CoherenceWithJdkSerializationTest.java @@ -42,7 +42,7 @@ public static void prepareCache() throws InterruptedException { "CoherenceProxyManager_JdkSerialization", () -> UUID.randomUUID().toString(), () -> Bucket4jCoherence.entryProcessorBasedBuilder(cache) - ) + ).checkExpiration() ); } diff --git a/bucket4j-coherence/src/test/java/CoherenceWithPofSerializationTest.java b/bucket4j-coherence/src/test/java/CoherenceWithPofSerializationTest.java index b0afa8eb..be7487b9 100644 --- a/bucket4j-coherence/src/test/java/CoherenceWithPofSerializationTest.java +++ b/bucket4j-coherence/src/test/java/CoherenceWithPofSerializationTest.java @@ -40,7 +40,7 @@ public static void prepareCache() throws InterruptedException { "CoherenceProxyManager_PofSerialization", () -> UUID.randomUUID().toString(), () -> Bucket4jCoherence.entryProcessorBasedBuilder(cache) - ) + ).checkExpiration() ); }