]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
datamodel: cache: prefetch for expiring record is separated from prediction
authorAleš Mrázek <ales.mrazek@nic.cz>
Thu, 11 Apr 2024 13:54:25 +0000 (15:54 +0200)
committerAleš Mrázek <ales.mrazek@nic.cz>
Mon, 22 Apr 2024 10:43:52 +0000 (12:43 +0200)
doc/user/config-cache-predict.rst
manager/etc/knot-resolver/config.example.personal.yaml
manager/knot_resolver_manager/datamodel/cache_schema.py
manager/knot_resolver_manager/datamodel/templates/cache.lua.j2
manager/tests/unit/datamodel/test_cache_schema.py [deleted file]

index f25f95baead7de78f435a29b03191d83b16372ce..08f168d7e8774c8c8c694d8dbb1b2d66f5d78f98 100644 (file)
@@ -2,34 +2,50 @@
 
 .. _config-cache-predict:
 
-Prefetching records
-===================
+Prefetching cache records
+=========================
 
-Prefetching records helps to keep the cache hot.
-It can utilize two independent mechanisms to select the records which should be refreshed:
-expiring records and prediction.
+Prefetching cache records helps to keep the cache hot.
+You can use two independent mechanisms to select the records which should be refreshed.
 
 Expiring records
 ----------------
 
-This mechanism is always active when the prefetching is enabled and it is not configurable.
-
 Any time the resolver answers with records that are about to expire,
 they get refreshed. Record is expiring if it has less than 1% TTL (or less than 5s).
 That improves latency for records which get frequently queried, relatively to their TTL.
 
+.. code-block:: yaml
+
+   cache:
+     prefetch:
+       # enabling prefetching of expiring records, 'false' is default
+       expiring: true
+
+
 Prediction
 ----------
 
-The resolver can also learn usage patterns and repetitive queries,
+The resolver can learn usage patterns and repetitive queries,
 though this mechanism is a prototype and **not recommended** for use in production or with high traffic.
 
+.. code-block:: yaml
+
+   cache:
+     prefetch:
+       # this mode is NOT RECOMMENDED for use in production
+       prediction:
+          window: 15m  # 15 minutes sampling window
+          period: 24   # track last 6 hours
+
+
+Window length is in minutes, period is a number of windows that can be kept in memory.
+e.g. if a ``window`` is 15 minutes, a ``period`` of "24" means 6 hours (360 minutes, 15*24=360).
+
 For example, if it makes a query every day at 18:00,
 the resolver expects that it is needed by that time and prefetches it ahead of time.
 This is helpful to minimize the perceived latency and keeps the cache hot.
 
-You can disable prediction by configuring :option:`period <period: <int>>` to ``0``.
-
 .. tip::
 
    The tracking window and period length determine memory requirements.
@@ -38,42 +54,8 @@ You can disable prediction by configuring :option:`period <period: <int>>` to ``
    Experiment to get the best results.
 
 
-Configuration
--------------
-
-.. option:: cache/prediction: true|false|<options>
-
-   :default: false
-
-   .. option:: window: <time ms|s|m|h|d>
-
-      :default: 15m
-
-   .. option:: period: <int>
-
-      :default: 24
-
-Reconfigure the predictor to given tracking window and period length. Both parameters are optional.
-Window length is in minutes, period is a number of windows that can be kept in memory.
-e.g. if a ``window`` is 15 minutes, a ``period`` of "24" means 6 hours (360 minutes, 15*24=360).
-
-.. code-block:: yaml
-
-   cache:
-     # this mode is NOT RECOMMENDED for use in production
-     prediction:
-       window: 15m  # 15 minutes sampling window
-       period: 24   # track last 6 hours
-
-It is also possible to enable prediction with defaults for :option:`window <window: <time ms|s|m|h|d>>` and :option:`period <period: <int>>`.
-
-.. code-block:: yaml
-
-   cache:
-     prediction: true
-
 Exported metrics
-----------------
+****************
 
 To visualize the efficiency of the predictions, following statistics are exported.
 
index b7d11c1aae96465093f6fba9d8e327ab3abaa98a..69233fef464f2b645c06252b16f951ce297fb14d 100644 (file)
@@ -16,4 +16,8 @@ network:
 cache:
   size-max: 100M
   # prefetch expiring/frequent records
-  prediction: true
+  prefetch:
+    expiring: true
+    prediction:
+      period: 24
+      window: 15m
index 40aa88970f23d4878faf64271f9ef2b39553d19e..ac30f0d0199e411f91031bb50286d23d60759f6b 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Any, List, Optional, Union
+from typing import List, Optional, Union
 
 from typing_extensions import Literal
 
