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:
parent
770b457430
commit
1caa2e0287
@ -5,10 +5,12 @@
|
|||||||
import inspect
|
import inspect
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
|
import uuid
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
|
||||||
# Django
|
# Django
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.core.cache import cache
|
||||||
from django.db import connection
|
from django.db import connection
|
||||||
from django.db.models.fields import FieldDoesNotExist
|
from django.db.models.fields import FieldDoesNotExist
|
||||||
from django.db.models.fields.related import OneToOneRel
|
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():
|
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)
|
new_obj.admin_role.members.add(request.user)
|
||||||
if sub_objs:
|
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
|
permission_check_func = None
|
||||||
if hasattr(type(self), 'deep_copy_permission_check_func'):
|
if hasattr(type(self), 'deep_copy_permission_check_func'):
|
||||||
permission_check_func = (
|
permission_check_func = (
|
||||||
@ -980,7 +987,7 @@ class CopyAPIView(GenericAPIView):
|
|||||||
)
|
)
|
||||||
trigger_delayed_deep_copy(
|
trigger_delayed_deep_copy(
|
||||||
self.model.__module__, self.model.__name__,
|
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
|
permission_check_func=permission_check_func
|
||||||
)
|
)
|
||||||
serializer = self._get_copy_return_serializer(new_obj)
|
serializer = self._get_copy_return_serializer(new_obj)
|
||||||
|
@ -2856,8 +2856,13 @@ def _reconstruct_relationships(copy_mapping):
|
|||||||
@task(queue=get_local_queuename)
|
@task(queue=get_local_queuename)
|
||||||
def deep_copy_model_obj(
|
def deep_copy_model_obj(
|
||||||
model_module, model_name, obj_pk, new_obj_pk,
|
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))
|
logger.debug('Deep copy {} from {} to {}.'.format(model_name, obj_pk, new_obj_pk))
|
||||||
from awx.api.generics import CopyAPIView
|
from awx.api.generics import CopyAPIView
|
||||||
from awx.main.signals import disable_activity_stream
|
from awx.main.signals import disable_activity_stream
|
||||||
|
Loading…
Reference in New Issue
Block a user