diff --git a/CHANGELOG.md b/CHANGELOG.md index 76e20e39e9aea4cd08be4a38849452398ec5d112..dceac0e272ecff2ea89cd2b45322e8fd985ddd24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +* `ETag` property for the query. The `ETag` tags a server state and is being + updated each time the server state is being updated (i.e. the stored entities + change). This can be used to debug the query cache and also allows a client + to determine whether the server's state has changed between queries. * Basic caching for queries. The caching is enabled by default and can be controlled by the usual "cache" flag. diff --git a/src/main/java/org/caosdb/server/query/Query.java b/src/main/java/org/caosdb/server/query/Query.java index 0a877fc83e2f680565181655ed92c3a61cda393b..60c361bea31b2ae62f73103595a5d549ffd78805 100644 --- a/src/main/java/org/caosdb/server/query/Query.java +++ b/src/main/java/org/caosdb/server/query/Query.java @@ -39,6 +39,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.UUID; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; import org.apache.commons.jcs.access.behavior.ICacheAccess; @@ -238,6 +239,14 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac */ private boolean cachable = true; + /** + * Tags the query cache and is renewed each time the cache is being cleared, i.e. each time the + * database is being updated. + * + * <p>As the name suggests, the idea is similar to the ETag header of the HTTP protocol. + */ + private static String cacheETag = UUID.randomUUID().toString(); + public Type getType() { return this.type; } @@ -668,6 +677,7 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac /** Remove all cached queries from the cache. */ public static void clearCache() { + cacheETag = UUID.randomUUID().toString(); cache.clear(); } @@ -678,10 +688,12 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac * @param resultSet */ private void setCache(String key, List<IdVersionPair> resultSet) { - if (resultSet instanceof Serializable) { - cache.put(key, (Serializable) resultSet); - } else { - cache.put(key, new ArrayList<>(resultSet)); + synchronized (cache) { + if (resultSet instanceof Serializable) { + cache.put(key, (Serializable) resultSet); + } else { + cache.put(key, new ArrayList<>(resultSet)); + } } } @@ -859,6 +871,7 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac ret.setAttribute("results", "0"); } ret.setAttribute("cached", Boolean.toString(this.cached)); + ret.setAttribute("etag", cacheETag); final Element parseTreeElem = new Element("ParseTree"); if (this.el.hasErrors()) {