From 6b98fdac81586f5c1b2972d8ba39e01eee0b76a8 Mon Sep 17 00:00:00 2001 From: Kieran Prasch Date: Wed, 14 Oct 2020 10:23:10 -0700 Subject: [PATCH] Sprinkles a little randomness on work tracker intervals --- nucypher/blockchain/eth/token.py | 22 +++++++++++-------- .../blockchain/actors/test_worker.py | 2 +- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/nucypher/blockchain/eth/token.py b/nucypher/blockchain/eth/token.py index cf17e19de..26734ec19 100644 --- a/nucypher/blockchain/eth/token.py +++ b/nucypher/blockchain/eth/token.py @@ -14,7 +14,7 @@ GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with nucypher. If not, see . """ - +import random from _pydecimal import Decimal from collections import UserList from enum import Enum @@ -526,19 +526,16 @@ def validate_increase(stake: Stake, amount: NU) -> None: class WorkTracker: CLOCK = reactor - REFRESH_RATE = 60 * 15 # Fifteen minutes + INTERVAL_FLOOR = 60 * 15 # fifteen minutes + INTERVAL_CEIL = 60 * 180 # three hours - def __init__(self, - worker, - refresh_rate: int = None, - *args, **kwargs): + def __init__(self, worker, *args, **kwargs): super().__init__(*args, **kwargs) self.log = Logger('stake-tracker') self.worker = worker self.staking_agent = self.worker.staking_agent - self._refresh_rate = refresh_rate or self.REFRESH_RATE self._tracking_task = task.LoopingCall(self._do_work) self._tracking_task.clock = self.CLOCK @@ -548,6 +545,10 @@ class WorkTracker: self.__uptime_period = NOT_STAKING self._abort_on_error = True + @classmethod + def random_interval(cls) -> int: + return random.randint(cls.INTERVAL_FLOOR, cls.INTERVAL_CEIL) + @property def current_period(self): return self.__current_period @@ -575,7 +576,7 @@ class WorkTracker: self.__current_period = self.__uptime_period self.log.info(f"START WORK TRACKING") - d = self._tracking_task.start(interval=self._refresh_rate, now=act_now) + d = self._tracking_task.start(interval=self.random_interval(), now=act_now) d.addErrback(self.handle_working_errors) def _crash_gracefully(self, failure=None) -> None: @@ -609,8 +610,11 @@ class WorkTracker: return r def _do_work(self) -> None: - # TODO: #1515 Shut down at end of terminal stake + # Randomize the task interval over time, within bounds. + self._tracking_task.interval = self.random_interval() + + # TODO: #1515 Shut down at end of terminal stake # Update on-chain status self.log.info(f"Checking for new period. Current period is {self.__current_period}") onchain_period = self.staking_agent.get_current_period() # < -- Read from contract diff --git a/tests/acceptance/blockchain/actors/test_worker.py b/tests/acceptance/blockchain/actors/test_worker.py index 041ba095a..8463c6e2e 100644 --- a/tests/acceptance/blockchain/actors/test_worker.py +++ b/tests/acceptance/blockchain/actors/test_worker.py @@ -69,7 +69,7 @@ def test_worker_auto_commitments(mocker, def time_travel(_): testerchain.time_travel(periods=1) - clock.advance(WorkTracker.REFRESH_RATE+1) + clock.advance(WorkTracker.INTERVAL_CEIL + 1) return clock def verify(clock):