summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark McLoughlin <markmc@redhat.com>2013-08-21 07:30:49 +0100
committerMark McLoughlin <markmc@redhat.com>2013-08-21 07:30:49 +0100
commit361092a48805e3dedc79ff0f8a18bdc6f35d9e8e (patch)
tree48f84945676a5917d2151db8174450f9f2c8eae1
parent0555e939be67f1001fd92e7d5b444d95eed51f14 (diff)
downloadoslo-messaging-361092a48805e3dedc79ff0f8a18bdc6f35d9e8e.tar.gz
Add a Notifier.prepare() method1.2.0a10
Nova sends notifications with a bunch of different publisher_ids, so we instantiate quite a lot of Notifier objects. Loading the noification drivers for each of these is a substantial amount of overhead. One obvious answer would be to make publisher_id an argument to the error(), info(), etc. methods, but I think it's nice to encapsulate the publisher_id in a notifier instance. Instead, add a prepare() method which mirrors the approach in RPCClient. You use this method to create a specialized notifier instance with a new publisher_id. Change-Id: Ia45fda3164086bb7a9ef6dee0587f726ab8b1a97
-rw-r--r--oslo/messaging/notify/notifier.py56
-rw-r--r--tests/test_notifier.py22
2 files changed, 70 insertions, 8 deletions
diff --git a/oslo/messaging/notify/notifier.py b/oslo/messaging/notify/notifier.py
index 66f23f3..e250053 100644
--- a/oslo/messaging/notify/notifier.py
+++ b/oslo/messaging/notify/notifier.py
@@ -60,7 +60,7 @@ class Notifier(object):
The Notifier class is used for sending notification messages over a
messaging transport or other means.
- Notification messages follow the following format:
+ Notification messages follow the following format::
{'message_id': str(uuid.uuid4()),
'publisher_id': 'compute.host1',
@@ -72,22 +72,29 @@ class Notifier(object):
A Notifier object can be instantiated with a transport object and a
publisher ID:
- notifier = notifier.Notifier(get_transport(CONF), 'compute.host1')
+ notifier = notifier.Notifier(get_transport(CONF), 'compute')
and notifications are sent via drivers chosen with the notification_driver
config option and on the topics consen with the notification_topics config
option.
Alternatively, a Notifier object can be instantiated with a specific
- driver or topic:
+ driver or topic::
notifier = notifier.Notifier(RPC_TRANSPORT,
'compute.host',
driver='messaging',
topic='notifications')
+
+ Notifier objects are relatively expensive to instantiate (mostly the cost
+ of loading notification drivers), so it is possible to specialize a given
+ Notifier object with a different publisher id using the prepare() method::
+
+ notifier = notifier.prepare(publisher_id='compute')
+ notifier.info(ctxt, event_type, payload)
"""
- def __init__(self, transport, publisher_id,
+ def __init__(self, transport, publisher_id=None,
driver=None, topic=None,
serializer=None):
"""Construct a Notifier object.
@@ -127,12 +134,26 @@ class Notifier(object):
},
)
- def _notify(self, ctxt, event_type, payload, priority):
+ _marker = object()
+
+ def prepare(self, publisher_id=_marker):
+ """Return a specialized Notifier instance.
+
+ Returns a new Notifier instance with the supplied publisher_id. Allows
+ sending notifications from multiple publisher_ids without the overhead
+ of notification driver loading.
+
+ :param publisher_id: field in notifications sent, e.g. 'compute.host1'
+ :type publisher_id: str
+ """
+ return _SubNotifier._prepare(self, publisher_id)
+
+ def _notify(self, ctxt, event_type, payload, priority, publisher_id=None):
payload = self._serializer.serialize_entity(ctxt, payload)
ctxt = self._serializer.serialize_context(ctxt)
msg = dict(message_id=uuidutils.generate_uuid(),
- publisher_id=self.publisher_id,
+ publisher_id=publisher_id or self.publisher_id,
event_type=event_type,
priority=priority,
payload=payload,
@@ -208,3 +229,26 @@ class Notifier(object):
:type payload: dict
"""
self._notify(ctxt, event_type, payload, 'CRITICAL')
+
+
+class _SubNotifier(Notifier):
+
+ _marker = Notifier._marker
+
+ def __init__(self, base, publisher_id):
+ self._base = base
+ self.conf = base.conf
+ self.transport = base.transport
+ self.publisher_id = publisher_id
+
+ self._serializer = self._base._serializer
+ self._driver_mgr = self._base._driver_mgr
+
+ def _notify(self, ctxt, event_type, payload, priority):
+ super(_SubNotifier, self)._notify(ctxt, event_type, payload, priority)
+
+ @classmethod
+ def _prepare(cls, base, publisher_id=_marker):
+ if publisher_id is cls._marker:
+ publisher_id = base.publisher_id
+ return cls(base, publisher_id)
diff --git a/tests/test_notifier.py b/tests/test_notifier.py
index 6ee2842..2b32383 100644
--- a/tests/test_notifier.py
+++ b/tests/test_notifier.py
@@ -82,6 +82,16 @@ class TestMessagingNotifier(test_utils.BaseTestCase):
('not_v2', dict(v2=False)),
]
+ _publisher_id = [
+ ('ctor_pub_id', dict(ctor_pub_id='test',
+ expected_pub_id='test')),
+ ('prep_pub_id', dict(prep_pub_id='test.localhost',
+ expected_pub_id='test.localhost')),
+ ('override', dict(ctor_pub_id='test',
+ prep_pub_id='test.localhost',
+ expected_pub_id='test.localhost')),
+ ]
+
_topics = [
('no_topics', dict(topics=[])),
('single_topic', dict(topics=['notifications'])),
@@ -108,6 +118,7 @@ class TestMessagingNotifier(test_utils.BaseTestCase):
def generate_scenarios(cls):
cls.scenarios = testscenarios.multiply_scenarios(cls._v1,
cls._v2,
+ cls._publisher_id,
cls._topics,
cls._priority,
cls._payload,
@@ -136,7 +147,14 @@ class TestMessagingNotifier(test_utils.BaseTestCase):
transport = _FakeTransport(self.conf)
- notifier = messaging.Notifier(transport, 'test.localhost')
+ if hasattr(self, 'ctor_pub_id'):
+ notifier = messaging.Notifier(transport,
+ publisher_id=self.ctor_pub_id)
+ else:
+ notifier = messaging.Notifier(transport)
+
+ if hasattr(self, 'prep_pub_id'):
+ notifier = notifier.prepare(publisher_id=self.prep_pub_id)
self.mox.StubOutWithMock(transport, '_send_notification')
@@ -148,7 +166,7 @@ class TestMessagingNotifier(test_utils.BaseTestCase):
message = {
'message_id': str(message_id),
- 'publisher_id': 'test.localhost',
+ 'publisher_id': self.expected_pub_id,
'event_type': 'test.notify',
'priority': self.priority.upper(),
'payload': self.payload,