-
Notifications
You must be signed in to change notification settings - Fork 1
Feature/bwdo 809 implement lock clone cache #68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,7 +18,9 @@ | |
| import shutil | ||
| import subprocess | ||
| import sys | ||
| import time | ||
|
|
||
| from filelock import FileLock, Timeout | ||
| from pydantic import BaseModel | ||
|
|
||
| from .cloner import Cloner, RefType | ||
|
|
@@ -29,6 +31,8 @@ | |
| logger = logging.getLogger(__name__) | ||
|
|
||
| REPO_CACHE_DIR = Path.home() / ".caches" | ||
| CACHE_LOCK_PATH = REPO_CACHE_DIR / ".lock" | ||
| CACHE_MAX_WAIT = 600 | ||
|
|
||
| class RepoClonerConfig(BaseModel): | ||
| """ | ||
|
|
@@ -74,8 +78,42 @@ def clone(self, directory: Path): | |
| - Parses the manifest to retrieve projects. | ||
| - Initializes GitFlow for all unlocked projects. | ||
| """ | ||
| reference = self._cache() if self.config.cache else None | ||
| if self.config.cache: | ||
| self._clone_with_cache(directory) | ||
| else: | ||
| self._clone(directory) | ||
|
|
||
| def _clone_with_cache(self, directory: Path): | ||
| REPO_CACHE_DIR.mkdir(exist_ok=True) | ||
|
|
||
| started = time.monotonic() | ||
| lock = FileLock(CACHE_LOCK_PATH) | ||
|
|
||
| logger.info("Acquiring cache lock.") | ||
| while True: | ||
| try: | ||
| lock.acquire(timeout=20) | ||
| break | ||
| except Timeout: | ||
| waited = int(time.monotonic() - started) | ||
| if waited < CACHE_MAX_WAIT: | ||
| logger.info( | ||
| f"Cache is in use by another process, waited {waited} seconds..." | ||
| ) | ||
|
BenjiMilan marked this conversation as resolved.
|
||
| else: | ||
| logger.error( | ||
| f"Cache remained locked past the set wait time of {CACHE_MAX_WAIT} seconds." | ||
| ) | ||
| sys.exit(1) | ||
|
Comment on lines
+89
to
+107
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm pretty sure old SC would clear the lock if you reached the 5 min timeout. We should probably do that. Also does this library handle the lock if it was there since before the start of the sc process, like when a clone gets killed halfway through and the lock is never cleared. Then the user tries to clone again? |
||
| logger.info("Cache lock acquired.") | ||
|
|
||
| try: | ||
| reference = self._cache() | ||
| self._clone(directory, reference) | ||
| finally: | ||
| lock.release() | ||
|
|
||
| def _clone(self, directory: Path, reference: Path | None = None): | ||
| self._init_repo(directory=directory, reference=reference) | ||
| RepoLibrary.sync( | ||
| directory, | ||
|
|
@@ -95,7 +133,6 @@ def _cache(self) -> Path: | |
| Returns: | ||
| Path: The directory of the mirrored cache. | ||
| """ | ||
| REPO_CACHE_DIR.mkdir(exist_ok=True) | ||
| manifest_hostname = self._get_manifest_hostname(self.config.uri) | ||
| host_cache_dir = Path(REPO_CACHE_DIR / manifest_hostname) | ||
| host_cache_dir.mkdir(exist_ok=True) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be better to call the lock
.sc_lock. I doubt we'll ever re-use the cache in the future, but alwaty nicer to know where the lock came from.