summaryrefslogtreecommitdiff
path: root/searx/search/checker/scheduler.py
diff options
context:
space:
mode:
authorAlexandre Flament <alex@al-f.net>2022-07-15 18:38:32 +0200
committerAlexandre Flament <alex@al-f.net>2022-11-05 12:04:50 +0100
commitfe419e355bf1527c51e3aee98495d08b89510320 (patch)
tree0ed03d5e3d77e68ac5a5834e5890f5f27fe29fe7 /searx/search/checker/scheduler.py
parentd764d94a70b0b10291105a867227975d59af5675 (diff)
downloadsearxng-fe419e355bf1527c51e3aee98495d08b89510320.tar.gz
searxng-fe419e355bf1527c51e3aee98495d08b89510320.zip
The checker requires Redis
Remove the abstraction in searx.shared.SharedDict. Implement a basic and dedicated scheduler for the checker using a Redis script.
Diffstat (limited to 'searx/search/checker/scheduler.py')
-rw-r--r--searx/search/checker/scheduler.py57
1 files changed, 57 insertions, 0 deletions
diff --git a/searx/search/checker/scheduler.py b/searx/search/checker/scheduler.py
new file mode 100644
index 000000000..1ae635951
--- /dev/null
+++ b/searx/search/checker/scheduler.py
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: AGPL-3.0-or-later
+# lint: pylint
+# pylint: disable=missing-module-docstring
+"""Lame scheduler which use Redis as a source of truth:
+* the Redis key SearXNG_checker_next_call_ts contains the next time the embedded checker should run.
+* to avoid lock, a unique Redis script reads and updates the Redis key SearXNG_checker_next_call_ts.
+* this Redis script returns a list of two elements:
+ * the first one is a boolean. If True, the embedded checker must run now in this worker.
+ * the second element is the delay in second to wait before the next call to the Redis script.
+
+This scheduler is not generic on purpose: if more feature are required, a dedicate scheduler must be used
+(= a better scheduler should not use the web workers)
+"""
+
+import logging
+import time
+import importlib
+from typing import Callable
+
+from searx.shared.redisdb import client as get_redis_client
+from searx.redislib import lua_script_storage
+
+
+logger = logging.getLogger('searx.search.checker')
+
+
+def scheduler_function(start_after_from: int, start_after_to: int, every_from: int, every_to: int, callback: Callable):
+ """Run the checker periodically. The function never returns.
+
+ Parameters:
+ * start_after_from and start_after_to: when to call "callback" for the first on the Redis instance
+ * every_from and every_to: after the first call, how often to call "callback"
+
+ There is no issue:
+ * to call this function is multiple workers
+ * to kill workers at any time as long there is one at least one worker
+ """
+ scheduler_now_script = importlib.resources.read_text(__package__, "scheduler.lua")
+ while True:
+ # ask the Redis script what to do
+ # the script says
+ # * if the checker must run now.
+ # * how to long to way before calling the script again (it can be call earlier, but not later).
+ script = lua_script_storage(get_redis_client(), scheduler_now_script)
+ call_now, wait_time = script(args=[start_after_from, start_after_to, every_from, every_to])
+
+ # does the worker run the checker now?
+ if call_now:
+ # run the checker
+ try:
+ callback()
+ except Exception: # pylint: disable=broad-except
+ logger.exception("Error calling the embedded checker")
+ # only worker display the wait_time
+ logger.info("Next call to the checker in %s seconds", wait_time)
+ # wait until the next call
+ time.sleep(wait_time)