Fix the deadlock in tags.
This commit is contained in:
parent
d973f9df45
commit
6c4e78ec0c
1 changed files with 16 additions and 22 deletions
|
@ -1580,25 +1580,16 @@ def list_repository_tags(namespace_name, repository_name, include_hidden=False):
|
||||||
|
|
||||||
|
|
||||||
def _garbage_collect_tags(namespace_name, repository_name):
|
def _garbage_collect_tags(namespace_name, repository_name):
|
||||||
inner = (RepositoryTag
|
# We do this without using a join to prevent holding read locks on the repository table
|
||||||
.select(RepositoryTag.id,
|
repo = _get_repository(namespace_name, repository_name)
|
||||||
RepositoryTag.lifetime_end_ts,
|
now = int(time.time())
|
||||||
RepositoryTag.repository)
|
|
||||||
.alias('rt'))
|
|
||||||
to_delete = (RepositoryTag
|
|
||||||
.select(inner.c.id)
|
|
||||||
.from_(inner)
|
|
||||||
.join(Repository, on=(inner.c.repository_id == Repository.id))
|
|
||||||
.join(Namespace, on=(Repository.namespace_user == Namespace.id))
|
|
||||||
.where(Repository.name == repository_name, Namespace.username == namespace_name,
|
|
||||||
~(inner.c.lifetime_end_ts >> None),
|
|
||||||
(inner.c.lifetime_end_ts + Namespace.removed_tag_expiration_s) <=
|
|
||||||
int(time.time())))
|
|
||||||
|
|
||||||
(RepositoryTag
|
(RepositoryTag
|
||||||
.delete()
|
.delete()
|
||||||
.where(RepositoryTag.id << to_delete)
|
.where(RepositoryTag.repository == repo,
|
||||||
.execute())
|
~(RepositoryTag.lifetime_end_ts >> None),
|
||||||
|
(RepositoryTag.lifetime_end_ts + repo.namespace_user.removed_tag_expiration_s) <= now)
|
||||||
|
.execute())
|
||||||
|
|
||||||
|
|
||||||
def garbage_collect_repository(namespace_name, repository_name):
|
def garbage_collect_repository(namespace_name, repository_name):
|
||||||
|
@ -1798,20 +1789,23 @@ def create_or_update_tag(namespace_name, repository_name, tag_name,
|
||||||
|
|
||||||
now_ts = int(time.time())
|
now_ts = int(time.time())
|
||||||
|
|
||||||
|
created = RepositoryTag.create(repository=repo, image=image, name=tag_name,
|
||||||
|
lifetime_start_ts=now_ts)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# When we move a tag, we really end the timeline of the old one and create a new one
|
# When we move a tag, we really end the timeline of the old one and create a new one
|
||||||
query = _tag_alive(RepositoryTag
|
query = _tag_alive(RepositoryTag
|
||||||
.select()
|
.select()
|
||||||
.where(RepositoryTag.repository == repo, RepositoryTag.name == tag_name))
|
.where(RepositoryTag.repository == repo, RepositoryTag.name == tag_name,
|
||||||
tag = db_for_update(query).get()
|
RepositoryTag.id != created.id))
|
||||||
|
tag = query.get()
|
||||||
tag.lifetime_end_ts = now_ts
|
tag.lifetime_end_ts = now_ts
|
||||||
tag.save()
|
tag.save()
|
||||||
except RepositoryTag.DoesNotExist:
|
except RepositoryTag.DoesNotExist:
|
||||||
# No tag that needs to be ended
|
# No tag that needs to be ended
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return RepositoryTag.create(repository=repo, image=image, name=tag_name,
|
return created
|
||||||
lifetime_start_ts=now_ts)
|
|
||||||
|
|
||||||
|
|
||||||
def delete_tag(namespace_name, repository_name, tag_name):
|
def delete_tag(namespace_name, repository_name, tag_name):
|
||||||
|
|
Reference in a new issue