diff --git a/truewiki/storage/git.py b/truewiki/storage/git.py index 19e7745..29ffaaa 100644 --- a/truewiki/storage/git.py +++ b/truewiki/storage/git.py @@ -1,6 +1,7 @@ import asyncio import click import git +import multiprocessing from concurrent import futures from openttd_helpers import click_helper @@ -61,22 +62,24 @@ def prepare(self): super().prepare() try: - self._git = git.Repo(self.folder) + return git.Repo(self.folder) except git.exc.NoSuchPathError: - self._init_repository() + return self._init_repository() except git.exc.InvalidGitRepositoryError: - self._init_repository() + return self._init_repository() def _init_repository(self): - self._git = git.Repo.init(self.folder) + _git = git.Repo.init(self.folder) # Always make sure there is a commit in the working tree, otherwise # HEAD is invalid, which results in other nasty problems. - self._git.index.commit( + _git.index.commit( "Add: initial empty commit", author=git.Actor(GIT_USERNAME, GIT_EMAIL), committer=git.Actor(GIT_USERNAME, GIT_EMAIL), ) + return _git + async def _run_out_of_process(self, folder, ssh_command, callback, func, *args): await GIT_BUSY.wait() GIT_BUSY.clear() @@ -87,7 +90,11 @@ async def _run_out_of_process(self, folder, ssh_command, callback, func, *args): # Run the reload in a new process, so we don't block the rest of the # server while doing this job. loop = asyncio.get_event_loop() - with futures.ProcessPoolExecutor(max_workers=1) as executor: + # Use "spawn" over "fork", as we don't need any variable from our + # current process. This heavily cuts back on memory usage, but it + # takes a bit longer to start up. + mp_context = multiprocessing.get_context("spawn") + with futures.ProcessPoolExecutor(max_workers=1, mp_context=mp_context) as executor: task = loop.run_in_executor(executor, getattr(out_of_process, func), *args) result = await task finally: diff --git a/truewiki/storage/github.py b/truewiki/storage/github.py index a30ba82..0c626ce 100644 --- a/truewiki/storage/github.py +++ b/truewiki/storage/github.py @@ -92,15 +92,17 @@ def __init__(self): self._ssh_command = f"ssh -i {self._github_private_key_file.name}" def prepare(self): - super().prepare() + _git = super().prepare() # Make sure the origin is set correctly - if "origin" not in self._git.remotes: - self._git.create_remote("origin", _github_url) - origin = self._git.remotes.origin + if "origin" not in _git.remotes: + _git.create_remote("origin", _github_url) + origin = _git.remotes.origin if origin.url != _github_url: origin.set_url(_github_url) + return _git + def reload(self): loop = asyncio.get_event_loop() loop.create_task(self._run_out_of_process(self._folder, self._ssh_command, self._reload_done, "fetch_latest"))