From e994c813cc6b46884e347594cbd935d9551345a2 Mon Sep 17 00:00:00 2001 From: "christian.lutnik" Date: Wed, 10 Dec 2025 11:48:50 +0100 Subject: [PATCH] Fix race condition, minor improvements to caching --- .../github/jamsesso/jsonlogic/JsonLogic.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/main/java/io/github/jamsesso/jsonlogic/JsonLogic.java b/src/main/java/io/github/jamsesso/jsonlogic/JsonLogic.java index fa25f2f..c137b11 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/JsonLogic.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/JsonLogic.java @@ -9,12 +9,13 @@ import java.lang.reflect.Array; import java.util.*; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; public final class JsonLogic { private final Map parseCache = new ConcurrentHashMap<>(); private final Map expressions = new ConcurrentHashMap<>(); - private JsonLogicEvaluator evaluator; + private final AtomicReference evaluator = new AtomicReference<>(); public JsonLogic() { // Add default operations @@ -70,21 +71,24 @@ public String key() { public JsonLogic addOperation(JsonLogicExpression expression) { expressions.put(expression.key(), expression); - evaluator = null; - + evaluator.set(null); return this; } public Object apply(String json, Object data) throws JsonLogicException { - if (!parseCache.containsKey(json)) { - parseCache.put(json, JsonLogicParser.parse(json)); + JsonLogicNode cached = parseCache.get(json); + if (cached == null) { + cached = JsonLogicParser.parse(json); + parseCache.putIfAbsent(json, cached); } - if (evaluator == null) { - evaluator = new JsonLogicEvaluator(expressions); + JsonLogicEvaluator localEvaluator = this.evaluator.get(); + if (localEvaluator == null) { + this.evaluator.compareAndSet(null, new JsonLogicEvaluator(expressions)); + localEvaluator = this.evaluator.get(); } - return evaluator.evaluate(parseCache.get(json), data, "$"); + return localEvaluator.evaluate(cached, data, "$"); } public static boolean truthy(Object value) {