Skip to content

Notifications

Saray Cabrera Padrón edited this page Nov 17, 2022 · 28 revisions

Details about our notification sub-system.

Workflow

  • An Event gets stored in the database
  • clockwork periodically schedules a SendEventEmailsJob every 30 seconds.
  • SendEventEmailsJob goes over the Event table and
    • EventMailer sends email about Event that have a email EventSubscription
    • NotificationService::Notifier creates Notification for all Event that have web/rss EventSubscription
    • Once done Event.mails_sent is set to true so the event subsystem knows we are done and can clean up after itself.

Event

An Event describes things that happen throughout the whole OBS. See the Events documentation for details.

EventSubscription

People subscribe to an event by creating an instance of EventSubscription in the database.

A subscription is specific for a User, a Group, a type of Event (eventtype=Event::CommentForPackage), a Role the User might have (receiver_role="maintainer") and the place where it should be displayed (channel=web, channel=instant_email)

The code below will, for instance, create an email subscription for the user henne for all Event::BuildFail events, concerning packages henne is maintainer of.

EventSubscription.create(eventtype: "Event::BuildFail",
                         receiver_role: "maintainer",
                         user: User.find_by(login: 'henne'),
                         channel: "instant_email",
                         enabled: true)

App Wide Default Subscriptions

All EventSubscription instances that have neither the user nor the group attribute set are considered for all users and groups. Those defaults can only be created by OBS admins via the UI. In a fresh OBS installation there are no instances of EventSubscription.

Finding people subscribed to an Event

EventSubscription does not have a direct association with events. OBS uses EventSubscription::FindForEvent to find people who have subscribed to an event.

EventSubscription::FindForEvent.new(@event).subscriptions(:instant_email)

The process looks like that:

  • For each Role (e.g. commenter, maintainer etc.), find all the people that possibly would get a notification
  • Filter out the people that don't have a subscription for this type of Event, Role and "channel"
    • Also consider the default app wide default subscriptions
  • Skip the event originator because we consider this too much noise
  • Return all subscribers

SendEventEmailsJob then uses those subscriptions to decide whom to notify.

Notifications

A Notification collects information about

  • an Event
  • that happened to a thing (BsRequest, Comment etc.) in OBS (notifiable association)
  • other things in OBS (Project or Group) involved with the notifiable (notified_projects, group associations)
  • a channel to display the notification on (rss=true, web=false attributes)
  • people (User or Group) to display them to (subscriber association)

The code below will, for instance, create a web notification for the user henne, concerning henne home project.

Notification.create(title: 'A comment was made for home:henne',
                    event_type: 'Event::CommentForProject',
                    event_payload: {pay: :load},
                    subscriber: User.find_by(login: 'henne'),
                    subscription_receiver_role: 'maintainer',
                    notifiable: Project.find_by(name: 'home:henne'),
                    web: true

All notifications are created with the help of SendEventEmailsJob (yes this is a bad name and should change 😞). This job is using classes in the NotificationService module to create Notification. Depending on the subscription channel a bit different.

Creating Notification for the web UI channel

NotificationService::WebChannel.new(@event, @subscription).call
  1. As we only display the latest state of thing the notification is about we find the existing notifications for the notifiable and delete them
  2. Create/Update the Notification and it's associations

Creating Notification for the RSS channel

NotificationService::RSSChannel.new(@event, @subscription).call
  1. Create the Notification and it's associations if it does not exist

Viewing the Notifications

The UI/API then uses the rich data the Notification collected to display/filter what's going on in OBS for people on /my/notifications

Notification UI

Process Notifications When Testing

If you somehow need to process any pending notifications, execute SendEventEmailsJob.new.perform_now in a Rails console. This is especially useful when testing changes in the notifications feature after you've generated a few events like writing a comment in a request or adding a reviewer to a request.

Create Notifications in Your Development Environment

When working on the notifications feature, it's helpful to have a few notifications for the My Notifications page. You can generate them by executing the following commands in your Docker development environment:

  1. bundle exec rake dev:test_data:create (This will reset your development database and setup the Admin user)
  2. bundle exec rake dev:notifications:data[2] (This will create notifications for the Admin user)
Clone this wiki locally