.oO SearXNG Developer Documentation Oo.
Loading...
Searching...
No Matches
scheduler.py
Go to the documentation of this file.
1# SPDX-License-Identifier: AGPL-3.0-or-later
2# pylint: disable=missing-module-docstring
3"""Lame scheduler which use Redis as a source of truth:
4* the Redis key SearXNG_checker_next_call_ts contains the next time the embedded checker should run.
5* to avoid lock, a unique Redis script reads and updates the Redis key SearXNG_checker_next_call_ts.
6* this Redis script returns a list of two elements:
7 * the first one is a boolean. If True, the embedded checker must run now in this worker.
8 * the second element is the delay in second to wait before the next call to the Redis script.
9
10This scheduler is not generic on purpose: if more feature are required, a dedicate scheduler must be used
11(= a better scheduler should not use the web workers)
12"""
13
14import logging
15import time
16from pathlib import Path
17from typing import Callable
18
19from searx.redisdb import client as get_redis_client
20from searx.redislib import lua_script_storage
21
22
23logger = logging.getLogger('searx.search.checker')
24
25SCHEDULER_LUA = Path(__file__).parent / "scheduler.lua"
26
27
28def scheduler_function(start_after_from: int, start_after_to: int, every_from: int, every_to: int, callback: Callable):
29 """Run the checker periodically. The function never returns.
30
31 Parameters:
32 * start_after_from and start_after_to: when to call "callback" for the first on the Redis instance
33 * every_from and every_to: after the first call, how often to call "callback"
34
35 There is no issue:
36 * to call this function is multiple workers
37 * to kill workers at any time as long there is one at least one worker
38 """
39 scheduler_now_script = SCHEDULER_LUA.open().read()
40 while True:
41 # ask the Redis script what to do
42 # the script says
43 # * if the checker must run now.
44 # * how to long to way before calling the script again (it can be call earlier, but not later).
45 script = lua_script_storage(get_redis_client(), scheduler_now_script)
46 call_now, wait_time = script(args=[start_after_from, start_after_to, every_from, every_to])
47
48 # does the worker run the checker now?
49 if call_now:
50 # run the checker
51 try:
52 callback()
53 except Exception: # pylint: disable=broad-except
54 logger.exception("Error calling the embedded checker")
55 # only worker display the wait_time
56 logger.info("Next call to the checker in %s seconds", wait_time)
57 # wait until the next call
58 time.sleep(wait_time)
scheduler_function(int start_after_from, int start_after_to, int every_from, int every_to, Callable callback)
Definition scheduler.py:28