Edgewall Software

Changes between Initial Version and Version 1 of TracDev/Proposals/AdvancedNotification/INotificationSubscriber


Ignore:
Timestamp:
Oct 12, 2013, 5:06:21 PM (6 years ago)
Author:
Peter Suter
Comment:

Legend:

Unmodified
Added
Removed
Modified
  • TracDev/Proposals/AdvancedNotification/INotificationSubscriber

    v1 v1  
     1== Extension Point : ''INotificationSubscriber'' ==
     2
     3||'''Interface'''||''INotificationSubscriber''||'''Since'''||[wiki:TracDev/ApiChanges/1.1.2#INotificationSubscriber 1.1.2]||
     4||'''Module'''||''trac.notification''||'''Source'''||[source:psuter/trac/notification/api.py@advanced-notification-subscriptions#/INotificationSubscriber api.py]||
     5
     6The ''INotificationSubscriber'' subscribes users to [TracNotification notification] events.
     7
     8== Purpose ==
     9
     10Trac provides an extendible and flexible notification system. Different people are interested in different kinds of notifications. Notification subscriptions allow administrators and / or users to configure the exact rules used that trigger sending of notifications.
     11
     12== Usage ==
     13
     14Implementing the interface follows the standard guidelines found in [wiki:TracDev/ComponentArchitecture] and of course [wiki:TracDev/PluginDevelopment].
     15
     16The main part of this interface is the `match()` function. It returns a list of subscriptions, in the form of tuples consisting of:
     17* `class`: The name of the Python class. (This could probably be removed.)
     18* `distributor`: Also known as `transport`. E.g. the string `email`. See [wiki:TracDev/Proposals/AdvancedNotification/INotificationDistributor INotificationDistributor].
     19* `sid`: The session ID of the subscriber. (Can be `None` if `address` is provided.)
     20* `authenticated`: `1` for authenticated session IDs, `0` for anonymous session IDs.
     21* `address`: The (email) address to use. (Can be `None` if `sid` is provided.)
     22* `format`: The MIME type to be used (e.g. `text/plain` or `text/html`.)
     23* `priority`: An integer priority. Smaller numbers have higher priority than bigger numbers. `1` is the highest priority.
     24* `adverb`: Either the string `always` or `never`.
     25
     26Since more then one component can handle the same realms and categories, the priorities and adverbs are used to resolve conflicting subscriptions.
     27
     28The implementation can use any means to determine if a user is interested in hearing about a given event.
     29Most check that the appropriate conditions apply and then retrieve the required information from the [wiki:TracDev/Proposals/AdvancedNotification/DatabaseSchema#Tablesubscription subscription] DB table.
     30
     31The subscriptions in that table are configured in a shared preferences panel that uses two other methods of this interface:
     32The simple `description()` method returns a description string shown to the user in the preferences panel (or `None` if the plugin does use the `subscriptions` DB table.)
     33The `requires_authentication()` method allows hiding the rule from unauthenticated users. (E.g. because only authenticated users can be ticket owners.)
     34
     35The `default_subscriptions()` method describes any  default subscriptions that automatically exist without the user configuring `subscription` DB entries in the preferences.
     36These are also displayed on the preferences panel, but can not be directly modified there. (They usually can be overriden by non-default subscriptions.)
     37The plugin still has to return the respective subscriptions from the `matches()` method.
     38
     39Default descriptions should be used when users can be determined by the event itself.
     40For instance, ticket author has a default subscription that is controlled via trac.ini.
     41Default subscriptions should be low priority (i.e. have a priority number much larger than `1`, like 100) so that the user can easily override them.
     42
     43== Examples ==
     44
     45The following example implements a simple subscriber that can trigger notifications when a new ticket is created with a high priority level.
     46{{{#!python
     47from trac.core import *
     48from trac.notification.api import INotificationSubscriber
     49from trac.notification.model import Subscription
     50
     51class HighPriorityTicketNotificationSubscriber(Component):
     52
     53    implements(INotificationSubscriber)
     54
     55    # INotificationSubscriber methods
     56
     57    def matches(self, event):
     58        if event.realm != 'ticket':
     59            return
     60        if event.category != 'created':
     61            return
     62
     63        ticket = event.target
     64        if ticket['priority'] not in ('blocker', 'critical', 'major'):
     65            return
     66
     67        klass = self.__class__.__name__
     68        for i in Subscription.find_by_class(self.env, klass):
     69            yield i.subscription_tuple()
     70
     71    def description(self):
     72        return "notify me when new high priority tickets are created"
     73
     74    def requires_authentication(self):
     75        return False
     76}}}
     77
     78== Available Implementations ==
     79
     80Several implementations are part of core Trac:
     81
     82* `trac.ticket.notification.AllTicketSubscriber`\\
     83  Allows anyone to subscribe to all ticket change notifications.
     84* `trac.ticket.notification.TicketOwnerSubscriber`\\
     85  Allows ticket owners to subscribe to (or unsubscribe from) change notifications for owned tickets.
     86* `trac.ticket.notification.TicketComponentOwnerSubscriber`\\
     87  Allows component owners to subscribe to (or unsubscribe from) change notifications for tickets assigned to owned component.
     88* `trac.ticket.notification.TicketUpdaterSubscriber`\\
     89  Allows anyone to subscribe to (or unsubscribe from) change notifications for their own ticket changes.
     90* `trac.ticket.notification.TicketReporterSubscriber`\\
     91  Allows ticket reporters to subscribe to (or unsubscribe from) change notifications for tickets they created.
     92* `trac.ticket.notification.CarbonCopySubscriber`\\
     93  Allows anyone to subscribe to (or unsubscribe from) change notifications for tickets where they are listed in CC.
     94
     95== Additional Information and References ==
     96
     97 * [http://www.edgewall.org/docs/trac-trunk/epydoc/trac.notification.api.INotificationSubscriber-class.html epydoc]
     98 * [http://www.edgewall.org/docs/trac-trunk/html/api/trac_notification.html#trac.notification.api.INotificationSubscriber API Reference]
     99 * The precursor of this interface was `IAnnouncementSubscriber` from the th:AnnouncerPlugin.
     100 * DONE The `IAnnouncementDefaultSubscriber` from the th:AnnouncerPlugin was also folded into this interface.
     101
     102== Open Questions
     103
     104=== Merge `description()` and `requires_authentication()`
     105These methods are both only used in the preferences panel.
     106Merging them could be easier to understand and more flexible, allowing different requirement checks:
     107{{{
     108    def get_subscription_preference_description(self, req):
     109        if req.session.authenticated and 'TICKET_ADMIN' in req.perm:
     110            return "notify me when an admin is needed"
     111}}}
     112
     113=== Remove `class` name
     114The `class` item could be removed from the tuple returned by `matches()`. It's not really needed and clutters up each plugin with ugly `klass = self.__class__.__name__` lines.
     115
     116Counter-arguments:
     117* It helps debugging and can be logged.
     118 * But if that's needed the `NotificationSystem` should do so, to avoid mistakes and simplify plugins.
     119* The [wiki:TracDev/Proposals/AdvancedNotification/DatabaseSchema#Tablesubscription subscription] DB table requires that anyway.
     120 * But it should be replaced there as well, e.g. by a freely chosen `rule` string.