Implement PUT chunk uploads, 16MiB chunk size for faster transfers with resilient retries and smoother progress

This commit is contained in:
Leo Vasanko
2026-04-25 01:08:21 +00:00
parent 88a032acfe
commit 76c928a24c
3 changed files with 370 additions and 109 deletions
+38 -4
View File
@@ -1,5 +1,6 @@
import asyncio
import os
import threading
from cista import config
from cista.util import filename
@@ -69,6 +70,8 @@ class FileServer:
self.alink.to_sync,
)
self.cache = LRUCache(File, capacity=10, maxage=5.0)
self.cache_lock = threading.Lock()
self.file_locks: dict[str, threading.Lock] = {}
async def stop(self):
await self.alink.stop()
@@ -80,6 +83,8 @@ class FileServer:
with req as (command, *args):
if command == "upload":
req.set_result(self.upload(*args))
elif command == "upload_info":
req.set_result(self.upload_info(*args))
elif command == "download":
req.set_result(self.download(*args))
else:
@@ -87,13 +92,42 @@ class FileServer:
finally:
self.cache.close()
@staticmethod
def _stat_size(path):
try:
return os.stat(path).st_size
except FileNotFoundError:
return None
def upload(self, name, pos, data, file_size):
name = filename.sanitize(name)
f = self.cache[name]
f.write(pos, data, file_size=file_size)
with self.cache_lock:
f = self.cache[name]
lock = self.file_locks.setdefault(name, threading.Lock())
with lock:
f.write(pos, data, file_size=file_size)
return len(data)
def upload_info(self, name, pos, data, file_size):
name = filename.sanitize(name)
with self.cache_lock:
f = self.cache[name]
lock = self.file_locks.setdefault(name, threading.Lock())
with lock:
size_before = self._stat_size(f.path)
f.write(pos, data, file_size=file_size)
size_after = self._stat_size(f.path)
return {
"written": len(data),
"created": size_before is None,
"size_before": size_before,
"size_after": size_after,
}
def download(self, name, start, end):
name = filename.sanitize(name)
f = self.cache[name]
return f[start:end]
with self.cache_lock:
f = self.cache[name]
lock = self.file_locks.setdefault(name, threading.Lock())
with lock:
return f[start:end]