packages/reflex-cache: send redirect to upstream cache on first fetch
This commit is contained in:
parent
1754841832
commit
226fc6da9a
3 changed files with 36 additions and 26 deletions
|
@ -10,9 +10,9 @@ class IPFSController:
|
||||||
self.__nix = nixCache
|
self.__nix = nixCache
|
||||||
self.__db = db
|
self.__db = db
|
||||||
|
|
||||||
def ipfs_fetch_task(self, nar):
|
def ipfs_fetch_task(self, callback, nar, hint=None):
|
||||||
print(f"Downloading NAR: {nar}")
|
print(f"Downloading NAR: {nar}")
|
||||||
code, content = self.__nix.try_all("get", nar)
|
code, _, content = self.__nix.try_all("get", nar, hint)
|
||||||
if code == 200:
|
if code == 200:
|
||||||
upload = {"file": ("FILE", content, "application/octet-stream")}
|
upload = {"file": ("FILE", content, "application/octet-stream")}
|
||||||
try:
|
try:
|
||||||
|
@ -22,9 +22,12 @@ class IPFSController:
|
||||||
hash = rIpfs.json()["Hash"]
|
hash = rIpfs.json()["Hash"]
|
||||||
print(f"Mapped: {nar} -> /ipfs/{hash}")
|
print(f"Mapped: {nar} -> /ipfs/{hash}")
|
||||||
self.__db.set_path(nar, hash)
|
self.__db.set_path(nar, hash)
|
||||||
|
callback()
|
||||||
return (nar, 200, hash)
|
return (nar, 200, hash)
|
||||||
except requests.ConnectionError as e:
|
except requests.ConnectionError as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
callback()
|
||||||
return (nar, 502, False)
|
return (nar, 502, False)
|
||||||
else:
|
else:
|
||||||
|
callback()
|
||||||
return (nar, code, False)
|
return (nar, code, False)
|
||||||
|
|
|
@ -10,7 +10,7 @@ class NixCacheFetcher:
|
||||||
self.__caches = caches
|
self.__caches = caches
|
||||||
|
|
||||||
@lru_cache(maxsize=32768)
|
@lru_cache(maxsize=32768)
|
||||||
def __try_all_cached(self, method, path):
|
def __try_all_cached(self, method, path, hint):
|
||||||
fn = (
|
fn = (
|
||||||
requests.get
|
requests.get
|
||||||
if method == "get"
|
if method == "get"
|
||||||
|
@ -22,7 +22,13 @@ class NixCacheFetcher:
|
||||||
bestState = 404
|
bestState = 404
|
||||||
|
|
||||||
print(f" fetching [{method}] from any cache {path}")
|
print(f" fetching [{method}] from any cache {path}")
|
||||||
for cache in self.__caches:
|
if hint != None:
|
||||||
|
caches = []
|
||||||
|
caches.append(hint)
|
||||||
|
caches.extend(self.__caches)
|
||||||
|
else:
|
||||||
|
caches = self.__caches
|
||||||
|
for cache in caches:
|
||||||
try:
|
try:
|
||||||
rCache = fn(f"{cache}{path}")
|
rCache = fn(f"{cache}{path}")
|
||||||
if rCache.status_code < bestState:
|
if rCache.status_code < bestState:
|
||||||
|
@ -30,7 +36,7 @@ class NixCacheFetcher:
|
||||||
|
|
||||||
print(f" {rCache.status_code} - [{method}] {cache}{path}")
|
print(f" {rCache.status_code} - [{method}] {cache}{path}")
|
||||||
if bestState == 200:
|
if bestState == 200:
|
||||||
r = (bestState, rCache.content if method != "head" else False)
|
r = (bestState, cache, rCache.content if method != "head" else False)
|
||||||
if path.endswith(".narinfo"):
|
if path.endswith(".narinfo"):
|
||||||
return r
|
return r
|
||||||
else:
|
else:
|
||||||
|
@ -40,10 +46,10 @@ class NixCacheFetcher:
|
||||||
|
|
||||||
# HACK: lru_cache does not cache results if an exception occurs
|
# 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
|
# since we don't want to cache empty query results, we make use of this behavior
|
||||||
raise Uncached((bestState, False))
|
raise Uncached((bestState, None, False))
|
||||||
|
|
||||||
def try_all(self, method, path):
|
def try_all(self, method, path, hint=None):
|
||||||
try:
|
try:
|
||||||
return self.__try_all_cached(method, path)
|
return self.__try_all_cached(method, path, hint)
|
||||||
except Uncached as r:
|
except Uncached as r:
|
||||||
return r.args[0]
|
return r.args[0]
|
||||||
|
|
|
@ -27,7 +27,7 @@ class ReflexHTTPServiceHandler(BaseHTTPRequestHandler):
|
||||||
def do_HEAD(self):
|
def do_HEAD(self):
|
||||||
if self.path.endswith(".narinfo"):
|
if self.path.endswith(".narinfo"):
|
||||||
print(f"NAR info request: {self.path}")
|
print(f"NAR info request: {self.path}")
|
||||||
code, content = self._nix.try_all("head", self.path)
|
code, _, content = self._nix.try_all("head", self.path)
|
||||||
self.send_response(code)
|
self.send_response(code)
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
else:
|
else:
|
||||||
|
@ -45,6 +45,15 @@ class ReflexHTTPServiceHandler(BaseHTTPRequestHandler):
|
||||||
resultHash = self._db.get_path(self.path)
|
resultHash = self._db.get_path(self.path)
|
||||||
|
|
||||||
if resultHash == None:
|
if resultHash == None:
|
||||||
|
code, cache, _ = self._nix.try_all("head", self.path)
|
||||||
|
if code == 200:
|
||||||
|
self.send_response(302)
|
||||||
|
self.send_header("Location", f"{cache}{self.path}")
|
||||||
|
self.end_headers()
|
||||||
|
else:
|
||||||
|
self.send_response(404)
|
||||||
|
self.end_headers()
|
||||||
|
return
|
||||||
with self._workSetLock:
|
with self._workSetLock:
|
||||||
found = False
|
found = False
|
||||||
for (itemNar, itemFuture) in self._workSet:
|
for (itemNar, itemFuture) in self._workSet:
|
||||||
|
@ -58,25 +67,17 @@ class ReflexHTTPServiceHandler(BaseHTTPRequestHandler):
|
||||||
|
|
||||||
if not found:
|
if not found:
|
||||||
print(f"Creating new IPFS fetch task for {self.path}")
|
print(f"Creating new IPFS fetch task for {self.path}")
|
||||||
|
def cb():
|
||||||
|
with self._workSetLock:
|
||||||
|
try:
|
||||||
|
self._workSet.remove((self.path, f))
|
||||||
|
except KeyError:
|
||||||
|
# already removed
|
||||||
|
pass
|
||||||
f = self._executor_nar.submit(
|
f = self._executor_nar.submit(
|
||||||
self._ipfs.ipfs_fetch_task, self.path
|
self._ipfs.ipfs_fetch_task, cb, self.path, cache
|
||||||
)
|
)
|
||||||
self._workSet.add((self.path, f))
|
self._workSet.add((self.path, f))
|
||||||
|
|
||||||
resultNar, code, resultHash = f.result()
|
|
||||||
|
|
||||||
with self._workSetLock:
|
|
||||||
try:
|
|
||||||
self._workSet.remove((self.path, f))
|
|
||||||
except KeyError:
|
|
||||||
# already removed
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
code = 200
|
|
||||||
|
|
||||||
if code != 200:
|
|
||||||
self.send_response(code)
|
|
||||||
self.end_headers()
|
|
||||||
return
|
return
|
||||||
|
|
||||||
self.send_response(302)
|
self.send_response(302)
|
||||||
|
@ -104,7 +105,7 @@ class ReflexHTTPServiceHandler(BaseHTTPRequestHandler):
|
||||||
|
|
||||||
elif self.path.endswith(".narinfo"):
|
elif self.path.endswith(".narinfo"):
|
||||||
print(f"NAR info request: {self.path}")
|
print(f"NAR info request: {self.path}")
|
||||||
code, content = self._nix.try_all("get", self.path)
|
code, _, content = self._nix.try_all("get", self.path)
|
||||||
self.send_response(code)
|
self.send_response(code)
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
if code == 200:
|
if code == 200:
|
||||||
|
|
Loading…
Reference in a new issue