Skip to content

Adds 60 second disk cache for unauthenticated indexes. #111

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/manage/install_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@
else:
LOGGER.verbose("Searching for default Python version")

downloader = IndexDownloader(source, Index, {}, DOWNLOAD_CACHE)
downloader = IndexDownloader(source, Index, {}, DOWNLOAD_CACHE, None if cmd.force else cmd.download_dir)

Check warning on line 393 in src/manage/install_command.py

View check run for this annotation

Codecov / codecov/patch

src/manage/install_command.py#L393

Added line #L393 was not covered by tests
install = select_package(downloader, tag, cmd.default_platform, by_id=by_id)

if by_id:
Expand Down
2 changes: 1 addition & 1 deletion src/manage/list_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ def execute(cmd):
from .urlutils import IndexDownloader
try:
installs = _get_installs_from_index(
IndexDownloader(cmd.source, Index),
IndexDownloader(cmd.source, Index, disk_cache=cmd.download_dir),
tags,
)
except OSError as ex:
Expand Down
35 changes: 34 additions & 1 deletion src/manage/urlutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -625,20 +625,46 @@


class IndexDownloader:
def __init__(self, source, index_cls, auth=None, cache=None):
def __init__(self, source, index_cls, auth=None, cache=None, disk_cache=None):
self.index_cls = index_cls
self._url = source.rstrip("/")
if not self._url.casefold().endswith(".json".casefold()):
self._url += "/index.json"
self._auth = auth if auth is not None else {}
self._cache = cache if cache is not None else {}
self._disk_cache = Path(disk_cache) if disk_cache is not None else None

Check warning on line 635 in src/manage/urlutils.py

View check run for this annotation

Codecov / codecov/patch

src/manage/urlutils.py#L635

Added line #L635 was not covered by tests
self._urlopen = urlopen
self._used_auth = False

Check warning on line 637 in src/manage/urlutils.py

View check run for this annotation

Codecov / codecov/patch

src/manage/urlutils.py#L637

Added line #L637 was not covered by tests

def _use_disk_cache(self, url, data=None):
if not self._disk_cache:
return None
try:

Check warning on line 642 in src/manage/urlutils.py

View check run for this annotation

Codecov / codecov/patch

src/manage/urlutils.py#L641-L642

Added lines #L641 - L642 were not covered by tests
if extract_url_auth(url):
return None
except OSError:
return None
from hashlib import sha256
from time import time
path = self._disk_cache / (sha256(url.encode("utf-8", "unicodeescape")).hexdigest() + ".cache")

Check warning on line 649 in src/manage/urlutils.py

View check run for this annotation

Codecov / codecov/patch

src/manage/urlutils.py#L644-L649

Added lines #L644 - L649 were not covered by tests
if data:
path.parent.mkdir(parents=True, exist_ok=True)
path.write_bytes(data)
return
try:

Check warning on line 654 in src/manage/urlutils.py

View check run for this annotation

Codecov / codecov/patch

src/manage/urlutils.py#L651-L654

Added lines #L651 - L654 were not covered by tests
if time() - path.lstat().st_mtime < 60:
return path.read_bytes()
path.unlink()
return None
except OSError:
return None

Check warning on line 660 in src/manage/urlutils.py

View check run for this annotation

Codecov / codecov/patch

src/manage/urlutils.py#L656-L660

Added lines #L656 - L660 were not covered by tests

def __iter__(self):
return self

def on_auth(self, url):
# TODO: Try looking for parent paths from URL
self._used_auth = True

Check warning on line 667 in src/manage/urlutils.py

View check run for this annotation

Codecov / codecov/patch

src/manage/urlutils.py#L667

Added line #L667 was not covered by tests
try:
return self._auth[url]
except LookupError:
Expand All @@ -658,14 +684,21 @@
except LookupError:
data = None

data = self._use_disk_cache(url)

Check warning on line 687 in src/manage/urlutils.py

View check run for this annotation

Codecov / codecov/patch

src/manage/urlutils.py#L687

Added line #L687 was not covered by tests
if data:
LOGGER.debug("Fetched from disk cache")

Check warning on line 689 in src/manage/urlutils.py

View check run for this annotation

Codecov / codecov/patch

src/manage/urlutils.py#L689

Added line #L689 was not covered by tests

if not data:
try:
self._used_auth = False

Check warning on line 693 in src/manage/urlutils.py

View check run for this annotation

Codecov / codecov/patch

src/manage/urlutils.py#L693

Added line #L693 was not covered by tests
data = self._cache[url] = self._urlopen(
url,
"GET",
{"Accepts": "application/json"},
on_auth_request=self.on_auth,
)
if not self._used_auth:
self._use_disk_cache(url, data)

Check warning on line 701 in src/manage/urlutils.py

View check run for this annotation

Codecov / codecov/patch

src/manage/urlutils.py#L701

Added line #L701 was not covered by tests
except FileNotFoundError: # includes 404
LOGGER.error("Unable to find runtimes index at %s", sanitise_url(url))
raise
Expand Down