2022-02-26 01:48:16 +02:00
|
|
|
from functools import lru_cache
|
|
|
|
|
|
|
|
import requests
|
|
|
|
|
|
|
|
from reflex_cache.util import Uncached
|
|
|
|
|
|
|
|
|
|
|
|
class NixCacheFetcher:
|
|
|
|
def __init__(self, caches):
|
|
|
|
self.__caches = caches
|
|
|
|
|
|
|
|
@lru_cache(maxsize=32768)
|
2022-12-19 00:05:29 +02:00
|
|
|
def __try_all_cached(self, method, path, hint):
|
2022-03-02 00:59:31 +02:00
|
|
|
fn = (
|
|
|
|
requests.get
|
|
|
|
if method == "get"
|
|
|
|
else requests.head
|
|
|
|
if method == "head"
|
|
|
|
else Exception("invalid method")
|
|
|
|
)
|
2022-02-26 01:48:16 +02:00
|
|
|
|
|
|
|
bestState = 404
|
|
|
|
|
|
|
|
print(f" fetching [{method}] from any cache {path}")
|
2022-12-19 00:05:29 +02:00
|
|
|
if hint != None:
|
|
|
|
caches = []
|
|
|
|
caches.append(hint)
|
|
|
|
caches.extend(self.__caches)
|
|
|
|
else:
|
|
|
|
caches = self.__caches
|
|
|
|
for cache in caches:
|
2022-02-26 01:48:16 +02:00
|
|
|
try:
|
|
|
|
rCache = fn(f"{cache}{path}")
|
|
|
|
if rCache.status_code < bestState:
|
|
|
|
bestState = rCache.status_code
|
|
|
|
|
|
|
|
print(f" {rCache.status_code} - [{method}] {cache}{path}")
|
|
|
|
if bestState == 200:
|
2022-12-19 00:05:29 +02:00
|
|
|
r = (bestState, cache, rCache.content if method != "head" else False)
|
2022-02-26 01:48:16 +02:00
|
|
|
if path.endswith(".narinfo"):
|
|
|
|
return r
|
|
|
|
else:
|
|
|
|
raise Uncached(r)
|
|
|
|
except requests.ConnectionError as e:
|
|
|
|
print(e)
|
|
|
|
|
|
|
|
# HACK: lru_cache does not cache results if an exception occurs
|
|
|
|
# since we don't want to cache empty query results, we make use of this behavior
|
2022-12-19 00:05:29 +02:00
|
|
|
raise Uncached((bestState, None, False))
|
2022-02-26 01:48:16 +02:00
|
|
|
|
2022-12-19 00:05:29 +02:00
|
|
|
def try_all(self, method, path, hint=None):
|
2022-02-26 01:48:16 +02:00
|
|
|
try:
|
2022-12-19 00:05:29 +02:00
|
|
|
return self.__try_all_cached(method, path, hint)
|
2022-02-26 01:48:16 +02:00
|
|
|
except Uncached as r:
|
|
|
|
return r.args[0]
|