From 556b552f806ecdc71c8f0b6b347cab6bda5b55b7 Mon Sep 17 00:00:00 2001 From: Loic Hermann Date: Wed, 13 Dec 2023 17:33:37 -0500 Subject: [PATCH 1/4] allow runtime bucket configuration --- .../deployment/Bucket4jProcessor.java | 6 +- .../runtime/BucketPodStorageRecorder.java | 16 ++--- .../bucket4j/runtime/RateLimiterConfig.java | 72 ------------------- .../runtime/RateLimiterRuntimeConfig.java | 55 ++++++++++++++ 4 files changed, 66 insertions(+), 83 deletions(-) delete mode 100644 runtime/src/main/java/io/quarkiverse/bucket4j/runtime/RateLimiterConfig.java diff --git a/deployment/src/main/java/io/quarkiverse/bucket4j/deployment/Bucket4jProcessor.java b/deployment/src/main/java/io/quarkiverse/bucket4j/deployment/Bucket4jProcessor.java index faf9412..c991807 100644 --- a/deployment/src/main/java/io/quarkiverse/bucket4j/deployment/Bucket4jProcessor.java +++ b/deployment/src/main/java/io/quarkiverse/bucket4j/deployment/Bucket4jProcessor.java @@ -127,12 +127,11 @@ private void visit(Map visited, Anno } @BuildStep - @Record(ExecutionTime.STATIC_INIT) + @Record(ExecutionTime.RUNTIME_INIT) void createBucketPodStorage( BucketPodStorageRecorder recorder, List rateLimitChecks, BuildProducer syntheticBeans) { - rateLimitChecks.forEach( item -> recorder.registerMethod(item.getMethodDescription(), item.getBucket(), item.getIdentityResolver())); @@ -140,7 +139,8 @@ void createBucketPodStorage( SyntheticBeanBuildItem.configure(BucketPodStorage.class) .scope(ApplicationScoped.class) .unremovable() - .runtimeValue(recorder.create()) + .runtimeProxy(recorder.create()) + .setRuntimeInit() .done()); } diff --git a/runtime/src/main/java/io/quarkiverse/bucket4j/runtime/BucketPodStorageRecorder.java b/runtime/src/main/java/io/quarkiverse/bucket4j/runtime/BucketPodStorageRecorder.java index 298ff7e..f59c996 100644 --- a/runtime/src/main/java/io/quarkiverse/bucket4j/runtime/BucketPodStorageRecorder.java +++ b/runtime/src/main/java/io/quarkiverse/bucket4j/runtime/BucketPodStorageRecorder.java @@ -7,29 +7,29 @@ import io.github.bucket4j.Bandwidth; import io.github.bucket4j.BucketConfiguration; import io.github.bucket4j.ConfigurationBuilder; +import io.quarkiverse.bucket4j.runtime.RateLimiterRuntimeConfig.Bucket; +import io.quarkiverse.bucket4j.runtime.RateLimiterRuntimeConfig.Limit; import io.quarkiverse.bucket4j.runtime.resolver.IdentityResolver; -import io.quarkus.runtime.RuntimeValue; import io.quarkus.runtime.annotations.Recorder; @Recorder public class BucketPodStorageRecorder { - private final RateLimiterConfig config; + private final RateLimiterRuntimeConfig config; Map pods = new HashMap<>(); - public BucketPodStorageRecorder(RateLimiterConfig config) { + public BucketPodStorageRecorder(RateLimiterRuntimeConfig config) { this.config = config; } private BucketPod getBucketPod(MethodDescription methodDescription, String key, String identityResolverClassName) { - RateLimiterConfig.Bucket bucketConfig = config.buckets().get(key); + Bucket bucketConfig = config.buckets().get(key); if (bucketConfig == null) { throw new IllegalStateException("missing limits config for " + key); } - ConfigurationBuilder builder = BucketConfiguration.builder(); - for (RateLimiterConfig.Limit limit : bucketConfig.limits()) { + for (Limit limit : bucketConfig.limits()) { builder.addLimit(Bandwidth.builder() .capacity(limit.permittedUses()) .refillGreedy(limit.permittedUses(), limit.period()) @@ -51,7 +51,7 @@ public void registerMethod(MethodDescription description, pods.put(description, getBucketPod(description, key, identityResolverClassName)); } - public RuntimeValue create() { - return new RuntimeValue<>(methodDescription -> pods.get(methodDescription)); + public BucketPodStorage create() { + return methodDescription -> pods.get(methodDescription); } } diff --git a/runtime/src/main/java/io/quarkiverse/bucket4j/runtime/RateLimiterConfig.java b/runtime/src/main/java/io/quarkiverse/bucket4j/runtime/RateLimiterConfig.java deleted file mode 100644 index 02c1523..0000000 --- a/runtime/src/main/java/io/quarkiverse/bucket4j/runtime/RateLimiterConfig.java +++ /dev/null @@ -1,72 +0,0 @@ -package io.quarkiverse.bucket4j.runtime; - -import java.time.Duration; -import java.util.List; -import java.util.Map; - -import io.quarkiverse.bucket4j.runtime.resolver.IdentityResolver; -import io.quarkus.runtime.annotations.ConfigDocMapKey; -import io.quarkus.runtime.annotations.ConfigGroup; -import io.quarkus.runtime.annotations.ConfigPhase; -import io.quarkus.runtime.annotations.ConfigRoot; -import io.quarkus.runtime.configuration.DurationConverter; -import io.smallrye.config.ConfigMapping; -import io.smallrye.config.WithConverter; -import io.smallrye.config.WithDefault; - -@ConfigMapping(prefix = "quarkus.rate-limiter") -@ConfigRoot(phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED) -public interface RateLimiterConfig { - - /** - * represent a group of limit applied to a method - * identified by the bucket id - */ - @ConfigDocMapKey("bucket-id") - Map buckets(); - - /** - * represent one single bucket - */ - @ConfigGroup - interface Bucket { - - /** - * Identity resolver allow to segment the population. - * Each resolved identity key will have its own quota. - * this must be a valid CDI bean implementing IdentityResolver. - */ - @WithDefault("io.quarkiverse.bucket4j.runtime.resolver.ConstantResolver") - String identityResolver(); - - /** - * limits enforced for this bucket - */ - List limits(); - - /** - * If true, permitted uses are shared for all methods using the same bucket id. - * If false, each method has its own quota. - */ - @WithDefault("false") - Boolean shared(); - } - - /** - * represent one single limit - */ - @ConfigGroup - interface Limit { - - /** - * Number of usage per period - */ - int permittedUses(); - - /** - * evaluation period - */ - @WithConverter(DurationConverter.class) - Duration period(); - } -} diff --git a/runtime/src/main/java/io/quarkiverse/bucket4j/runtime/RateLimiterRuntimeConfig.java b/runtime/src/main/java/io/quarkiverse/bucket4j/runtime/RateLimiterRuntimeConfig.java index 9b94e40..9c73c4c 100644 --- a/runtime/src/main/java/io/quarkiverse/bucket4j/runtime/RateLimiterRuntimeConfig.java +++ b/runtime/src/main/java/io/quarkiverse/bucket4j/runtime/RateLimiterRuntimeConfig.java @@ -1,7 +1,11 @@ package io.quarkiverse.bucket4j.runtime; import java.time.Duration; +import java.util.List; +import java.util.Map; +import io.quarkus.runtime.annotations.ConfigDocMapKey; +import io.quarkus.runtime.annotations.ConfigGroup; import io.quarkus.runtime.annotations.ConfigPhase; import io.quarkus.runtime.annotations.ConfigRoot; import io.quarkus.runtime.configuration.DurationConverter; @@ -32,4 +36,55 @@ public interface RateLimiterRuntimeConfig { @WithConverter(DurationConverter.class) Duration keepAfterRefill(); + /** + * represent a group of limit applied to a method + * identified by the bucket id + */ + @ConfigDocMapKey("bucket-id") + Map buckets(); + + /** + * represent one single bucket + */ + @ConfigGroup + interface Bucket { + + /** + * Identity resolver allow to segment the population. + * Each resolved identity key will have its own quota. + * this must be a valid CDI bean implementing IdentityResolver. + */ + @WithDefault("io.quarkiverse.bucket4j.runtime.resolver.ConstantResolver") + String identityResolver(); + + /** + * limits enforced for this bucket + */ + List limits(); + + /** + * If true, permitted uses are shared for all methods using the same bucket id. + * If false, each method has its own quota. + */ + @WithDefault("false") + Boolean shared(); + } + + /** + * represent one single limit + */ + @ConfigGroup + interface Limit { + + /** + * Number of usage per period + */ + int permittedUses(); + + /** + * evaluation period + */ + @WithConverter(DurationConverter.class) + Duration period(); + } } From c2ac3ec911b5059a115fd59dada0262af3311577 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hermann?= Date: Thu, 14 Dec 2023 08:31:25 -0500 Subject: [PATCH 2/4] Update runtime/src/main/java/io/quarkiverse/bucket4j/runtime/RateLimiterRuntimeConfig.java Co-authored-by: George Gastaldi --- .../quarkiverse/bucket4j/runtime/RateLimiterRuntimeConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/main/java/io/quarkiverse/bucket4j/runtime/RateLimiterRuntimeConfig.java b/runtime/src/main/java/io/quarkiverse/bucket4j/runtime/RateLimiterRuntimeConfig.java index 9c73c4c..f10ecba 100644 --- a/runtime/src/main/java/io/quarkiverse/bucket4j/runtime/RateLimiterRuntimeConfig.java +++ b/runtime/src/main/java/io/quarkiverse/bucket4j/runtime/RateLimiterRuntimeConfig.java @@ -37,7 +37,7 @@ public interface RateLimiterRuntimeConfig { Duration keepAfterRefill(); /** - * represent a group of limit applied to a method + * Represents a group of limits applied to a method * identified by the bucket id */ @ConfigDocMapKey("bucket-id") From 4a96a39890c9d892a0b565998f48d8af324dc3d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hermann?= Date: Thu, 14 Dec 2023 08:31:41 -0500 Subject: [PATCH 3/4] Update runtime/src/main/java/io/quarkiverse/bucket4j/runtime/RateLimiterRuntimeConfig.java Co-authored-by: George Gastaldi --- .../quarkiverse/bucket4j/runtime/RateLimiterRuntimeConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/main/java/io/quarkiverse/bucket4j/runtime/RateLimiterRuntimeConfig.java b/runtime/src/main/java/io/quarkiverse/bucket4j/runtime/RateLimiterRuntimeConfig.java index f10ecba..8454d1e 100644 --- a/runtime/src/main/java/io/quarkiverse/bucket4j/runtime/RateLimiterRuntimeConfig.java +++ b/runtime/src/main/java/io/quarkiverse/bucket4j/runtime/RateLimiterRuntimeConfig.java @@ -58,7 +58,7 @@ interface Bucket { String identityResolver(); /** - * limits enforced for this bucket + * Limits enforced for this bucket */ List limits(); From 762e5783218563d96646b2d59663c20fe1382999 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hermann?= Date: Thu, 14 Dec 2023 08:31:48 -0500 Subject: [PATCH 4/4] Update runtime/src/main/java/io/quarkiverse/bucket4j/runtime/RateLimiterRuntimeConfig.java Co-authored-by: George Gastaldi --- .../quarkiverse/bucket4j/runtime/RateLimiterRuntimeConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/main/java/io/quarkiverse/bucket4j/runtime/RateLimiterRuntimeConfig.java b/runtime/src/main/java/io/quarkiverse/bucket4j/runtime/RateLimiterRuntimeConfig.java index 8454d1e..5c17b93 100644 --- a/runtime/src/main/java/io/quarkiverse/bucket4j/runtime/RateLimiterRuntimeConfig.java +++ b/runtime/src/main/java/io/quarkiverse/bucket4j/runtime/RateLimiterRuntimeConfig.java @@ -82,7 +82,7 @@ interface Limit { int permittedUses(); /** - * evaluation period + * Evaluation period */ @WithConverter(DurationConverter.class) Duration period();