diff --git a/freqtrade/util/__init__.py b/freqtrade/util/__init__.py index f7e63d9d3..b85b36ffb 100644 --- a/freqtrade/util/__init__.py +++ b/freqtrade/util/__init__.py @@ -3,6 +3,7 @@ from freqtrade.util.datetime_helpers import (dt_floor_day, dt_from_ts, dt_humani format_ms_time, shorten_date) from freqtrade.util.formatters import decimals_per_coin, fmt_coin, round_value from freqtrade.util.ft_precise import FtPrecise +from freqtrade.util.measure_time import MeasureTime from freqtrade.util.periodic_cache import PeriodicCache from freqtrade.util.template_renderer import render_template, render_template_with_fallback # noqa @@ -24,4 +25,5 @@ __all__ = [ 'decimals_per_coin', 'round_value', 'fmt_coin', + 'MeasureTime', ] diff --git a/freqtrade/util/measure_time.py b/freqtrade/util/measure_time.py new file mode 100644 index 000000000..beb43c27e --- /dev/null +++ b/freqtrade/util/measure_time.py @@ -0,0 +1,42 @@ +import logging +import time +from typing import Callable + +from cachetools import TTLCache + + +logger = logging.getLogger(__name__) + + +class MeasureTime: + """ + Measure the time of a block of code and call a callback if the time limit is exceeded. + + """ + def __init__(self, callback: Callable[[int, int], None], time_limit: int, ttl: int = 3600 * 4): + """ + :param callback: The callback to call if the time limit is exceeded. + This callback will be called once every "ttl" seconds, + with the parameters "duration" (in seconds) and + "time limit" - representing the passed in time limit. + :param time_limit: The time limit in seconds. + :param ttl: The time to live of the cache in seconds. + """ + self._callback = callback + self._time_limit = time_limit + self.__cache = TTLCache(maxsize=1, ttl=ttl) + + def __enter__(self): + self._start = time.time() + + def __exit__(self, *args): + end = time.time() + if self.__cache.get('value'): + return + duration = end - self._start + + if duration < self._time_limit: + return + self._callback(duration, self._time_limit) + + self.__cache['value'] = True