Update release check to use django-redis

This commit is contained in:
jeremystretch 2021-07-07 20:57:47 -04:00
parent d9e27b6a82
commit 2c023ef7a0
3 changed files with 17 additions and 60 deletions

View File

@ -1,7 +1,7 @@
import logging
from cacheops import CacheMiss, cache
from django.conf import settings
from django.core.cache import cache
from django_rq import get_queue
from utilities.background_tasks import get_releases
@ -12,12 +12,11 @@ logger = logging.getLogger('netbox.releases')
def get_latest_release(pre_releases=False):
if settings.RELEASE_CHECK_URL:
logger.debug("Checking for most recent release")
try:
latest_release = cache.get('latest_release')
if latest_release:
logger.debug("Found cached release: {}".format(latest_release))
return latest_release
except CacheMiss:
latest_release = cache.get('latest_release')
if latest_release:
logger.debug(f"Found cached release: {latest_release}")
return latest_release
else:
# Check for an existing job. This can happen if the RQ worker process is not running.
queue = get_queue('check_releases')
if queue.jobs:

View File

@ -3,8 +3,8 @@ from logging import ERROR
from unittest.mock import Mock, patch
import requests
from cacheops import CacheMiss, RedisCache
from django.conf import settings
from django.core.cache import cache
from django.test import SimpleTestCase, override_settings
from packaging.version import Version
from requests import Response
@ -60,10 +60,8 @@ def unsuccessful_github_response(url, *_args, **_kwargs):
@override_settings(RELEASE_CHECK_URL='https://localhost/unittest/releases', RELEASE_CHECK_TIMEOUT=160876)
class GetReleasesTestCase(SimpleTestCase):
@patch.object(requests, 'get')
@patch.object(RedisCache, 'set')
@patch.object(RedisCache, 'get')
def test_pre_releases(self, dummy_cache_get: Mock, dummy_cache_set: Mock, dummy_request_get: Mock):
dummy_cache_get.side_effect = CacheMiss()
@patch.object(cache, 'set')
def test_pre_releases(self, dummy_cache_set: Mock, dummy_request_get: Mock):
dummy_request_get.side_effect = successful_github_response
releases = get_releases(pre_releases=True)
@ -90,10 +88,8 @@ class GetReleasesTestCase(SimpleTestCase):
)
@patch.object(requests, 'get')
@patch.object(RedisCache, 'set')
@patch.object(RedisCache, 'get')
def test_no_pre_releases(self, dummy_cache_get: Mock, dummy_cache_set: Mock, dummy_request_get: Mock):
dummy_cache_get.side_effect = CacheMiss()
@patch.object(cache, 'set')
def test_no_pre_releases(self, dummy_cache_set: Mock, dummy_request_get: Mock):
dummy_request_get.side_effect = successful_github_response
releases = get_releases(pre_releases=False)
@ -119,10 +115,7 @@ class GetReleasesTestCase(SimpleTestCase):
)
@patch.object(requests, 'get')
@patch.object(RedisCache, 'set')
@patch.object(RedisCache, 'get')
def test_failed_request(self, dummy_cache_get: Mock, dummy_cache_set: Mock, dummy_request_get: Mock):
dummy_cache_get.side_effect = CacheMiss()
def test_failed_request(self, dummy_request_get: Mock):
dummy_request_get.side_effect = unsuccessful_github_response
with self.assertLogs(level=ERROR) as cm:
@ -143,28 +136,3 @@ class GetReleasesTestCase(SimpleTestCase):
headers={'Accept': 'application/vnd.github.v3+json'},
proxies=settings.HTTP_PROXIES
)
# Check if failure is put in cache
dummy_cache_set.assert_called_once_with(
'latest_release_no_retry',
'https://localhost/unittest/releases',
900
)
@patch.object(requests, 'get')
@patch.object(RedisCache, 'set')
@patch.object(RedisCache, 'get')
def test_blocked_retry(self, dummy_cache_get: Mock, dummy_cache_set: Mock, dummy_request_get: Mock):
dummy_cache_get.return_value = 'https://localhost/unittest/releases'
dummy_request_get.side_effect = successful_github_response
releases = get_releases()
# Check result
self.assertListEqual(releases, [])
# Check if request is NOT made
dummy_request_get.assert_not_called()
# Check if cache is not updated
dummy_cache_set.assert_not_called()

View File

@ -1,8 +1,8 @@
import logging
import requests
from cacheops.simple import cache, CacheMiss
from django.conf import settings
from django.core.cache import cache
from django_rq import job
from packaging import version
@ -18,16 +18,8 @@ def get_releases(pre_releases=False):
}
releases = []
# Check whether this URL has failed recently and shouldn't be retried yet
try:
if url == cache.get('latest_release_no_retry'):
logger.info("Skipping release check; URL failed recently: {}".format(url))
return []
except CacheMiss:
pass
try:
logger.debug("Fetching new releases from {}".format(url))
logger.info(f"Fetching new releases from {url}")
response = requests.get(url, headers=headers, proxies=settings.HTTP_PROXIES)
response.raise_for_status()
total_releases = len(response.json())
@ -38,12 +30,10 @@ def get_releases(pre_releases=False):
if not pre_releases and (release.get('devrelease') or release.get('prerelease')):
continue
releases.append((version.parse(release['tag_name']), release.get('html_url')))
logger.debug("Found {} releases; {} usable".format(total_releases, len(releases)))
logger.debug(f"Found {total_releases} releases; {len(releases)} usable")
except requests.exceptions.RequestException:
# The request failed. Set a flag in the cache to disable future checks to this URL for 15 minutes.
logger.exception("Error while fetching {}. Disabling checks for 15 minutes.".format(url))
cache.set('latest_release_no_retry', url, 900)
except requests.exceptions.RequestException as exc:
logger.exception(f"Error while fetching latest release from {url}: {exc}")
return []
# Cache the most recent release