mirror of
				https://github.com/dgtlmoon/changedetection.io.git
				synced 2025-10-31 14:47:21 +00:00 
			
		
		
		
	Compare commits
	
		
			5 Commits
		
	
	
		
			flask-upda
			...
			jitter
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 1e11eb898c | ||
|   | 2c6cf78f79 | ||
|   | d7554df0eb | ||
|   | a39ca24e84 | ||
|   | c8b60c2489 | 
| @@ -1274,8 +1274,11 @@ def notification_runner(): | |||||||
|  |  | ||||||
| # Thread runner to check every minute, look for new watches to feed into the Queue. | # Thread runner to check every minute, look for new watches to feed into the Queue. | ||||||
| def ticker_thread_check_time_launch_checks(): | def ticker_thread_check_time_launch_checks(): | ||||||
|  |     import random | ||||||
|     from changedetectionio import update_worker |     from changedetectionio import update_worker | ||||||
|     import logging |  | ||||||
|  |     recheck_time_minimum_seconds = int(os.getenv('MINIMUM_SECONDS_RECHECK_TIME', 20)) | ||||||
|  |     print("System env MINIMUM_SECONDS_RECHECK_TIME", recheck_time_minimum_seconds) | ||||||
|  |  | ||||||
|     # Spin up Workers that do the fetching |     # Spin up Workers that do the fetching | ||||||
|     # Can be overriden by ENV or use the default settings |     # Can be overriden by ENV or use the default settings | ||||||
| @@ -1308,14 +1311,12 @@ def ticker_thread_check_time_launch_checks(): | |||||||
|         while update_q.qsize() >= 2000: |         while update_q.qsize() >= 2000: | ||||||
|             time.sleep(1) |             time.sleep(1) | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         recheck_time_system_seconds = int(datastore.threshold_seconds) | ||||||
|  |  | ||||||
|         # Check for watches outside of the time threshold to put in the thread queue. |         # Check for watches outside of the time threshold to put in the thread queue. | ||||||
|         now = time.time() |  | ||||||
|  |  | ||||||
|         recheck_time_minimum_seconds = int(os.getenv('MINIMUM_SECONDS_RECHECK_TIME', 60)) |  | ||||||
|         recheck_time_system_seconds = datastore.threshold_seconds |  | ||||||
|  |  | ||||||
|         for uuid in watch_uuid_list: |         for uuid in watch_uuid_list: | ||||||
|  |             now = time.time() | ||||||
|             watch = datastore.data['watching'].get(uuid) |             watch = datastore.data['watching'].get(uuid) | ||||||
|             if not watch: |             if not watch: | ||||||
|                 logging.error("Watch: {} no longer present.".format(uuid)) |                 logging.error("Watch: {} no longer present.".format(uuid)) | ||||||
| @@ -1326,20 +1327,33 @@ def ticker_thread_check_time_launch_checks(): | |||||||
|                 continue |                 continue | ||||||
|  |  | ||||||
|             # If they supplied an individual entry minutes to threshold. |             # If they supplied an individual entry minutes to threshold. | ||||||
|             threshold = now |  | ||||||
|             watch_threshold_seconds = watch.threshold_seconds() |  | ||||||
|             if watch_threshold_seconds: |  | ||||||
|                 threshold -= watch_threshold_seconds |  | ||||||
|             else: |  | ||||||
|                 threshold -= recheck_time_system_seconds |  | ||||||
|  |  | ||||||
|             # Yeah, put it in the queue, it's more than time |             watch_threshold_seconds = watch.threshold_seconds() | ||||||
|             if watch['last_checked'] <= max(threshold, recheck_time_minimum_seconds): |             threshold = watch_threshold_seconds if watch_threshold_seconds > 0 else recheck_time_system_seconds | ||||||
|  |  | ||||||
|  |             # #580 - Jitter plus/minus amount of time to make the check seem more random to the server | ||||||
|  |             jitter = datastore.data['settings']['requests'].get('jitter_seconds', 0) | ||||||
|  |             if jitter > 0: | ||||||
|  |                 if watch.jitter_seconds == 0: | ||||||
|  |                     watch.jitter_seconds = random.uniform(-abs(jitter), jitter) | ||||||
|  |  | ||||||
|  |  | ||||||
|  |             seconds_since_last_recheck = now - watch['last_checked'] | ||||||
|  |             if seconds_since_last_recheck >= (threshold + watch.jitter_seconds) and seconds_since_last_recheck >= recheck_time_minimum_seconds: | ||||||
|                 if not uuid in running_uuids and uuid not in update_q.queue: |                 if not uuid in running_uuids and uuid not in update_q.queue: | ||||||
|  |                     print("Queued watch UUID {} last checked at {} queued at {:0.2f} jitter {:0.2f}s, {:0.2f}s since last checked".format(uuid, | ||||||
|  |                                                                                                          watch['last_checked'], | ||||||
|  |                                                                                                          now, | ||||||
|  |                                                                                                          watch.jitter_seconds, | ||||||
|  |                                                                                                          now - watch['last_checked'])) | ||||||
|  |                     # Into the queue with you | ||||||
|                     update_q.put(uuid) |                     update_q.put(uuid) | ||||||
|  |  | ||||||
|         # Wait a few seconds before checking the list again |                     # Reset for next time | ||||||
|         time.sleep(3) |                     watch.jitter_seconds = 0 | ||||||
|  |  | ||||||
|  |         # Wait before checking the list again - saves CPU | ||||||
|  |         time.sleep(1) | ||||||
|  |  | ||||||
|         # Should be low so we can break this out in testing |         # Should be low so we can break this out in testing | ||||||
|         app.config.exit.wait(1) |         app.config.exit.wait(1) | ||||||
| @@ -363,7 +363,9 @@ class watchForm(commonSettingsForm): | |||||||
| class globalSettingsRequestForm(Form): | class globalSettingsRequestForm(Form): | ||||||
|     time_between_check = FormField(TimeBetweenCheckForm) |     time_between_check = FormField(TimeBetweenCheckForm) | ||||||
|     proxy = RadioField('Proxy') |     proxy = RadioField('Proxy') | ||||||
|  |     jitter_seconds = IntegerField('Random jitter seconds ± check', | ||||||
|  |                                   render_kw={"style": "width: 5em;"}, | ||||||
|  |                                   validators=[validators.NumberRange(min=0, message="Should contain zero or more seconds")]) | ||||||
|  |  | ||||||
| # datastore.data['settings']['application'].. | # datastore.data['settings']['application'].. | ||||||
| class globalSettingsApplicationForm(commonSettingsForm): | class globalSettingsApplicationForm(commonSettingsForm): | ||||||
|   | |||||||
| @@ -23,6 +23,7 @@ class model(dict): | |||||||
|                 'requests': { |                 'requests': { | ||||||
|                     'timeout': 15,  # Default 15 seconds |                     'timeout': 15,  # Default 15 seconds | ||||||
|                     'time_between_check': {'weeks': None, 'days': None, 'hours': 3, 'minutes': None, 'seconds': None}, |                     'time_between_check': {'weeks': None, 'days': None, 'hours': 3, 'minutes': None, 'seconds': None}, | ||||||
|  |                     'jitter_seconds': 0, | ||||||
|                     'workers': 10,  # Number of threads, lower is better for slow connections |                     'workers': 10,  # Number of threads, lower is better for slow connections | ||||||
|                     'proxy': None # Preferred proxy connection |                     'proxy': None # Preferred proxy connection | ||||||
|                 }, |                 }, | ||||||
|   | |||||||
| @@ -13,7 +13,6 @@ from changedetectionio.notification import ( | |||||||
| class model(dict): | class model(dict): | ||||||
|     __newest_history_key = None |     __newest_history_key = None | ||||||
|     __history_n=0 |     __history_n=0 | ||||||
|  |  | ||||||
|     __base_config = { |     __base_config = { | ||||||
|             'url': None, |             'url': None, | ||||||
|             'tag': None, |             'tag': None, | ||||||
| @@ -48,7 +47,8 @@ class model(dict): | |||||||
|             'time_between_check': {'weeks': None, 'days': None, 'hours': None, 'minutes': None, 'seconds': None}, |             'time_between_check': {'weeks': None, 'days': None, 'hours': None, 'minutes': None, 'seconds': None}, | ||||||
|             'webdriver_delay': None |             'webdriver_delay': None | ||||||
|         } |         } | ||||||
|  |     jitter_seconds = 0 | ||||||
|  |     mtable = {'seconds': 1, 'minutes': 60, 'hours': 3600, 'days': 86400, 'weeks': 86400 * 7} | ||||||
|     def __init__(self, *arg, **kw): |     def __init__(self, *arg, **kw): | ||||||
|         import uuid |         import uuid | ||||||
|         self.update(self.__base_config) |         self.update(self.__base_config) | ||||||
| @@ -157,8 +157,7 @@ class model(dict): | |||||||
|  |  | ||||||
|     def threshold_seconds(self): |     def threshold_seconds(self): | ||||||
|         seconds = 0 |         seconds = 0 | ||||||
|         mtable = {'seconds': 1, 'minutes': 60, 'hours': 3600, 'days': 86400, 'weeks': 86400 * 7} |         for m, n in self.mtable.items(): | ||||||
|         for m, n in mtable.items(): |  | ||||||
|             x = self.get('time_between_check', {}).get(m, None) |             x = self.get('time_between_check', {}).get(m, None) | ||||||
|             if x: |             if x: | ||||||
|                 seconds += x * n |                 seconds += x * n | ||||||
|   | |||||||
| @@ -9,6 +9,8 @@ | |||||||
| # exit when any command fails | # exit when any command fails | ||||||
| set -e | set -e | ||||||
|  |  | ||||||
|  | export MINIMUM_SECONDS_RECHECK_TIME=0 | ||||||
|  |  | ||||||
| find tests/test_*py -type f|while read test_name | find tests/test_*py -type f|while read test_name | ||||||
| do | do | ||||||
|   echo "TEST RUNNING $test_name" |   echo "TEST RUNNING $test_name" | ||||||
|   | |||||||
| @@ -159,12 +159,11 @@ class ChangeDetectionStore: | |||||||
|     def threshold_seconds(self): |     def threshold_seconds(self): | ||||||
|         seconds = 0 |         seconds = 0 | ||||||
|         mtable = {'seconds': 1, 'minutes': 60, 'hours': 3600, 'days': 86400, 'weeks': 86400 * 7} |         mtable = {'seconds': 1, 'minutes': 60, 'hours': 3600, 'days': 86400, 'weeks': 86400 * 7} | ||||||
|         minimum_seconds_recheck_time = int(os.getenv('MINIMUM_SECONDS_RECHECK_TIME', 60)) |  | ||||||
|         for m, n in mtable.items(): |         for m, n in mtable.items(): | ||||||
|             x = self.__data['settings']['requests']['time_between_check'].get(m) |             x = self.__data['settings']['requests']['time_between_check'].get(m) | ||||||
|             if x: |             if x: | ||||||
|                 seconds += x * n |                 seconds += x * n | ||||||
|         return max(seconds, minimum_seconds_recheck_time) |         return seconds | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def has_unviewed(self): |     def has_unviewed(self): | ||||||
|   | |||||||
| @@ -32,6 +32,11 @@ | |||||||
|                         {{ render_field(form.requests.form.time_between_check, class="time-check-widget") }} |                         {{ render_field(form.requests.form.time_between_check, class="time-check-widget") }} | ||||||
|                         <span class="pure-form-message-inline">Default time for all watches, when the watch does not have a specific time setting.</span> |                         <span class="pure-form-message-inline">Default time for all watches, when the watch does not have a specific time setting.</span> | ||||||
|                     </div> |                     </div> | ||||||
|  |                     <div class="pure-control-group"> | ||||||
|  |                         {{ render_field(form.requests.form.jitter_seconds, class="jitter_seconds") }} | ||||||
|  |                         <span class="pure-form-message-inline">Example - 3 seconds random jitter could trigger up to 3 seconds earlier or up to 3 seconds later</span> | ||||||
|  |                     </div> | ||||||
|  |  | ||||||
|                     <div class="pure-control-group"> |                     <div class="pure-control-group"> | ||||||
|                         {% if not hide_remove_pass %} |                         {% if not hide_remove_pass %} | ||||||
|                             {% if current_user.is_authenticated %} |                             {% if current_user.is_authenticated %} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user