1
0
mirror of https://github.com/ansible/awx.git synced 2024-10-30 13:55:31 +03:00

work around a limitation in postgres notify to properly support copying

postgres has a limitation on its notify message size (8k), and the
messages we generate for deep copying functionality easily go over this
limit; instead of passing a giant nested data structure across the
message bus, this change makes it so that we temporarily store the JSON
structure in memcached, and look it up from *within* the task

see: https://github.com/ansible/tower/issues/4162
This commit is contained in:
Ryan Petrello 2020-03-02 16:35:06 -05:00
parent 770b457430
commit 1caa2e0287
No known key found for this signature in database
GPG Key ID: F2AA5F2122351777
2 changed files with 14 additions and 2 deletions

View File

@ -5,10 +5,12 @@
import inspect
import logging
import time
import uuid
import urllib.parse
# Django
from django.conf import settings
from django.core.cache import cache
from django.db import connection
from django.db.models.fields import FieldDoesNotExist
from django.db.models.fields.related import OneToOneRel
@ -973,6 +975,11 @@ class CopyAPIView(GenericAPIView):
if hasattr(new_obj, 'admin_role') and request.user not in new_obj.admin_role.members.all():
new_obj.admin_role.members.add(request.user)
if sub_objs:
# store the copied object dict into memcached, because it's
# often too large for postgres' notification bus
# (which has a default maximum message size of 8k)
key = 'deep-copy-{}'.format(str(uuid.uuid4()))
cache.set(key, sub_objs, timeout=3600)
permission_check_func = None
if hasattr(type(self), 'deep_copy_permission_check_func'):
permission_check_func = (
@ -980,7 +987,7 @@ class CopyAPIView(GenericAPIView):
)
trigger_delayed_deep_copy(
self.model.__module__, self.model.__name__,
obj.pk, new_obj.pk, request.user.pk, sub_objs,
obj.pk, new_obj.pk, request.user.pk, key,
permission_check_func=permission_check_func
)
serializer = self._get_copy_return_serializer(new_obj)

View File

@ -2856,8 +2856,13 @@ def _reconstruct_relationships(copy_mapping):
@task(queue=get_local_queuename)
def deep_copy_model_obj(
model_module, model_name, obj_pk, new_obj_pk,
user_pk, sub_obj_list, permission_check_func=None
user_pk, uuid, permission_check_func=None
):
sub_obj_list = cache.get(uuid)
if sub_obj_list is None:
logger.error('Deep copy {} from {} to {} failed unexpectedly.'.format(model_name, obj_pk, new_obj_pk))
return
logger.debug('Deep copy {} from {} to {}.'.format(model_name, obj_pk, new_obj_pk))
from awx.api.generics import CopyAPIView
from awx.main.signals import disable_activity_stream