@@ -95,49 +95,44 @@ class PredictionSchema(ConfigSchema):
     """
 
     window: TimeUnit = TimeUnit("15m")
-    period: IntNonNegative = IntNonNegative(24)
+    period: IntPositive = IntPositive(24)
+
+
+class PrefetchSchema(ConfigSchema):
+    """
+    These options help keep the cache hot by prefetching expiring records or learning usage patterns and repetitive queries.
+    ---
+    expiring: Prefetch expiring records.
+    prediction: Prefetch record by predicting based on usage patterns and repetitive queries.
+    """
+
+    expiring: bool = False
+    prediction: Optional[PredictionSchema] = None
 
 
 class CacheSchema(ConfigSchema):
-    class Raw(ConfigSchema):
-        """
-        DNS resolver cache configuration.
-
-        ---
-        storage: Cache storage of the DNS resolver.
-        size_max: Maximum size of the cache.
-        garbage_collector: Use the garbage collector (kres-cache-gc) to periodically clear cache.
-        ttl_min: Minimum time-to-live for the cache entries.
-        ttl_max: Maximum time-to-live for the cache entries.
-        ns_timeout: Time interval for which a nameserver address will be ignored after determining that it does not return (useful) answers.
-        prefill: Prefill the cache periodically by importing zone data obtained over HTTP.
-        prediction: Helps keep the cache hot by prefetching expiring records and learning usage patterns and repetitive queries.
-        """
-
-        storage: Dir = lazy_default(Dir, "/var/cache/knot-resolver")
-        size_max: SizeUnit = SizeUnit("100M")
-        garbage_collector: Union[GarbageCollectorSchema, Literal[False]] = GarbageCollectorSchema()
-        ttl_min: TimeUnit = TimeUnit("5s")
-        ttl_max: TimeUnit = TimeUnit("1d")
-        ns_timeout: TimeUnit = TimeUnit("1000ms")
-        prefill: Optional[List[PrefillSchema]] = None
-        prediction: Union[bool, PredictionSchema] = False
-
-    _LAYER = Raw
-
-    storage: Dir
-    size_max: SizeUnit
-    garbage_collector: Union[GarbageCollectorSchema, Literal[False]]
-    ttl_min: TimeUnit
-    ttl_max: TimeUnit
-    ns_timeout: TimeUnit
-    prefill: Optional[List[PrefillSchema]]
-    prediction: Union[Literal[False], PredictionSchema]
-
-    def _prediction(self, obj: Raw) -> Any:
-        if obj.prediction is True:
-            return PredictionSchema()
-        return obj.prediction
+    """
+    DNS resolver cache configuration.
+
+    ---
+    storage: Cache storage of the DNS resolver.
+    size_max: Maximum size of the cache.
+    garbage_collector: Use the garbage collector (kres-cache-gc) to periodically clear cache.
+    ttl_min: Minimum time-to-live for the cache entries.
+    ttl_max: Maximum time-to-live for the cache entries.
+    ns_timeout: Time interval for which a nameserver address will be ignored after determining that it does not return (useful) answers.
+    prefill: Prefill the cache periodically by importing zone data obtained over HTTP.
+    prefetch: These options help keep the cache hot by prefetching expiring records or learning usage patterns and repetitive queries.
+    """
+
+    storage: Dir = lazy_default(Dir, "/var/cache/knot-resolver")
+    size_max: SizeUnit = SizeUnit("100M")
+    garbage_collector: Union[GarbageCollectorSchema, Literal[False]] = GarbageCollectorSchema()
+    ttl_min: TimeUnit = TimeUnit("5s")
+    ttl_max: TimeUnit = TimeUnit("1d")
+    ns_timeout: TimeUnit = TimeUnit("1000ms")
+    prefill: Optional[List[PrefillSchema]] = None
+    prefetch: PrefetchSchema = PrefetchSchema()
 
     def _validate(self):
         if self.ttl_min.seconds() >= self.ttl_max.seconds():
index fa92cad724cf671b34dcc79456694450526f9763..f0176a59f9fa00ee2ce197fd8cfe459e38a34e15 100644 (file)
@@ -17,11 +17,16 @@ prefill.config({
 })
 {% endif %}
 
-{% if cfg.cache.prediction %}
--- cache.prediction
+{% if cfg.cache.prefetch.expiring %}
+-- cache.prefetch.expiring
+modules.load('prefetch')
+{% endif %}
+
+{% if cfg.cache.prefetch.prediction %}
+-- cache.prefetch.prediction
 modules.load('predict')
 predict.config({
-    window = {{ cfg.cache.prediction.window.minutes() }},
-    period = {{ cfg.cache.prediction.period }},
+    window = {{ cfg.cache.prefetch.prediction.window.minutes() }},
+    period = {{ cfg.cache.prefetch.prediction.period }},
 })
 {% endif %}
diff --git a/manager/tests/unit/datamodel/test_cache_schema.py b/manager/tests/unit/datamodel/test_cache_schema.py
deleted file mode 100644 (file)
index f5c3030..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-from knot_resolver_manager.datamodel.cache_schema import CacheSchema
-
-
-def test_prediction_true_defaults():
-    o = CacheSchema({"prediction": True})
-    assert str(o.prediction.window) == "15m"
-    assert int(o.prediction.period) == 24