Skip to content

Commit

Permalink
Add local lock to ensure 2 tasks aren't making changes to the local d…
Browse files Browse the repository at this point in the history
…irectory at the same time
  • Loading branch information
dgarros committed Dec 19, 2024
1 parent 9fffe68 commit a2230fe
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 2 deletions.
18 changes: 18 additions & 0 deletions backend/infrahub/git/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
from infrahub.git.constants import BRANCHES_DIRECTORY_NAME, COMMITS_DIRECTORY_NAME, TEMPORARY_DIRECTORY_NAME
from infrahub.git.directory import get_repositories_directory, initialize_repositories_directory
from infrahub.git.worktree import Worktree
from infrahub.lock import LOCAL_REPO_LOCK
from infrahub.lock import registry as lock_registry
from infrahub.log import get_logger
from infrahub.services import InfrahubServices # noqa: TCH001

Expand Down Expand Up @@ -306,13 +308,24 @@ def validate_local_directories(self) -> bool:

async def create_locally(
self, checkout_ref: str | None = None, infrahub_branch_name: str | None = None, update_commit_value: bool = True
) -> bool:
async with lock_registry.get(name=LOCAL_REPO_LOCK, namespace=self.name, local=True):
return await self._create_locally(
checkout_ref=checkout_ref,
infrahub_branch_name=infrahub_branch_name,
update_commit_value=update_commit_value,
)

async def _create_locally(
self, checkout_ref: str | None = None, infrahub_branch_name: str | None = None, update_commit_value: bool = True
) -> bool:
"""Ensure the required directory already exist in the filesystem or create them if needed.
Returns
True if the directory has been created,
False if the directory was already present.
"""

initialize_repositories_directory()

if not self.location:
Expand Down Expand Up @@ -653,6 +666,11 @@ async def validate_remote_branch(self, branch_name: str) -> bool:

async def pull(self, branch_name: str) -> Union[bool, str]:
"""Pull the latest update from the remote repository on a given branch."""
async with lock_registry.get(name=LOCAL_REPO_LOCK, namespace=self.name, local=True):
return await self._pull_unsafe(branch_name=branch_name)

async def _pull_unsafe(self, branch_name: str) -> Union[bool, str]:
"""Pull the latest update from the remote repository on a given branch."""

if not self.has_origin:
return False
Expand Down
5 changes: 3 additions & 2 deletions backend/infrahub/git/integrator.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,9 @@ async def init(cls, commit: str | None = None, service: InfrahubServices | None
await self.ensure_location_is_defined()
await self.create_locally(infrahub_branch_name=self.infrahub_branch_name, update_commit_value=False)
service.log.info(f"Initialized the local directory for {self.name} because it was missing.")
if commit:
self.get_commit_worktree(commit=commit)

if commit:
self.get_commit_worktree(commit=commit)

service.log.debug(
f"Initiated the object on an existing directory for {self.name}",
Expand Down
10 changes: 10 additions & 0 deletions backend/infrahub/git/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
from infrahub.core.constants import InfrahubKind, RepositoryInternalStatus
from infrahub.exceptions import RepositoryError
from infrahub.git.integrator import InfrahubRepositoryIntegrator
from infrahub.lock import LOCAL_REPO_LOCK
from infrahub.lock import registry as lock_registry
from infrahub.log import get_logger
from infrahub.services import InfrahubServices

Expand Down Expand Up @@ -94,6 +96,10 @@ async def create_branch_in_git(
return True

async def sync(self, staging_branch: str | None = None) -> None:
async with lock_registry.get(name=LOCAL_REPO_LOCK, namespace=self.name, local=True):
return await self._sync_unsafe(staging_branch=staging_branch)

async def _sync_unsafe(self, staging_branch: str | None = None) -> None:
"""Synchronize the repository with its remote origin and with the database.
By default the sync will focus only on the branches pulled from origin that have some differences with the local one.
Expand Down Expand Up @@ -275,6 +281,10 @@ def get_commit_value(self, branch_name: str, remote: bool = False) -> str:
return str(commit)

async def sync_from_remote(self, commit: str | None = None) -> None:
async with lock_registry.get(name=LOCAL_REPO_LOCK, namespace=self.name, local=True):
return await self._sync_from_remote_unsafe(commit=commit)

async def _sync_from_remote_unsafe(self, commit: str | None = None) -> None:
if not commit:
commit = self.get_commit_value(branch_name=self.ref, remote=True)
local_branches = self.get_branches_from_local()
Expand Down
1 change: 1 addition & 0 deletions backend/infrahub/lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
)

LOCAL_SCHEMA_LOCK = "local.schema"
LOCAL_REPO_LOCK = "local.repository"
GLOBAL_INIT_LOCK = "global.init"
GLOBAL_SCHEMA_LOCK = "global.schema"
GLOBAL_GRAPH_LOCK = "global.graph"
Expand Down

0 comments on commit a2230fe

Please sign in to comment.