Audit the number of SQL queries we make in writing manifests, and significantly reduce in the common case

Instead of 41 queries now for the simple manifest, we are down to 14.

The biggest changes:
  - Only synthesize the V1 image rows if we haven't already found them in the database
  - Thread the repository object through to the other model method calls, and use it instead of loading again and again
This commit is contained in:
Joseph Schorr 2018-01-11 16:25:38 -05:00
parent 4f47808e99
commit 9e16a989f5
8 changed files with 145 additions and 66 deletions

View file

@ -246,13 +246,16 @@ def create_or_update_tag(namespace_name, repository_name, tag_name, tag_docker_i
except Repository.DoesNotExist:
raise DataModelException('Invalid repository %s/%s' % (namespace_name, repository_name))
return create_or_update_tag_for_repo(repo.id, tag_name, tag_docker_image_id, reversion=reversion)
def create_or_update_tag_for_repo(repository_id, tag_name, tag_docker_image_id, reversion=False):
now_ts = get_epoch_timestamp()
with db_transaction():
try:
tag = db_for_update(_tag_alive(RepositoryTag
.select()
.where(RepositoryTag.repository == repo,
.where(RepositoryTag.repository == repository_id,
RepositoryTag.name == tag_name), now_ts)).get()
tag.lifetime_end_ts = now_ts
tag.save()
@ -263,16 +266,17 @@ def create_or_update_tag(namespace_name, repository_name, tag_name, tag_docker_i
raise StaleTagException(msg % tag_name)
try:
image_obj = Image.get(Image.docker_image_id == tag_docker_image_id, Image.repository == repo)
image_obj = Image.get(Image.docker_image_id == tag_docker_image_id,
Image.repository == repository_id)
except Image.DoesNotExist:
raise DataModelException('Invalid image with id: %s' % tag_docker_image_id)
try:
return RepositoryTag.create(repository=repo, image=image_obj, name=tag_name,
return RepositoryTag.create(repository=repository_id, image=image_obj, name=tag_name,
lifetime_start_ts=now_ts, reversion=reversion)
except IntegrityError:
msg = 'Tag with name %s and lifetime start %s under repository %s/%s already exists'
raise TagAlreadyCreatedException(msg % (tag_name, now_ts, namespace_name, repository_name))
msg = 'Tag with name %s and lifetime start %s already exists'
raise TagAlreadyCreatedException(msg % (tag_name, now_ts))
def create_temporary_hidden_tag(repo, image_obj, expiration_s):
@ -504,13 +508,27 @@ def restore_tag_to_image(repo_obj, tag_name, docker_image_id):
return existing_image
def store_tag_manifest(namespace, repo_name, tag_name, docker_image_id, manifest_digest,
def store_tag_manifest(namespace_name, repository_name, tag_name, docker_image_id, manifest_digest,
manifest_data, reversion=False):
""" Stores a tag manifest for a specific tag name in the database. Returns the TagManifest
object, as well as a boolean indicating whether the TagManifest was created.
"""
try:
repo = _basequery.get_existing_repository(namespace_name, repository_name)
except Repository.DoesNotExist:
raise DataModelException('Invalid repository %s/%s' % (namespace_name, repository_name))
return store_tag_manifest_for_repo(repo.id, tag_name, docker_image_id, manifest_digest,
manifest_data, reversion=False)
def store_tag_manifest_for_repo(repository_id, tag_name, docker_image_id, manifest_digest,
manifest_data, reversion=False):
""" Stores a tag manifest for a specific tag name in the database. Returns the TagManifest
object, as well as a boolean indicating whether the TagManifest was created.
"""
with db_transaction():
tag = create_or_update_tag(namespace, repo_name, tag_name, docker_image_id, reversion=reversion)
tag = create_or_update_tag_for_repo(repository_id, tag_name, docker_image_id,
reversion=reversion)
try:
manifest = TagManifest.get(digest=manifest_digest)