diff options
author | Mark McLoughlin <markmc@redhat.com> | 2013-08-21 07:30:49 +0100 |
---|---|---|
committer | Mark McLoughlin <markmc@redhat.com> | 2013-08-21 07:30:49 +0100 |
commit | 361092a48805e3dedc79ff0f8a18bdc6f35d9e8e (patch) | |
tree | 48f84945676a5917d2151db8174450f9f2c8eae1 | |
parent | 0555e939be67f1001fd92e7d5b444d95eed51f14 (diff) | |
download | oslo-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.py | 56 | ||||
-rw-r--r-- | tests/test_notifier.py | 22 |
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, |