Source Code Repository

Introduction

A framework for customizable news feeds for various entity kinds that can be formatted on various site pages. Each newsfeed includes a subscription link, and through a ‘subscribe’ url pattern is used to render XML feeds.

Because of the relatively simple nature of the initial project, some of the post-midterm development will include an auxiliary open source pubsub component meant to be deployed separately, and act as a hub allowing Melange instances to host chat, Google Wave updates, and other real-time activity.

Newsfeed Model

An individual FeedItem entity is created for each news feed update. A garbage collection task will delete old feed items, so they don't take over the datastore.

The FeedItem model contains the following properties:

  • sender (db.Key) - The sender is the entity that was updated

  • receivers (db.Key) - A list of entities whose news feed is being updated.

  • update_type (created, deleted, modified)

  • created (datetime)

A FeedItem is created for each sender-receiver pair. For instance, if a document is created and saved, it is the sender while its associated project and program and user could all be receivers.

Access Protection

Very basic entity information (a title/name and a link) is shown in the Recent Updates box and the ATOM feed. This may violate access protection, and the alternative is to just show the name of the entity kind, or a truncated title.

Because the mail subscriptions are privately sent on a per-user basis, they contain more detailed information about the updated entity.

Logic

Newsfeed logic consists of two public methods:

  • addToFeed takes a sender entity, a list of receiver entities, an update type, and an optional payload (like a text preview of a document). It adds all the receivers to a FeedItem with the specified payload:
    for receiver in receivers:
      new_feed_item = soc.models.news_feed.FeedItem( 
      sender_key= str(sender.key()),     
      receiver_key = str(receiver.key()),
      user = user,
      update_type = update_type
      )
  • retrieveFeed takes a receiever entity, and retrieves it's latest news feed updates, with an optional count kwarg. This method is cached, with a cache handler in the /cache folder.
  def retrieveFeed(self, entity, count=10):
    """ Retrieves feed for a given entity 
    """
    feed_items = soc.models.news_feed.FeedItem.all().filter(
    "receiver_key =", str(entity.key())).fetch(1000)
    return feed_items[:count]

Views

The newsfeed template itself is simply a table modeled after the blog template that lists each news feed update, which is added to the context dict through the retrieveFeed method.

Subscribe via RSS

I've added a new url_path ‘subscribe’, so that a URL for requesting an ATOM feed would look like this:

http://melange.appspot.com/site/subscribe/somesite

The new URL pattern is configured in soc.views.helper.params:

  if params.get('subscribe'):
    new_params['django_patterns_defaults'] += [
        (r'^%(url_name)s/(?P<access_type>subscribe)/%(key_fields)s$',
         '%(module_package)s.%(module_name)s.subscribe', 
         'Subscribe to %(name_plural)s')]

This address is added to pages with a meta tag:

<link rel=“alternate” type=“application/rss+xml” title=“RSS” href=“{{ feed_url }}”/>

There is also a graphic subscribe icon on the corner of the newsfeed GUI module.

The ‘subscribe’ path will also be the interface for any PubSub interactions, but those will only be activated on POST requests with a callback URL, otherwise the ATOM feed will be returned as normal.

Notification Integration

The notifications module has been in need of work, and I've refactored it so that it has two new beneficial features:

  • Deploy to multiple contexts (the newsfeed widget, an ATOM feed for the user w/ pubsub support, and information-enriched private e-mails).

  • Any entity with a newsfeed can now be referenced in the notification so that that entity's newsfeed will be updated, etc.

Notification TODO

Refactor access handler to be able to perform reflective rights-based queries. Improve notifications front-end Licensing issues for images? Improve e-mail format to take better advantage of entity-tagging in notes. Tag multiple entities in notification.

E-mail Tasks

When a feed item is created, it schedules a handler to send out e-mail notification. This handler calls the sendFeedItemEmailNotifications method that fetches a list of users who are subscribed to the sender entity and e-mails them.

E-mails are now each sent via the mail_dispatcher task. Since it is very common to get OverQuotaErrors, this task API should always be used for sending e-mails.

User Subscriptions

The subscriptions model contains a relational index entity for the user, containing a list of entity keys that the user is subscribed to. From their edit_profile page, the user can set a global preference for whether they are accepting e-mail notifications, and the user can also configure individual entity preferences from those pages using the subscribe-by-star UI pattern.

PubSubHubbub Support

This demo demonstrates Google Reader updating in seconds after a blog is updated.

It should be fairly trivial to integrate push notification support, and abstract it so that it could also be accessed by other Melange features.

TODO

Subscription Handler

The subscriptions logic contains an UpdateLogic class that is meant to automatically compile a list of users with read-access to an arbitrary entity. Unfortunately, setting subscriptions manually is the only option right now, since the automatic subscription handler is not nearly where I hoped it would be by now. The idea is very simple - just subscribe users to the entities where they have read-access. But the reality has been much more difficult to do without creating an entirely new infrastructure, and I'm entertaining the idea of simply relying on a manual interface (subscribe-by-star). The takeaway from this is that perhaps the access component should be abstracted to a high-level API, because it appears to have gained dependencies and complexities that prevent it from being useful to the news feed logic.

Post Commit Hooks

Since most soc projects involve a code repository, it would be useful to allow repository commits to enter the news feed. This is already possible through using an RSS feed, but real-time updates could be generated by using the Google Code Post Commit Hook Support:

http://code.google.com/p/support/wiki/PostCommitWebHooks

This would require project owners to change a setting on their projects, and would be fairly easy to implement.