Files
mrleo1nid c8d83b3fe7 feat: add mod editing, revision merges and secure game storage
Add immutable revisions, PGVN editor, asset replacement, merge and rebase workflows, authenticated media delivery and reachability GC. Harden the script interpreter, pin unrpyc and remove tracked build metadata. Include current compatibility checks, Naninovel import and regression tests.
2026-10-25 04:42:48 +03:00

50 lines
1.4 KiB
Python

"""Shared writer leases and exclusive GC on the common data volume."""
import asyncio
import os
from contextlib import asynccontextmanager
from app.config import get_settings
def acquire(exclusive=False):
root = get_settings().data_dir
root.mkdir(parents=True, exist_ok=True)
handle = (root / "maintenance.lock").open("a+b")
try:
if os.name == "nt":
import msvcrt
if handle.tell() == 0:
handle.write(b"0")
handle.flush()
handle.seek(0)
msvcrt.locking(handle.fileno(), msvcrt.LK_LOCK, 1)
else:
import fcntl
fcntl.flock(handle, fcntl.LOCK_EX if exclusive else fcntl.LOCK_SH)
return handle
except BaseException:
handle.close()
raise
def release(handle):
if os.name == "nt":
import msvcrt
handle.seek(0)
msvcrt.locking(handle.fileno(), msvcrt.LK_UNLCK, 1)
handle.close()
@asynccontextmanager
async def storage_access(exclusive=False):
task = asyncio.create_task(asyncio.to_thread(acquire, exclusive))
try:
handle = await asyncio.shield(task)
except asyncio.CancelledError:
task.add_done_callback(lambda done: release(done.result()) if not done.cancelled() and not done.exception() else None)
raise
try:
yield
finally:
release(handle)