Don't store connection pool in RpcContext.
Fix bug 934575. As Chris pointed out in the bug, there is a downside to this approach to fixing the bug, in that a manager will no longer be able to use context.reply(). However, it wasn't being used at all, and it's no loss in functionality. A remote method can still return multiple values (in response to a multicall()) by using yield. Change-Id: I0e5aff2e8a40ffd8390c0e19d89dd17e60a74130
This commit is contained in:
@@ -160,18 +160,18 @@ class RpcContext(context.RequestContext):
|
|||||||
"""Context that supports replying to a rpc.call"""
|
"""Context that supports replying to a rpc.call"""
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.msg_id = kwargs.pop('msg_id', None)
|
self.msg_id = kwargs.pop('msg_id', None)
|
||||||
self.connection_pool = kwargs.pop('connection_pool', None)
|
|
||||||
super(RpcContext, self).__init__(*args, **kwargs)
|
super(RpcContext, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
def reply(self, reply=None, failure=None, ending=False):
|
def reply(self, reply=None, failure=None, ending=False,
|
||||||
|
connection_pool=None):
|
||||||
if self.msg_id:
|
if self.msg_id:
|
||||||
msg_reply(self.msg_id, self.connection_pool, reply, failure,
|
msg_reply(self.msg_id, connection_pool, reply, failure,
|
||||||
ending)
|
ending)
|
||||||
if ending:
|
if ending:
|
||||||
self.msg_id = None
|
self.msg_id = None
|
||||||
|
|
||||||
|
|
||||||
def unpack_context(msg, connection_pool):
|
def unpack_context(msg):
|
||||||
"""Unpack context from msg."""
|
"""Unpack context from msg."""
|
||||||
context_dict = {}
|
context_dict = {}
|
||||||
for key in list(msg.keys()):
|
for key in list(msg.keys()):
|
||||||
@@ -182,7 +182,6 @@ def unpack_context(msg, connection_pool):
|
|||||||
value = msg.pop(key)
|
value = msg.pop(key)
|
||||||
context_dict[key[9:]] = value
|
context_dict[key[9:]] = value
|
||||||
context_dict['msg_id'] = msg.pop('_msg_id', None)
|
context_dict['msg_id'] = msg.pop('_msg_id', None)
|
||||||
context_dict['connection_pool'] = connection_pool
|
|
||||||
ctx = RpcContext.from_dict(context_dict)
|
ctx = RpcContext.from_dict(context_dict)
|
||||||
LOG.debug(_('unpacked context: %s'), ctx.to_dict())
|
LOG.debug(_('unpacked context: %s'), ctx.to_dict())
|
||||||
return ctx
|
return ctx
|
||||||
@@ -228,12 +227,13 @@ class ProxyCallback(object):
|
|||||||
if hasattr(local.store, 'context'):
|
if hasattr(local.store, 'context'):
|
||||||
del local.store.context
|
del local.store.context
|
||||||
rpc_common._safe_log(LOG.debug, _('received %s'), message_data)
|
rpc_common._safe_log(LOG.debug, _('received %s'), message_data)
|
||||||
ctxt = unpack_context(message_data, self.connection_pool)
|
ctxt = unpack_context(message_data)
|
||||||
method = message_data.get('method')
|
method = message_data.get('method')
|
||||||
args = message_data.get('args', {})
|
args = message_data.get('args', {})
|
||||||
if not method:
|
if not method:
|
||||||
LOG.warn(_('no method for message: %s') % message_data)
|
LOG.warn(_('no method for message: %s') % message_data)
|
||||||
ctxt.reply(_('No method for message: %s') % message_data)
|
ctxt.reply(_('No method for message: %s') % message_data,
|
||||||
|
connection_pool=self.connection_pool)
|
||||||
return
|
return
|
||||||
self.pool.spawn_n(self._process_data, ctxt, method, args)
|
self.pool.spawn_n(self._process_data, ctxt, method, args)
|
||||||
|
|
||||||
@@ -251,14 +251,15 @@ class ProxyCallback(object):
|
|||||||
# Check if the result was a generator
|
# Check if the result was a generator
|
||||||
if inspect.isgenerator(rval):
|
if inspect.isgenerator(rval):
|
||||||
for x in rval:
|
for x in rval:
|
||||||
ctxt.reply(x, None)
|
ctxt.reply(x, None, connection_pool=self.connection_pool)
|
||||||
else:
|
else:
|
||||||
ctxt.reply(rval, None)
|
ctxt.reply(rval, None, connection_pool=self.connection_pool)
|
||||||
# This final None tells multicall that it is done.
|
# This final None tells multicall that it is done.
|
||||||
ctxt.reply(ending=True)
|
ctxt.reply(ending=True, connection_pool=self.connection_pool)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
LOG.exception('Exception during message handling')
|
LOG.exception('Exception during message handling')
|
||||||
ctxt.reply(None, sys.exc_info())
|
ctxt.reply(None, sys.exc_info(),
|
||||||
|
connection_pool=self.connection_pool)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -52,13 +52,6 @@ class _BaseRpcTestCase(test.TestCase):
|
|||||||
"args": {"value": value}})
|
"args": {"value": value}})
|
||||||
self.assertEqual(value, result)
|
self.assertEqual(value, result)
|
||||||
|
|
||||||
def test_call_succeed_despite_multiple_returns(self):
|
|
||||||
value = 42
|
|
||||||
result = self.rpc.call(self.context, 'test',
|
|
||||||
{"method": "echo_three_times",
|
|
||||||
"args": {"value": value}})
|
|
||||||
self.assertEqual(value + 2, result)
|
|
||||||
|
|
||||||
def test_call_succeed_despite_multiple_returns_yield(self):
|
def test_call_succeed_despite_multiple_returns_yield(self):
|
||||||
value = 42
|
value = 42
|
||||||
result = self.rpc.call(self.context, 'test',
|
result = self.rpc.call(self.context, 'test',
|
||||||
@@ -77,15 +70,6 @@ class _BaseRpcTestCase(test.TestCase):
|
|||||||
self.fail('should only receive one response')
|
self.fail('should only receive one response')
|
||||||
self.assertEqual(value + i, x)
|
self.assertEqual(value + i, x)
|
||||||
|
|
||||||
def test_multicall_succeed_three_times(self):
|
|
||||||
value = 42
|
|
||||||
result = self.rpc.multicall(self.context,
|
|
||||||
'test',
|
|
||||||
{"method": "echo_three_times",
|
|
||||||
"args": {"value": value}})
|
|
||||||
for i, x in enumerate(result):
|
|
||||||
self.assertEqual(value + i, x)
|
|
||||||
|
|
||||||
def test_multicall_three_nones(self):
|
def test_multicall_three_nones(self):
|
||||||
value = 42
|
value = 42
|
||||||
result = self.rpc.multicall(self.context,
|
result = self.rpc.multicall(self.context,
|
||||||
@@ -209,13 +193,6 @@ class TestReceiver(object):
|
|||||||
LOG.debug(_("Received %s"), context)
|
LOG.debug(_("Received %s"), context)
|
||||||
return context.to_dict()
|
return context.to_dict()
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def echo_three_times(context, value):
|
|
||||||
context.reply(value)
|
|
||||||
context.reply(value + 1)
|
|
||||||
context.reply(value + 2)
|
|
||||||
context.reply(ending=True)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def multicall_three_nones(context, value):
|
def multicall_three_nones(context, value):
|
||||||
yield None
|
yield None
|
||||||
|
|||||||
Reference in New Issue
Block a user