Hide menu Last updated: Jun 01 2017
Area: Episerver Social Applies to versions: 1.4 and higher
Other versions:

Activity streams: Activities

Activities signify an event or action occurring within your application. The Episerver Social platform allows for activities to be published, within an application, resulting in the generation of corresponding feed items for subscribing users. It also provides the opportunity for your application to react to these activities in real-time.

An activity is represented in the system using the Activity class.

Identifying an actor and target

An Activity identifies both an actor and a target:

  • Actor. User who triggered activity.
  • Target. Resource or user upon which the activity occurred.

The actor is identified with an instance of the Reference class.

The target is also identified with an instance of the Reference class, which may represent a resource, such as a page or product or a user within your application.

The scheme applied to define these target and references is designed within your application.

For more information on how to construct References, including best practices, see References and IDs.

Designing an activity

The Activity Streams feature leverages the platform's concept of Composites, providing developers with complete control over the design of their application's activities.

Activities published within the platform are accompanied by data of your design. This data, intended to encapsulate information defining the particular activity that occurred, is available upon retrieval of feeds for subscribing users.

For example, an application wants to broadcast an announcement to interested users whenever a product is rated. The application adds an activity representing this action through the Activity Streams system, resulting in the generation of feed items for subscribing users and the notification of handlers registered to react to the event in real-time.

An example of a class definition, representing the activity of rating a page, appears below.

public class PageRated 
    {
        public int Rating { get; set; }

        public string UserName { get; set; }

        public string PageId { get; set; }

        public string PageName { get; set; }
    }

For information and best practices on designing such types, see Defining extension data.

Managing activities

In the Episerver Social platform, activities are managed through a service implementing the interface IActivityService. This service provides the ability to add and respond to activities in your application.

Accessing an IActivityService

When the Activity Streams feature is installed to an Episerver CMS site, with the feature's site integration package, you can get an instance of this service from the inversion of control (IoC) container.

Example:

var activityService = EPiServer.ServiceLocation.ServiceLocator.Current.GetInstance<IActivityService>();

When the feature is installed to a non-Episerver CMS site, you can get an instance of a service from the default factory class provided within the package.

Example:

var factory = new EPiServer.Social.ActivityStreams.DefaultActivityStreamsFactory();
var activityService = factory.CreateActivityService();

Adding an activity

You can publish an activity to the Episerver Social Activity Streams system by using the Add<TExtension>(Activity,TExtension) method of the IActivityService. This method accepts an instance of the Activity class and an instance of TExtension. TExtension is a type, defined within your application, used to describe the activity that occurred.

When the system receives an activity, it scans existing subscriptions to identify subscribers that are interested in the received activity. If any matching subscriptions are found, the system generates a feed item for all eligible subscribers.

A feed item is generated for:

  • Any subscription following the target of the activity.
  • Any subscription following the actor who performed the activity.

Adding an activity also results in the notification of any handlers registered to watch for activities of the type represented by TExtension.

Adding an activity is a non-blocking operation. The activity is queued, and control is immediately returned to your application. The generation of feed items is not instantaneous; the items are generated as the system is able to process them.

The example below demonstrates the announcement of the contribution of a rating to a page, using the PageRated definition described in Designing an activity.

IActivityService activityService;

// ...

var actingUser = Reference.Create("user://identifier/for/a/user");
var pageActedUpon = Reference.Create("resource://identifier/for/a/resource");

var activity = new Activity(actingUser, pageActedUpon);
var payload = new PageRated
{
    Rating = 1,
    UserName = "Rater",
    PageId = "/My/Page",
    PageName = "My Page"
};

activityService.Add(activity, payload);

In the next example, a similar approach is used to add an activity targeting a user. Consider an activity using the Vote definition, described below:

    public class Vote 
    {
        public int Rating { get; set; }

        public String Candidate { get; set; }

        public String Voter { get; set; }
    }

To add an activity, whereby the user "Chris" votes for the user "Carlos", consider the sample below:

IActivityService activityService;

// ...

var actingUser = Reference.Create("user://identifier/for/a/user");
var userActedUpon = Reference.Create("user://identifier/for/another/user");

var activity = new Activity(actingUser, userActedUpon);

var payload = new Vote
{
    Rating = 10,
    Candidate = "Carlos",
    Voter = "Chris",
};
activityService.Add(activity, payload);

Watching activities

In addition to generating feed items, the Activity Streams feature handles activity notifications. A developer may register a handler, which the platform invokes upon receipt of activities that the handler is capable of processing.

You register a handler to receive activity notifications for a particular type of activity by using the Watch<TExtension>(IActivityHandler) method. The method accepts an instance of IActivityHandler<TExtension>, defining the operation to be executed when an activity is received. The type parameter, TExtension, identifies the type of activity payload that the handler is capable of handling.

The execution of handlers is not an instantaneous operation. Their execution does not block a request, and they are executed as the system can process them. The order of handler execution is not guaranteed. Implement handlers so that their behavior is not dependent on the execution of another handler.

The example below demonstrates an implementation of IActivityHandler for the PageRated activity, defined in previous examples.

public class PageRatedActivityHandler : IActivityHandler<PageRated>
{
    public void Handle(Activity activity, PageRated extension)
    {
        // Note: This example leverages the Episerver LogManager.

        LogManager.GetLogger().Debug(
            "PageRated activity received. Actor: {0} Date: {1} Payload: PageName: {2} UserName: {3}",
            activity.Actor.ToString(), 
            activity.Created.ToString(), 
            extension.PageName, 
            extension.UserName
        );
    }
}

An instance of this handler can be registered to receive notification upon receipt of PageRated activities as shown below.

IActivityService activityService;

// ...

activityService.Watch(new PageRatedActivityHandler());

A handler only needs to be registered once in the lifecycle of your application, typically during application startup or initialization. (Registering the same handler multiple times results in multiple invocations of that handler for a single activity.)

If you are registering a handler in an Episerver site, you could use an initialization module to perform this setup.

Best practices for watching activities

Stateless operations

It is important to consider that handlers are executed within the context of your application. It is advantageous to implement handlers as stateless operations to account for the possibility that instances of your application may be distributed.

Short-lived operations

The execution of a handler occurs in the background and does not block the execution of the thread in which an activity is being added into the system. However, the execution of one handler may block the execution of subsequent handlers. It is recommended that handlers registered to watch activities execute only short-lived operations. Longer running operations should be offloaded to services or systems more suitable to accommodating them.

Comments