<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Sockets and Presence</title><link>https://community.telligent.com/community/11/w/developer-training/65063/sockets-and-presence</link><description /><dc:language>en-US</dc:language><generator>14.0.0.586 14</generator><item><title>Sockets and Presence</title><link>https://community.telligent.com/community/11/w/developer-training/65063/sockets-and-presence</link><pubDate>Wed, 21 Aug 2019 03:44:11 GMT</pubDate><guid isPermaLink="false">f141b2d7-5f01-47b0-ab4d-105e12603c36</guid><dc:creator>Michael Monteleone</dc:creator><comments>https://community.telligent.com/community/11/w/developer-training/65063/sockets-and-presence#comments</comments><description>Current Revision posted to Developer Training by Michael Monteleone on 08/21/2019 03:44:11&lt;br /&gt;
&lt;p&gt;The Socket Framework provides support for &lt;strong&gt;real-time two-way communication between Verint Community and the browser&lt;/strong&gt;. This enables&amp;nbsp;receiving and sending messages directly to specific users or scoped&amp;nbsp;groups of users.&lt;/p&gt;
&lt;p&gt;[toc]&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l500"&gt;&lt;a id="When_would_I_want_to_use_sockets" name="When_would_I_want_to_use_sockets"&gt;&lt;/a&gt;When would I want to use sockets or presence?&lt;/h2&gt;
&lt;p&gt;Sockets are useful when you need to push messages from the server to the browser. An easy example to consider is a notification popup that is pushed to a user in the event of an action occurring on the server. Sockets are the mechanism through which built-in platform features including notifications, chat, live activity streams, forum threads, comment threads,&amp;nbsp;theme previews, presence indicators, tracing, and more communicate with the browser.&amp;nbsp;Socket plugins can&amp;nbsp;be developed to easily power other functionality like real-time whiteboards, analytics, or even games.&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l501"&gt;&lt;a id="Overview" name="Overview"&gt;&lt;/a&gt;Overview&lt;/h2&gt;
&lt;p&gt;Built on top of &lt;a href="http://signalr.net/"&gt;SignalR&lt;/a&gt;, the Socket Framework inherits all of SignalR&amp;#39;s performance, stability, and diversity of browser support over underlying WebSocket, server-sent event, or&amp;nbsp;long polling transports. Because it is Verint&amp;nbsp;Community-specific, the Socket Framework can also provide:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;[[Plugins|Plugin]] based extensibility&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Both built-in and third-party [[Plugins|plugin]] can implement their own &lt;em&gt;sockets&lt;/em&gt; which each define a pair of server and client methods and events for bi-directional communication, all multiplexed over a single&amp;nbsp;underlying connection to the server.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Presence&lt;/strong&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Users&amp;#39; site presence as well as their presence to individual pieces of content regardless of how and where that content is viewed&amp;nbsp;is&amp;nbsp;tracked&amp;nbsp;to enable&amp;nbsp;delivery of messages scoped only to&amp;nbsp;users viewing&amp;nbsp;specific&amp;nbsp;content. Additionally, Service Presence supports a similar, but non-content-based scoping of messages.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scale-out and reliability&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;All sockets are multiplexed across&amp;nbsp;a single connection between&amp;nbsp;the server and browser. Additionally,&amp;nbsp;the browser shares the same, single, connection across all of its windows and&amp;nbsp;tabs, transparently identifying a single window or tab at a time to serve&amp;nbsp;as the connection&amp;#39;s host.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Socket connections are reliably maintained and reconnect after any disconnections with randomized, exponential, retry backoffs.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;To support scale-out to multiple application instances and&amp;nbsp;delivery&amp;nbsp;of socket messages from plugins&amp;nbsp;running outside of web contexts in the job server, Verint&amp;nbsp;Community automatically distributes message sending&amp;nbsp;across a bus.&amp;nbsp;Community&amp;nbsp;bundles two&amp;nbsp;possible message bus servers: the Socket Message Bus Service as well as the lower-performing Database Message Bus. Alternatively, Verint&amp;nbsp;Community can use &lt;em&gt;any&lt;/em&gt; message bus service through plugin extensibility. The configuration of which message bus server to use, if any at all, is defined by [[Plugins|plugin]]-based connectors, which can be enabled or disabled through standard plugin management without restarting the application. Socket plugins also expose the underlying bus for use as a way to keep real-time application state in synchronization across multiple instances as needed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="mcetoc_1dio78l502"&gt;&lt;a id="API" name="API"&gt;&lt;/a&gt;API&lt;/h2&gt;
&lt;p&gt;The server-side API exists as a set of interfaces implementable by [[Plugins|plugins]].&lt;/p&gt;
&lt;p&gt;&lt;img alt=" " src="/resized-image/__size/640x480/__key/communityserver-wikis-components-files/00-00-00-12-83/sockets.png" /&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l503"&gt;&lt;a id="ISocket_Plugin" name="ISocket_Plugin"&gt;&lt;/a&gt;&lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket Plugin&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A socket is defined by a [[Plugins|plugin]] which implements the &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; interface. A single socket plugin represents a single channel of communication between the server and browser. For example, a socket plugin may represent all functionality related to sending and receiving realtime chat messages. A single socket plugin can send and receive arbitrary messages and optional data with those messages, but can only send or receive messages sent by or to the same socket plugin.&lt;/p&gt;
&lt;p&gt;Socket plugins are injected with instances of &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt; exposes an instance of an &lt;a href="/developers/w/developer90/50149.iclientscontroller-plugin-supplementary-type"&gt;IClientsController&lt;/a&gt; which contains events for when a user connects, disconnects, or sends a message from the browser. The &lt;a href="/developers/w/developer90/50149.iclientscontroller-plugin-supplementary-type"&gt;IClientsController&lt;/a&gt; also supports sending messages to a user, to all users present to specific&amp;nbsp;content or services, or broadcasting to all users.&lt;/p&gt;
&lt;p&gt;Each enabled socket plugin yields a corresponding client-side API.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l504"&gt;&lt;a id="ISocketMessageBus_Plugin" name="ISocketMessageBus_Plugin"&gt;&lt;/a&gt;&lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus Plugin&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Multiple-application instance scale-out and message delivery from non-web contexts like job server plugins is automatically&amp;nbsp;supported&amp;nbsp;by&amp;nbsp;the&amp;nbsp;enablement of plugins which implement the &lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus&lt;/a&gt; interface. Verint&amp;nbsp;Community bundles two default implementations to connect to either the Socket Message Bus Service or the Database Message Bus, but also supports integrating with other message busses as well. For details, see the discussion on Scale-Out.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l505"&gt;&lt;a id="Client-Side" name="Client-Side"&gt;&lt;/a&gt;Client-Side&lt;/h3&gt;
&lt;h4&gt;&lt;a id="Socket_Endpoints" name="Socket_Endpoints"&gt;&lt;/a&gt;Socket Endpoints&lt;/h4&gt;
&lt;p&gt;Each &lt;code&gt;ISocket&lt;/code&gt; plugin implements a &lt;code&gt;SocketName&lt;/code&gt;. This one-word string becomes the name of the client-side API. For example, given the socket:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public class MySocket : ISocket
{
    // ...

    string SocketName =&amp;gt; &amp;quot;mySocket&amp;quot;;

    // ...
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Then the following JavaScript API will be automatically exposed:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="javascript"&gt;// receive and handle a message with optional data from the server
jQuery.telligent.evolution.sockets.mySocket.on(messageName, function(data) {
   // handle
});

// send data to the server an optional object message
jQuery.telligent.evolution.sockets.mySocket.send(messageName, data);&lt;/pre&gt;&lt;/p&gt;
&lt;h4&gt;&lt;a id="Initiation" name="Initiation"&gt;&lt;/a&gt;Initiation&lt;/h4&gt;
&lt;p&gt;Before attempting to send or receive messages from the client side, the Socket Framework must initiate itself. This happens automatically, and when complete, it publishes a &lt;a href="/developers/w/developer90/50006.socket-connected-client-message"&gt;socket.connected&lt;/a&gt; &lt;a href="/developers/w/developer90/50024.messaging-javascript-api-module"&gt;client-side message&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="javascript"&gt;jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
    // set up message listeners or send messages
});&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l506"&gt;&lt;a id="Example_Socket" name="Example_Socket"&gt;&lt;/a&gt;Simple Example Socket&lt;/h2&gt;
&lt;p&gt;The following shows a basic example of a socket which routes greetings from one user to another. A user provides the user name of another community member, clicks &amp;#39;greet&amp;#39;, and an alert is displayed to the other user.&lt;/p&gt;
&lt;p&gt;Greetings are initiated from a user via a widget, sent via the client-side socket API to the &lt;code&gt;ISocket&lt;/code&gt; plugin, and then delivered to the recipient user where the same widget instance for the other user will display the message in a JavaScript &lt;code&gt;alert()&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l507"&gt;&lt;a id="Server_Side" name="Server_Side"&gt;&lt;/a&gt;Server Side&lt;/h3&gt;
&lt;p&gt;Create a new [[Plugins|plugin]] which implements the &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; interface. Its &lt;code&gt;Name&lt;/code&gt;, &lt;code&gt;Description&lt;/code&gt;, and &lt;code&gt;Initialize()&lt;/code&gt; are unimportant. For &lt;code&gt;SocketName&lt;/code&gt; and &lt;code&gt;SetController()&lt;/code&gt;, use the following:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public string SocketName =&amp;gt; &amp;quot;greeter&amp;quot;;

public void SetController(ISocketController controller)
{
    controller.Clients.Received += (sender, e) =&amp;gt;
    {
        // if this was a greting message, let&amp;#39;s process it
        if (e.MessageName == &amp;quot;greet&amp;quot;)
        {
            // get the associated recipient user
            // data passed from the client side is available on the dynamic MessageData object
            var to = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;Telligent.Evolution.Extensibility.Api.Version1.IUsers&amp;gt;().Users.Get(new Telligent.Evolution.Extensibility.Api.Version1.UsersGetOptions { Username = (string)e.MessageData.Recipient });

            // get the sender user
            var from = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;Telligent.Evolution.Extensibility.Api.Version1.IUsers&amp;gt;().Get(new Telligent.Evolution.Extensibility.Api.Version1.UsersGetOptions { Id = e.UserId });

            // send a new message to the recipient
            controller.Clients.Send(to.Id.GetValueOrDefault(), &amp;quot;greet&amp;quot;, new
            {
                Message = String.Format(&amp;quot;Hello {0}, from {1}&amp;quot;, to.DisplayName, from.DisplayName)
            });
        }
    };
}&lt;/pre&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l508"&gt;&lt;a id="Client_Side" name="Client_Side"&gt;&lt;/a&gt;Client Side&lt;/h3&gt;
&lt;p&gt;In Widget Studio, create a new widget&amp;nbsp;with content:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="velocity"&gt;## set up some unique ids for interface elements
#set($recipientInputId = $core_v2_widget.UniqueId(&amp;#39;recipient&amp;#39;))
#set($sendLinkId = $core_v2_widget.UniqueId(&amp;#39;greet&amp;#39;))

## basic interface
&amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;$recipientInputId&amp;quot; /&amp;gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;$sendLinkId&amp;quot;&amp;gt;Greet&amp;lt;/a&amp;gt;

&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
// Wait for socket to be connected
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {

    // when &amp;#39;Greet&amp;#39; is clicked, send a message to be delivered to the recipient
    jQuery(&amp;#39;#$sendLinkId&amp;#39;).on(&amp;#39;click&amp;#39;, function(e) {
        e.preventDefault();

        jQuery.telligent.evolution.sockets.greeter.send(&amp;#39;greet&amp;#39;, {
            Recipient: jQuery(&amp;#39;#$recipientInputId&amp;#39;).val()
        });
    });

    // when a &amp;#39;greet&amp;#39; message is received from the socket, display it as an alert
    jQuery.telligent.evolution.sockets.greeter.on(&amp;#39;greet&amp;#39;, function(data){
        alert(data.Message);
    });
});
&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Note use of the &lt;a href="/developers/w/developer90/50006.socket-connected-client-message"&gt;socket.connected&lt;/a&gt; &lt;a href="/developers/w/developer90/50024.messaging-javascript-api-module"&gt;client-side message&lt;/a&gt; as well as the automatically-generated &lt;code&gt;jQuery.telligent.evolution.sockets.testSocket&lt;/code&gt; API.&lt;/p&gt;
&lt;p&gt;The result is a simple UI that enables sending a greeting to another user by their user name.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter.png"&gt;&lt;img style="border:1px solid #DDD;width:264px;" alt=" " src="/resized-image/__size/640x480/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter_2D00_greeted.png"&gt;&lt;img style="border:1px solid #DDD;width:485px;" alt=" " src="/resized-image/__size/640x480/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter_2D00_greeted.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l509"&gt;&lt;a id="Download" name="Download"&gt;&lt;/a&gt;Download&lt;/h3&gt;
&lt;p&gt;The complete sample can be downloaded:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/SocketSample_2E00_cs"&gt;community.telligent.com/.../SocketSample_2E00_cs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/5314.GreeterUI_2D00_Widget.xml"&gt;community.telligent.com/.../5314.GreeterUI_2D00_Widget.xml&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l50f"&gt;&lt;a id="Presence_Services" name="Presence_Services"&gt;&lt;/a&gt;Presence Services&lt;/h2&gt;
&lt;p&gt;Being able to send messages directly to individual users is a great start. However, there is often a need to send messages to specific groups of users, i.e. messages about new replies to all users viewing a given forum thread so that it may&amp;nbsp;update its UI&amp;nbsp;in realtime. To that end, presence services enable sending messages to users scoped by their &lt;em&gt;presence&lt;/em&gt; to pieces of [[The Content Model|content]] or abstract &lt;em&gt;service&lt;/em&gt;&amp;nbsp;groupings.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50h"&gt;&lt;a id="Content_Presence" name="Content_Presence"&gt;&lt;/a&gt;Content Presence&lt;/h3&gt;
&lt;p&gt;The Content Presence service tracks which &lt;span&gt;[[The Content Model|content&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt; users are currently viewing. This enables the platform to deliver updates to&amp;nbsp;users in real time regarding&amp;nbsp;changes to content they are currently viewing. &lt;strong&gt;Importantly&lt;/strong&gt;, this can mean in whatever or wherever way that the content is presented. For example, a user viewing a forum thread&amp;#39;s question&amp;nbsp;in a group&amp;#39;s&amp;nbsp;activity stream is considered and tracked&amp;nbsp;as present to that forum&amp;nbsp;thread&amp;nbsp;the same&amp;nbsp;as a user on the forum thread&amp;#39;s own page. Also importantly, content presence even takes into account whether the content&amp;#39;s UI is scrolled into view. For example, a user is&amp;nbsp;&lt;em&gt;not&lt;/em&gt; be present to another forum thread whose activity story is&amp;nbsp;scrolled out of browser view in the activity stream.&lt;/p&gt;
&lt;h4&gt;&lt;a id="Content_Presence_Mappings" name="Content_Presence_Mappings"&gt;&lt;/a&gt;Content Presence&amp;nbsp;Mappings&lt;/h4&gt;
&lt;p&gt;To understand content presence APIs, it is important to first understand &lt;em&gt;the ways in which&amp;nbsp;content presence mappings are created and removed:&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Page Context&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;The service uses [[Page Definition and URL Routing|URL context]] to track what content the user&amp;nbsp;is currently viewing. As long as a user is on a URL with content context, the user is present to those content records. For example,&amp;nbsp;if a user is viewing a blog post, the content service would be aware that the user is present to&amp;nbsp;that blog post, the blog, and even the post&amp;#39;s author&amp;#39;s content records. So, sending a socket message to any of those three content IDs would deliver it to the viewing user.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HTML presence&amp;nbsp;attributes&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;In addition to overall page context, specific portions of a page&amp;#39;s UI can identify themselves as representing specific content, so that while a user is viewing that UI, the user is also mapped as present to the&amp;nbsp;content. These identifications are represented as attributes added to the HTML&amp;nbsp;element.&amp;nbsp;The activity stream uses such HTML attributes to wrap stories in the stream so that the user is present to stories&amp;#39; corresponding content, and only when those stories are scrolled into view.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;APIs&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&amp;nbsp;In-Process, Rest and Script&amp;nbsp;APIs are available to directly add and remove&amp;nbsp;presence mappings, though these are rarely needed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Content presence mappings are&amp;nbsp;&lt;em&gt;automatically removed&lt;/em&gt;&amp;nbsp;when they expire. As long as a user is on a page, the page regularly pings back to the server to identify that the user is online, and to identify the list of content records the user is present to, whether they were&amp;nbsp;identified by the overall page&amp;#39;s context, or by the currently scrolled elements decorated with&amp;nbsp;HTML presence attributes. Presence mappings that have not been refreshed for across a few&amp;nbsp;of these pings are considered expired and unmapped, thereby removing the user from receipt of socket messages&amp;nbsp;sent to users present to the content. Since&amp;nbsp;all windows and tabs of a single browser share a single socket connection, the single connection sends a ping identifying present content records across &lt;em&gt;all&lt;/em&gt; open windows and tabs.&lt;/p&gt;
&lt;h4&gt;&lt;a id="Content_Presence_API" name="Content_Presence_API"&gt;&lt;/a&gt;Content Presence API&lt;/h4&gt;
&lt;p&gt;Content presence APIs enable sending messages, querying total presence counts, and registering specific presence mappings.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;To send messages&lt;/em&gt;, use &lt;a href="/community/11/w/api-documentation/64162/iclientscontroller-plugin-supplementary-type"&gt;IClientsController.SendToUsersPresentToContent(Guid contentId, string messageName)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To query&lt;em&gt;&amp;nbsp;metadata summaries&lt;/em&gt; about users present to a given piece of content via &lt;a href="/11/w/api-documentation/63974/contentpresence-in-process-api-service"&gt;&lt;code&gt;IContentPresence&lt;/code&gt;&lt;/a&gt; or&amp;nbsp;&lt;code&gt;&lt;a href="/community/11/w/api-documentation/65749/core_5f00_v2_5f00_contentpresence-script-api"&gt;core_v2_contentPresence.GetSummary()&lt;/a&gt;. &lt;/code&gt;This metadata&amp;nbsp;is just a count summary, and may&amp;nbsp;be delayed.&lt;/p&gt;
&lt;p&gt;To register specific HTML elements as representing content so that&amp;nbsp;the user is mapped to the content while viewing the element, use &lt;code&gt;&lt;a href="/community/11/w/api-documentation/65749/core_5f00_v2_5f00_contentpresence-script-api#RenderAttributes"&gt;core_v2_contentPresence.RenderAttributes()&lt;/a&gt;&lt;/code&gt;&lt;span&gt;.&amp;nbsp;This method will render the proper attributes&amp;nbsp;to include inline with any HTML element, such as a &amp;lt;div&amp;gt; wrapping an activity stream story, or a &amp;lt;span&amp;gt; surrounding a like button.&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50i"&gt;&lt;a id="Service_Presence" name="Service_Presence"&gt;&lt;/a&gt;Service Presence&lt;/h3&gt;
&lt;p&gt;Service Presence is nearly identical to&amp;nbsp;Content Presence in that it enables&amp;nbsp;mapping a user&amp;#39;s presence and&amp;nbsp;sending socket messages to users based on those mappings. However, while Content Presence is&amp;nbsp;designed specifically for Content IDs and Content Type IDs and automatically maps users to content by their page context, service presence allows mapping users to &lt;em&gt;any arbitrary Guid&lt;/em&gt;. As such, there are no automatically-created service presence mappings. Service presence mappings can only be registered by specific&amp;nbsp;&lt;em&gt;HTML presence attributes&lt;/em&gt; or the APIs (rarely&amp;nbsp;used). (Please see the above discussion on Content Presence Mappings for a discussion on how such attributes work.)&lt;/p&gt;
&lt;p&gt;In this way, a widget can define an HTML element to contain&amp;nbsp;a service presence mapping of any arbitrary ID.&amp;nbsp;Any user viewing the element in that&amp;nbsp;widget will be considered present to that ID &amp;quot;service&amp;quot;. And a socket plugin can then deliver a message to any user viewing&amp;nbsp;that widget by the same arbitrary service presence ID.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Similar to content presence, service presence mappings&amp;nbsp;automatically expire.&lt;/p&gt;
&lt;p&gt;While less frequently needed than content presence, service presence provides flexibility for edge cases.&lt;/p&gt;
&lt;h4&gt;&lt;a id="Service_Presence_API" name="Service_Presence_API"&gt;&lt;/a&gt;Service Presence API&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;To send messages&lt;/em&gt;, use &lt;a href="/community/11/w/api-documentation/64162/iclientscontroller-plugin-supplementary-type"&gt;IClientsController.SendToUsersPresentToService(Guid serviceId, string messageName)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To query&lt;em&gt;&amp;nbsp;metadata summaries&lt;/em&gt; about users present to an ID via &lt;a href="/community/11/w/api-documentation/64069/servicepresence-in-process-api-service"&gt;&lt;code&gt;IServicePresence&lt;/code&gt;&lt;/a&gt; or&amp;nbsp;&lt;code&gt;&lt;a href="/community/11/w/api-documentation/65767/core_5f00_v2_5f00_servicepresence-script-api#GetSummary"&gt;core_v2_servicePresence.GetSummary()&lt;/a&gt;. &lt;/code&gt;This metadata&amp;nbsp;is just a count summary, and may&amp;nbsp;be delayed.&lt;/p&gt;
&lt;p&gt;To register specific HTML elements as services mapping ID so that&amp;nbsp;the user is mapped to the ID&amp;nbsp;while viewing the element, use &lt;code&gt;&lt;a href="/community/11/w/api-documentation/65767/core_5f00_v2_5f00_servicepresence-script-api#RenderAttributes"&gt;core_v2_servicePresence.RenderAttributes()&lt;/a&gt;&lt;/code&gt;&lt;span&gt;.&amp;nbsp;This method will render the proper attributes&amp;nbsp;to include inline with any HTML element.&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50g"&gt;&lt;a id="User_Presence" name="User_Presence"&gt;&lt;/a&gt;User Presence&lt;/h3&gt;
&lt;p&gt;User presence is a set of related&amp;nbsp;UIs and APIs which track and render a user&amp;#39;s overall presence to the site.&amp;nbsp;User Presence is built on sockets and content presence. After all, user records are content records, too.&lt;/p&gt;
&lt;h4&gt;&lt;a id="UI" name="UI"&gt;&lt;/a&gt;UI&lt;/h4&gt;
&lt;p&gt;The service is responsible for the presence indicator often&amp;nbsp;displayed alongside the user&amp;nbsp;names.&lt;/p&gt;
&lt;p&gt;&lt;img alt=" " src="/resized-image/__size/320x240/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence.png" /&gt;&lt;/p&gt;
&lt;h4&gt;&lt;a id="API" name="API"&gt;&lt;/a&gt;API&lt;/h4&gt;
&lt;p&gt;Live-updating user presence indicators&amp;nbsp;can be easily&amp;nbsp;rendered with &lt;code&gt;&lt;a href="/community/11/w/api-documentation/65797/core_5f00_v2_5f00_ui-script-api#UserPresence"&gt;core_v2_ui.UserPresence()&lt;/a&gt;&lt;/code&gt;. These are an easy way to add benefits of realtime-updating presence to your UI to&amp;nbsp;improve engagement in your community.&lt;/p&gt;
&lt;p&gt;Of note, core_v2_ui.UserPresence is, itself, built on top of these&amp;nbsp;APIs. It renders a &lt;a href="/community/11/w/api-documentation/65143/ui-javascript-api-module"&gt;UI component&lt;/a&gt; which presents&amp;nbsp;an indicator dot wrapped with content presence HTML attributes&amp;nbsp;registering&amp;nbsp;the&amp;nbsp;accessing user as present to the&amp;nbsp;user being indicated so that socket messages sent on users&amp;#39; presence change events&amp;nbsp;can be delivered to anyone viewing the changed users&amp;#39; indicators.&lt;/p&gt;
&lt;p&gt;A user&amp;#39;s current presence is an attribute of the user&amp;#39;s entity, returned from REST, Script, or In-Process APIs. Like other user property changes, changes to their presence can be handled with events.&lt;/p&gt;
&lt;p&gt;Similar to content and service presence mappings, users&amp;#39; presences are automatically set to offline whenever the user closes all of their browser windows and tabs or after the last of their content presence mappings expire.&lt;/p&gt;
&lt;h4&gt;&lt;a id="Privacy" name="Privacy"&gt;&lt;/a&gt;Privacy&lt;/h4&gt;
&lt;p&gt;The platform has the options for&amp;nbsp;&lt;strong&gt;Enable Presence Tracking&lt;/strong&gt;,&amp;nbsp;&lt;strong&gt;Allow Members To Toggle Presence Tracking Enablement &lt;/strong&gt;and&lt;strong&gt; Default Presence Tracking Enablement Value &amp;nbsp;&lt;/strong&gt;available under Membership in the Membership Options panel in Administration. &amp;nbsp;&lt;strong&gt;Enable Presence Tracking&amp;nbsp;&lt;/strong&gt;controls whether user presence tracking is available for the community. &amp;nbsp;If tracking is enabled, &amp;nbsp;&lt;strong&gt;Allow Members To Toggle Presence Tracking Enablement&lt;/strong&gt; controls whether or not each user should have the option to disable tracking of their online status. If that option is enabled the&amp;nbsp;&lt;strong&gt;Default Presence Tracking Enablement Value&amp;nbsp;&lt;/strong&gt;is also available. &amp;nbsp;If users are giving the option to control their presence tracking, the&amp;nbsp;&lt;strong&gt;Enable presence tracking&lt;/strong&gt; option will be available in the membership settings.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence-admin.png"&gt;&lt;img alt=" " src="/resized-image/__size/550x539/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence-admin.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l50j"&gt;&lt;a id="Example_Socket_using_Content_Presence_Service" name="Example_Socket_using_Content_Presence_Service"&gt;&lt;/a&gt;Example Socket using Content Presence&lt;/h2&gt;
&lt;p&gt;This example will&amp;nbsp;create an &lt;code&gt;ISocket&lt;/code&gt; implementation that will send socket messages to users when a vote is received or changed on an idea. By combining the socket implementation with the content presence service, the socket messages can be sent only to those users who are currently viewing the idea that received the vote.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50k"&gt;&lt;a id="Server_Side" name="Server_Side"&gt;&lt;/a&gt;Server Side&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;ISocket&lt;/code&gt; implementation will use the &lt;em&gt;ideavotes&lt;/em&gt; for the &lt;code&gt;SocketName &lt;/code&gt;and maintain a reference to the &lt;code&gt;SocketController&lt;/code&gt; for later use in our example.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;ISocketController _sockets;
public string SocketName =&amp;gt; &amp;quot;ideavotes&amp;quot;;

public void SetController(ISocketController controller)
{
    _sockets = controller;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The example class will need to send a message whenever an idea is&amp;nbsp;voted on, this can be accomplished by attaching to the Idea Vote Events for these actions in our plugin&amp;#39;s &lt;code&gt;Initialize&lt;/code&gt; method. &amp;nbsp;In each event handler, we will call the same method SendVoteCounts passing the idea id for the vote.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public void Initialize()
{
    _ideas = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IIdeas&amp;gt;();

    _ideaVotes = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IVotes&amp;gt;();
    _ideaVotes.Events.AfterCreate += VoteCreated;
    _ideaVotes.Events.AfterDelete += VoteDeleted;
    _ideaVotes.Events.AfterUpdate += VoteUpdated;
}

private void VoteCreated(VoteAfterCreateEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}

private void VoteUpdated(VoteAfterUpdateEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}

private void VoteDeleted(VoteAfterDeleteEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;In the SendVoteCounts method, the number of up and down votes will be retrieved and the&amp;nbsp;&lt;code&gt;_sockets.Clients.SendToUsersPresentToContent &lt;/code&gt;method will be used to send a message to all users who are currently present to that idea.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;void SendVoteCounts(Guid ideaId)
{
    var idea = _ideas.Get(ideaId);
    if (idea != null &amp;amp;&amp;amp; !idea.HasErrors())
    {
        var upVotes =
            _ideaVotes.List(new VotesListOptions() {IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = true });

        var downVotes =
            _ideaVotes.List(new VotesListOptions() { IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = false });

        // send socket message with updated totals
        _sockets.Clients.SendToUsersPresentToContent(idea.ContentId, &amp;quot;ideavoted&amp;quot;, new
        {
            contentId = idea.ContentId,
            contentTypeId = _ideas.ContentTypeId,
            yesVotes = upVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;,
            noVotes = downVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;
        });
    }
}&lt;/pre&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50l"&gt;&lt;a id="Client_Side" name="Client_Side"&gt;&lt;/a&gt;Client Side&lt;/h3&gt;
&lt;p&gt;Once this plugin is compiled and enabled on the community site, each time an idea is voted on any user who is viewing that idea will receive an &lt;em&gt;ideavoted&amp;nbsp;&lt;/em&gt;socket message. &amp;nbsp;For this example, we can use a widget to see these messages. &amp;nbsp;The example will&amp;nbsp;make use of the&amp;nbsp;&lt;code&gt;$.telligent.evolution.sockets.ideavotes&lt;/code&gt; API that is automatically generated for our &lt;code&gt;ISocket&lt;/code&gt; implementation. &amp;nbsp;That API will enable the widget to listen for messages from the custom socket. &amp;nbsp;In this case, the message&amp;#39;s data will output to the browser&amp;#39;s console window.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="javascript"&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
	jQuery.telligent.evolution.sockets.ideavotes.on(&amp;#39;ideavoted&amp;#39;, function(data) {
		console.log(data);
	});
});
&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The widget can be placed on the Idea page or Idea List page,&amp;nbsp;you will be able to see the messages for the ideas you are currently viewing when any vote is received on the idea(s) you are currently viewing.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50m"&gt;&lt;a id="Completed_Sample" name="Completed_Sample"&gt;&lt;/a&gt;Completed Sample&lt;/h3&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;using System;
using Telligent.Evolution.Extensibility.Ideation.Api;
using Telligent.Evolution.Extensibility.Sockets.Version1;
using Telligent.Evolution.Extensibility.Version1;

namespace Telligent.Evolution.Examples
{
    public class VoteSocket : IPlugin, ISocket
    {
        ISocketController _sockets;
        IIdeas _ideas;
        IVotes _ideaVotes;

        public string Name =&amp;gt; &amp;quot;Idea Vote Sockets&amp;quot;;
        public string Description =&amp;gt; &amp;quot;Enables live updates to idea votes.&amp;quot;;
        public string SocketName =&amp;gt; &amp;quot;ideavotes&amp;quot;;

        public void Initialize()
        {
            _ideas = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IIdeas&amp;gt;();

            _ideaVotes = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IVotes&amp;gt;();
            _ideaVotes.Events.AfterCreate += VoteCreated;
            _ideaVotes.Events.AfterDelete += VoteDeleted;
            _ideaVotes.Events.AfterUpdate += VoteUpdated;
        }

        public void SetController(ISocketController controller)
        {
            _sockets = controller;
        }

        private void VoteCreated(VoteAfterCreateEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        private void VoteUpdated(VoteAfterUpdateEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        private void VoteDeleted(VoteAfterDeleteEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        void SendVoteCounts(Guid ideaId)
        {
            var idea = _ideas.Get(ideaId);
            if (idea != null &amp;amp;&amp;amp; !idea.HasErrors())
            {
                var upVotes =
                    _ideaVotes.List(new VotesListOptions() {IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = true });

                var downVotes =
                    _ideaVotes.List(new VotesListOptions() { IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = false });

                // send socket message with updated totals
                _sockets.Clients.SendToUsersPresentToContent(idea.ContentId, &amp;quot;ideavoted&amp;quot;, new
                {
                    contentId = idea.ContentId,
                    contentTypeId = _ideas.ContentTypeId,
                    yesVotes = upVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;,
                    noVotes = downVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;
                });
            }
        }
    }
}
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="xml"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;
&amp;lt;scriptedContentFragments&amp;gt;
  &amp;lt;scriptedContentFragment name=&amp;quot;Idea Socket Presence Test&amp;quot; version=&amp;quot;10.0.0.0&amp;quot; description=&amp;quot;&amp;quot; instanceIdentifier=&amp;quot;c7e0a2c7d2b44ab08f22d8938ef03a06&amp;quot; theme=&amp;quot;&amp;quot; isCacheable=&amp;quot;false&amp;quot; varyCacheByUser=&amp;quot;false&amp;quot; showHeaderByDefault=&amp;quot;false&amp;quot; cssClass=&amp;quot;&amp;quot; provider=&amp;quot;7bb87a0cc5864a9392ae5b9e5f9747b7&amp;quot;&amp;gt;
    &amp;lt;contentScript&amp;gt;&amp;lt;![CDATA[

&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
	jQuery.telligent.evolution.sockets.ideavotes.on(&amp;#39;ideavoted&amp;#39;, function(data) {
		console.log(data);
	});
});
&amp;lt;/script&amp;gt;

]]&amp;gt;&amp;lt;/contentScript&amp;gt;
  &amp;lt;/scriptedContentFragment&amp;gt;
&amp;lt;/scriptedContentFragments&amp;gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l50a"&gt;&lt;a id="Scale-out" name="Scale-out"&gt;&lt;/a&gt;Scale-out&lt;/h2&gt;
&lt;h3 id="mcetoc_1dio78l50b"&gt;&lt;a id="Overview" name="Overview"&gt;&lt;/a&gt;Overview&lt;/h3&gt;
&lt;p&gt;While multiple users connected to a single web node are easy enough to reason about, this becomes more complicated&amp;nbsp;when there are multiple app nodes and&amp;nbsp;a job server. Consider&amp;nbsp;the case of User A on Server X and User B on Server Y where User A intends to send a real-time chat socket message to User B. The socket message must not only be sent to a different user, it must be sent to that user from a different server entirely. Or consider the case of a plugin running in the context of a job on the job server instead of a web node which also intends to send a socket message to a user, such as a socket-based message&amp;nbsp;that some delayed process has completed. The job server is not connected directly to any users, and so needs to communicate with the web nodes in order to deliver socket messages.&lt;/p&gt;
&lt;p&gt;These scenarios are already&amp;nbsp;&lt;em&gt;automatically and transparently&lt;/em&gt; supported through the use of the message bus.&amp;nbsp;&lt;strong&gt;Verint Community requires the use of a&amp;nbsp;message bus&lt;/strong&gt;. Verint Community comes with&amp;nbsp;two possible message bus services built in, the Socket Message Bus Windows Service as well as the lower performance&amp;nbsp;Database Message Bus. At least one of these services or another conforming message bus is required to be enabled as part of the installation of Community.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50c"&gt;&lt;a id="Socket_Message_Bus_Server" name="Socket_Message_Bus_Server"&gt;&lt;/a&gt;Socket Message Bus Service&lt;/h3&gt;
&lt;p&gt;Verint&amp;nbsp;Community comes with the Socket Message Bus Windows Service and its corresponding &lt;code&gt;ISocketMessageBus&lt;/code&gt; plugin-based connector, &lt;em&gt;Socket Message Bus Service &lt;/em&gt;available in&lt;em&gt; Administration &amp;gt; Site &amp;gt; Message Buses&lt;/em&gt;. This is simply a Windows Service which echoes messages it receives to all connected Verint&amp;nbsp;Community instances.&lt;/p&gt;
&lt;p&gt;Community also includes an alternative Database Message Bus which&amp;nbsp;has lower performance, but requires no separate service installation.&amp;nbsp;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50d"&gt;&lt;a id="Custom_Message_Bus" name="Custom_Message_Bus"&gt;&lt;/a&gt;Custom Message Bus&lt;/h3&gt;
&lt;p&gt;In cases where a community would prefer to use an existing third party message bus solution, custom &lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus plugins&lt;/a&gt; can be written against it and deployed. An example could be a message bus service which supports multiple Verint&amp;nbsp;Community communities on a single bus server by potentially adding an identifier to the string messages sent and received by the plugin for routing the message on the bus server.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50e"&gt;&lt;a id="Generic_Messages" name="Generic_Messages"&gt;&lt;/a&gt;Generic Messages&lt;/h3&gt;
&lt;p&gt;Custom logic in &lt;code&gt;ISocket&lt;/code&gt; plugins can also make use of the message bus directly. Generic messages can be useful for keeping small amounts&amp;nbsp;of state synchronized in realtime across application instances.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt; injected into &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; plugins contains an instance of an &lt;a href="/developers/w/developer90/50167.imessagebuscontroller-plugin-supplementary-type"&gt;IMessageBusController&lt;/a&gt;. The &lt;a href="/developers/w/developer90/50167.imessagebuscontroller-plugin-supplementary-type"&gt;IMessageBusController&lt;/a&gt; exposes events for when generic messages are received from instances of the application along with a method for sending them.&lt;/p&gt;
&lt;p&gt;A useful pattern for state change is to send a generic message to the bus, and only handle it once it is re-received. This allows all instances to know about the state. Additionally, the instance that sends it receives the message immediately without having to wait for the round-trip, and is made aware of the local origin of the message. In this manner, the sender can also be exclusively responsible for potentially persisting the state change elsewhere.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;controller.MessageBus.Publish(&amp;quot;something.happened&amp;quot;,&amp;quot;&amp;quot;);
controller.MessageBus.Received += (sender, e) =&amp;gt;
{
    if (e.MessageName == &amp;quot;something.happened&amp;quot;)
    {
        // update some local caches
        // ...
        if (e.Source == BusMessageSource.Local)
        {
            // update DB
            // ...
        }
    }
};&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l50n"&gt;&lt;a id="Tips_and_Tricks" name="Tips_and_Tricks"&gt;&lt;/a&gt;Additional Notes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Socket connections are only established for authenticated, non-system, users&lt;/li&gt;
&lt;li&gt;User disconnection events are raised whenever&amp;nbsp;a user&amp;#39;s last window&amp;nbsp;or tab for a&amp;nbsp;browser closes, as they all share a single connection. Disconnection events can also raise when plugins refresh.&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: socket, messaging, presence, bus&lt;/div&gt;
</description></item><item><title>Sockets and Presence</title><link>https://community.telligent.com/community/11/w/developer-training/65063/sockets-and-presence/revision/9</link><pubDate>Tue, 20 Aug 2019 22:05:26 GMT</pubDate><guid isPermaLink="false">f141b2d7-5f01-47b0-ab4d-105e12603c36</guid><dc:creator>Michael Monteleone</dc:creator><comments>https://community.telligent.com/community/11/w/developer-training/65063/sockets-and-presence#comments</comments><description>Revision 9 posted to Developer Training by Michael Monteleone on 08/20/2019 22:05:26&lt;br /&gt;
&lt;p&gt;The Socket Framework provides support for &lt;strong&gt;real-time two-way communication between Verint Community and the browser&lt;/strong&gt;. This enables&amp;nbsp;receiving and sending messages directly to specific users or scoped&amp;nbsp;groups of users.&lt;/p&gt;
&lt;p&gt;[toc]&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l500"&gt;&lt;a id="When_would_I_want_to_use_sockets" name="When_would_I_want_to_use_sockets"&gt;&lt;/a&gt;When would I want to use sockets or presence?&lt;/h2&gt;
&lt;p&gt;Sockets are useful when you need to push messages from the server to the browser. An easy example to consider is a notification popup that is pushed to a user in the event of an action occurring on the server. Sockets are the mechanism through which built-in platform features including notifications, chat, live activity streams, forum threads, comment threads,&amp;nbsp;theme previews, presence indicators, tracing, and more communicate with the browser.&amp;nbsp;Socket plugins can&amp;nbsp;be developed to easily power other functionality like real-time whiteboards, analytics, or even games.&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l501"&gt;&lt;a id="Overview" name="Overview"&gt;&lt;/a&gt;Overview&lt;/h2&gt;
&lt;p&gt;Built on top of &lt;a href="http://signalr.net/"&gt;SignalR&lt;/a&gt;, the Socket Framework inherits all of SignalR&amp;#39;s performance, stability, and diversity of browser support over underlying WebSocket, server-sent event, or&amp;nbsp;long polling transports. Because it is Verint&amp;nbsp;Community-specific, the Socket Framework can provide:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;[[Plugins|Plugin]] based extensibility&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Both built-in and third-party [[Plugins|plugin]] can implement their own &lt;em&gt;sockets&lt;/em&gt; which each define a pair of server and client methods and events for bi-directional communication, all multiplexed over a single&amp;nbsp;underlying connection to the server.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Presence&lt;/strong&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Users&amp;#39; site presence as well as their presence to individual pieces of content regardless of how and where that content is viewed&amp;nbsp;is&amp;nbsp;tracked&amp;nbsp;to enable&amp;nbsp;delivery of messages scoped only to&amp;nbsp;users viewing&amp;nbsp;specific&amp;nbsp;content. Additionally, Service Presence supports a similar, but non-content-based scoping of messages.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scale-out and reliability&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;All sockets are multiplexed across&amp;nbsp;a single connection between&amp;nbsp;the server and browser. Additionally,&amp;nbsp;the browser shares the same, single, connection across all of its windows and&amp;nbsp;tabs, transparently identifying a single window or tab at a time to serve&amp;nbsp;as the connection&amp;#39;s host.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Socket connections are reliably maintained and reconnect after any disconnections with randomized, exponential, retry backoffs.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;To support scale-out to multiple application instances and&amp;nbsp;delivery&amp;nbsp;of socket messages from plugins&amp;nbsp;running outside of web contexts in the job server, Verint&amp;nbsp;Community automatically distributes message sending&amp;nbsp;across a bus.&amp;nbsp;Community&amp;nbsp;bundles two&amp;nbsp;possible message bus servers: the Socket Message Bus Service as well as the lower-performing Database Message Bus. Alternatively, Verint&amp;nbsp;Community can use &lt;em&gt;any&lt;/em&gt; message bus service through plugin extensibility. The configuration of which message bus server to use, if any at all, is defined by [[Plugins|plugin]]-based connectors, which can be enabled or disabled through standard plugin management without restarting the application. Socket plugins also expose the underlying bus for use as a way to keep real-time application state in synchronization across multiple instances as needed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="mcetoc_1dio78l502"&gt;&lt;a id="API" name="API"&gt;&lt;/a&gt;API&lt;/h2&gt;
&lt;p&gt;The server-side API exists as a set of interfaces implementable by [[Plugins|plugins]].&lt;/p&gt;
&lt;p&gt;&lt;img alt=" " src="/resized-image/__size/640x480/__key/communityserver-wikis-components-files/00-00-00-12-83/sockets.png" /&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l503"&gt;&lt;a id="ISocket_Plugin" name="ISocket_Plugin"&gt;&lt;/a&gt;&lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket Plugin&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A socket is defined by a [[Plugins|plugin]] which implements the &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; interface. A single socket plugin represents a single channel of communication between the server and browser. For example, a socket plugin may represent all functionality related to sending and receiving realtime chat messages. A single socket plugin can send and receive arbitrary messages and optional data with those messages, but can only send or receive messages sent by or to the same socket plugin.&lt;/p&gt;
&lt;p&gt;Socket plugins are injected with instances of &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt; exposes an instance of an &lt;a href="/developers/w/developer90/50149.iclientscontroller-plugin-supplementary-type"&gt;IClientsController&lt;/a&gt; which contains events for when a user connects, disconnects, or sends a message from the browser. The &lt;a href="/developers/w/developer90/50149.iclientscontroller-plugin-supplementary-type"&gt;IClientsController&lt;/a&gt; also supports sending messages to a user, to all users present to specific&amp;nbsp;content or services, or broadcasting to all users.&lt;/p&gt;
&lt;p&gt;Each enabled socket plugin yields a corresponding client-side API.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l504"&gt;&lt;a id="ISocketMessageBus_Plugin" name="ISocketMessageBus_Plugin"&gt;&lt;/a&gt;&lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus Plugin&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Multiple-application instance scale-out and message delivery from non-web contexts like job server plugins is automatically&amp;nbsp;supported&amp;nbsp;by&amp;nbsp;the&amp;nbsp;enablement of plugins which implement the &lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus&lt;/a&gt; interface. Verint&amp;nbsp;Community bundles two default implementations to connect to either the Socket Message Bus Service or the Database Message Bus, but also supports integrating with other message busses as well. For details, see the discussion on Scale-Out.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l505"&gt;&lt;a id="Client-Side" name="Client-Side"&gt;&lt;/a&gt;Client-Side&lt;/h3&gt;
&lt;h4&gt;&lt;a id="Socket_Endpoints" name="Socket_Endpoints"&gt;&lt;/a&gt;Socket Endpoints&lt;/h4&gt;
&lt;p&gt;Each &lt;code&gt;ISocket&lt;/code&gt; plugin implements a &lt;code&gt;SocketName&lt;/code&gt;. This one-word string becomes the name of the client-side API. For example, given the socket:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public class MySocket : ISocket
{
    // ...

    string SocketName =&amp;gt; &amp;quot;mySocket&amp;quot;;

    // ...
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Then the following JavaScript API will be automatically exposed:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="javascript"&gt;// receive and handle a message with optional data from the server
jQuery.telligent.evolution.sockets.mySocket.on(messageName, function(data) {
   // handle
});

// send data to the server an optional object message
jQuery.telligent.evolution.sockets.mySocket.send(messageName, data);&lt;/pre&gt;&lt;/p&gt;
&lt;h4&gt;&lt;a id="Initiation" name="Initiation"&gt;&lt;/a&gt;Initiation&lt;/h4&gt;
&lt;p&gt;Before attempting to send or receive messages from the client side, the Socket Framework must initiate itself. This happens automatically, and when complete, it publishes a &lt;a href="/developers/w/developer90/50006.socket-connected-client-message"&gt;socket.connected&lt;/a&gt; &lt;a href="/developers/w/developer90/50024.messaging-javascript-api-module"&gt;client-side message&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="javascript"&gt;jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
    // set up message listeners or send messages
});&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l506"&gt;&lt;a id="Example_Socket" name="Example_Socket"&gt;&lt;/a&gt;Simple Example Socket&lt;/h2&gt;
&lt;p&gt;The following shows a basic example of a socket which routes greetings from one user to another. A user provides the user name of another community member, clicks &amp;#39;greet&amp;#39;, and an alert is displayed to the other user.&lt;/p&gt;
&lt;p&gt;Greetings are initiated from a user via a widget, sent via the client-side socket API to the &lt;code&gt;ISocket&lt;/code&gt; plugin, and then delivered to the recipient user where the same widget instance for the other user will display the message in a JavaScript &lt;code&gt;alert()&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l507"&gt;&lt;a id="Server_Side" name="Server_Side"&gt;&lt;/a&gt;Server Side&lt;/h3&gt;
&lt;p&gt;Create a new [[Plugins|plugin]] which implements the &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; interface. Its &lt;code&gt;Name&lt;/code&gt;, &lt;code&gt;Description&lt;/code&gt;, and &lt;code&gt;Initialize()&lt;/code&gt; are unimportant. For &lt;code&gt;SocketName&lt;/code&gt; and &lt;code&gt;SetController()&lt;/code&gt;, use the following:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public string SocketName =&amp;gt; &amp;quot;greeter&amp;quot;;

public void SetController(ISocketController controller)
{
    controller.Clients.Received += (sender, e) =&amp;gt;
    {
        // if this was a greting message, let&amp;#39;s process it
        if (e.MessageName == &amp;quot;greet&amp;quot;)
        {
            // get the associated recipient user
            // data passed from the client side is available on the dynamic MessageData object
            var to = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;Telligent.Evolution.Extensibility.Api.Version1.IUsers&amp;gt;().Users.Get(new Telligent.Evolution.Extensibility.Api.Version1.UsersGetOptions { Username = (string)e.MessageData.Recipient });

            // get the sender user
            var from = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;Telligent.Evolution.Extensibility.Api.Version1.IUsers&amp;gt;().Get(new Telligent.Evolution.Extensibility.Api.Version1.UsersGetOptions { Id = e.UserId });

            // send a new message to the recipient
            controller.Clients.Send(to.Id.GetValueOrDefault(), &amp;quot;greet&amp;quot;, new
            {
                Message = String.Format(&amp;quot;Hello {0}, from {1}&amp;quot;, to.DisplayName, from.DisplayName)
            });
        }
    };
}&lt;/pre&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l508"&gt;&lt;a id="Client_Side" name="Client_Side"&gt;&lt;/a&gt;Client Side&lt;/h3&gt;
&lt;p&gt;In Widget Studio, create a new widget&amp;nbsp;with content:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="velocity"&gt;## set up some unique ids for interface elements
#set($recipientInputId = $core_v2_widget.UniqueId(&amp;#39;recipient&amp;#39;))
#set($sendLinkId = $core_v2_widget.UniqueId(&amp;#39;greet&amp;#39;))

## basic interface
&amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;$recipientInputId&amp;quot; /&amp;gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;$sendLinkId&amp;quot;&amp;gt;Greet&amp;lt;/a&amp;gt;

&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
// Wait for socket to be connected
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {

    // when &amp;#39;Greet&amp;#39; is clicked, send a message to be delivered to the recipient
    jQuery(&amp;#39;#$sendLinkId&amp;#39;).on(&amp;#39;click&amp;#39;, function(e) {
        e.preventDefault();

        jQuery.telligent.evolution.sockets.greeter.send(&amp;#39;greet&amp;#39;, {
            Recipient: jQuery(&amp;#39;#$recipientInputId&amp;#39;).val()
        });
    });

    // when a &amp;#39;greet&amp;#39; message is received from the socket, display it as an alert
    jQuery.telligent.evolution.sockets.greeter.on(&amp;#39;greet&amp;#39;, function(data){
        alert(data.Message);
    });
});
&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Note use of the &lt;a href="/developers/w/developer90/50006.socket-connected-client-message"&gt;socket.connected&lt;/a&gt; &lt;a href="/developers/w/developer90/50024.messaging-javascript-api-module"&gt;client-side message&lt;/a&gt; as well as the automatically-generated &lt;code&gt;jQuery.telligent.evolution.sockets.testSocket&lt;/code&gt; API.&lt;/p&gt;
&lt;p&gt;The result is a simple UI that enables sending a greeting to another user by their user name.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter.png"&gt;&lt;img style="border:1px solid #DDD;width:264px;" alt=" " src="/resized-image/__size/640x480/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter_2D00_greeted.png"&gt;&lt;img style="border:1px solid #DDD;width:485px;" alt=" " src="/resized-image/__size/640x480/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter_2D00_greeted.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l509"&gt;&lt;a id="Download" name="Download"&gt;&lt;/a&gt;Download&lt;/h3&gt;
&lt;p&gt;The complete sample can be downloaded:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/SocketSample_2E00_cs"&gt;community.telligent.com/.../SocketSample_2E00_cs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/5314.GreeterUI_2D00_Widget.xml"&gt;community.telligent.com/.../5314.GreeterUI_2D00_Widget.xml&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l50f"&gt;&lt;a id="Presence_Services" name="Presence_Services"&gt;&lt;/a&gt;Presence Services&lt;/h2&gt;
&lt;p&gt;Being able to send messages directly to individual users is a great start. However, there is often a need to send messages to specific groups of users, i.e. messages about new replies to all users viewing a given forum thread so that it may&amp;nbsp;update its UI&amp;nbsp;in realtime. To that end, presence services enable sending messages to users scoped by their &lt;em&gt;presence&lt;/em&gt; to pieces of [[The Content Model|content]] or abstract &lt;em&gt;service&lt;/em&gt;&amp;nbsp;groupings.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50h"&gt;&lt;a id="Content_Presence" name="Content_Presence"&gt;&lt;/a&gt;Content Presence&lt;/h3&gt;
&lt;p&gt;The Content Presence service tracks which &lt;span&gt;[[The Content Model|content&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt; users are currently viewing. This enables the platform to deliver updates to&amp;nbsp;users in real time regarding&amp;nbsp;changes to content they are currently viewing. &lt;strong&gt;Importantly&lt;/strong&gt;, this can mean in whatever or wherever way that the content is presented. For example, a user viewing a forum thread&amp;#39;s question&amp;nbsp;in a group&amp;#39;s&amp;nbsp;activity stream is considered and tracked&amp;nbsp;as present to that forum&amp;nbsp;thread&amp;nbsp;the same&amp;nbsp;as a user on the forum thread&amp;#39;s own page. Also importantly, content presence even takes into account whether the content&amp;#39;s UI is scrolled into view. For example, a user is&amp;nbsp;&lt;em&gt;not&lt;/em&gt; be present to another forum thread whose activity story is&amp;nbsp;scrolled out of browser view in the activity stream.&lt;/p&gt;
&lt;h4&gt;&lt;/h4&gt;
&lt;h4&gt;&lt;a id="Content_Presence_Mappings" name="Content_Presence_Mappings"&gt;&lt;/a&gt;Content Presence&amp;nbsp;Mappings&lt;/h4&gt;
&lt;p&gt;To understand content presence APIs, it is important to first understand &lt;em&gt;the ways in which&amp;nbsp;content presence mappings are created and removed:&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Page Context&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;The service uses [[Page Definition and URL Routing|URL context]] to track what content the using is currently viewing. As long as a user is on a URL with content context, the user is present to those content records. For example,&amp;nbsp;if a user is viewing a blog post, the content service would be aware that the user is present to&amp;nbsp;that blog post, the blog, and even the post&amp;#39;s author&amp;#39;s content records. So, sending a socket message to any of those three content IDs would deliver it to the viewing user.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HTML presence&amp;nbsp;attributes&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;In addition to overall page context, specific portions of a page&amp;#39;s UI can identify themselves as representing specific content, so that while a user is viewing that UI, the user also is also mapped as present to the&amp;nbsp;content. These identifications are represented as attributes added to the HTML&amp;nbsp;element.&amp;nbsp;The activity stream uses such HTML presence attributes to wrap stories in the stream so that the user is present to stories&amp;#39; corresponding content, and only when those stories are scrolled into view.&lt;/li&gt;
&lt;li&gt;HTML presence&amp;nbsp;attributes can be added to through the &lt;code&gt;core_v2_contentPresence.RenderAttributes&lt;/code&gt; method. &amp;nbsp;This method will render the proper attributes to automatically track a user&amp;#39;s content presence, when the decorated element is currently visible on the page they are viewing. &amp;nbsp;The comment stream and activity stream are two examples where this method is in use.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;APIs&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&amp;nbsp;In-Process, Rest and Script&amp;nbsp;APIs are available to directly add and remove&amp;nbsp;presence mappings, though these are rarely needed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Content presence mappings are&amp;nbsp;&lt;em&gt;automatically removed&lt;/em&gt;&amp;nbsp;when they expire. As long as a user is on a page, the page is pinging back to the server to identify that the user is online, and to identify the list of content records the user is present to, whether they were&amp;nbsp;identified by the overall page&amp;#39;s context, or the currently scrolled elements decorated with&amp;nbsp;HTML presence attributes. Presence mappings that have not been refreshed for across a few&amp;nbsp;of these pings are considered expired and unmapped, thereby removing the user from receipt of socket messages&amp;nbsp;sent to users present to the content. Since&amp;nbsp;all windows and tabs of a single browser share a single socket connection, the single connection sends a ping identifying present content records across &lt;em&gt;all&lt;/em&gt; open windows and tabs.&lt;/p&gt;
&lt;h4&gt;&lt;a id="Content_Presence_API" name="Content_Presence_API"&gt;&lt;/a&gt;Content Presence API&lt;/h4&gt;
&lt;p&gt;Content presence APIs enable sending messages, querying total presence counts, and registering specific presence mappings.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;To send messages&lt;/em&gt;, use &lt;a href="/community/11/w/api-documentation/64162/iclientscontroller-plugin-supplementary-type"&gt;IClientsController.SendToUsersPresentToContent(Guid contentId, string messageName)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To query&lt;em&gt;&amp;nbsp;metadata summaries&lt;/em&gt; about users present to a given piece of content via &lt;a href="/11/w/api-documentation/63974/contentpresence-in-process-api-service"&gt;&lt;code&gt;IContentPresence&lt;/code&gt;&lt;/a&gt; or&amp;nbsp;&lt;code&gt;&lt;a href="/community/11/w/api-documentation/65749/core_5f00_v2_5f00_contentpresence-script-api"&gt;core_v2_contentPresence.GetSummary()&lt;/a&gt;. &lt;/code&gt;This metadata&amp;nbsp;is just a count summary, and may&amp;nbsp;be delayed.&lt;/p&gt;
&lt;p&gt;To register specific HTML elements as representing content so that&amp;nbsp;the user is mapped to the content while viewing the element, use &lt;code&gt;&lt;a href="/community/11/w/api-documentation/65749/core_5f00_v2_5f00_contentpresence-script-api#RenderAttributes"&gt;core_v2_contentPresence.RenderAttributes()&lt;/a&gt;&lt;/code&gt;&lt;span&gt;.&amp;nbsp;This method will render the proper attributes&amp;nbsp;to include inline with any HTML element, such as a &amp;lt;div&amp;gt; wrapping an activity stream story, or a &amp;lt;span&amp;gt; surrounding a like button.&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50i"&gt;&lt;a id="Service_Presence" name="Service_Presence"&gt;&lt;/a&gt;Service Presence&lt;/h3&gt;
&lt;p&gt;Service Presence is nearly identical to&amp;nbsp;Content Presence in that it enables&amp;nbsp;mapping a user&amp;#39;s presence and&amp;nbsp;sending socket messages to users based on those mappings. However, while Content Presence is&amp;nbsp;designed specifically for Content IDs and Content Type IDs and automatically maps users to content by their page context, service presence allows mapping users to &lt;em&gt;any arbitrary Guid&lt;/em&gt;. As such, there are no automatically-created service presence mappings. Service presence mappings can only be registered by specific&amp;nbsp;&lt;em&gt;HTML presence attributes&lt;/em&gt; or the APIs (rarely&amp;nbsp;used). (Please see the above discussion on Content Presence Mappings for a discussion on how such attributes work.)&lt;/p&gt;
&lt;p&gt;In this way, a widget can define an HTML element to contain&amp;nbsp;a service presence mapping of any arbitrary ID.&amp;nbsp;Any user viewing that widget will be considered present to that ID &amp;quot;service&amp;quot;. And a socket plugin can then deliver a message to any user viewing&amp;nbsp;that widget by the same arbitrary service presence ID.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Similar to content presence, service presence mappings&amp;nbsp;automatically expire.&lt;/p&gt;
&lt;p&gt;While less frequently needed than content presence, service presence provides flexibility for edge cases.&lt;/p&gt;
&lt;h4&gt;&lt;a id="Service_Presence_API" name="Service_Presence_API"&gt;&lt;/a&gt;Service Presence API&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;To send messages&lt;/em&gt;, use &lt;a href="/community/11/w/api-documentation/64162/iclientscontroller-plugin-supplementary-type"&gt;IClientsController.SendToUsersPresentToContent(Guid contentId, string messageName)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To query&lt;em&gt;&amp;nbsp;metadata summaries&lt;/em&gt; about users present to an ID via &lt;a href="/community/11/w/api-documentation/64069/servicepresence-in-process-api-service"&gt;&lt;code&gt;IServicePresence&lt;/code&gt;&lt;/a&gt; or&amp;nbsp;&lt;code&gt;&lt;a href="/community/11/w/api-documentation/65767/core_5f00_v2_5f00_servicepresence-script-api#GetSummary"&gt;core_v2_servicePresence.GetSummary()&lt;/a&gt;. &lt;/code&gt;This metadata&amp;nbsp;is just a count summary, and may&amp;nbsp;be delayed.&lt;/p&gt;
&lt;p&gt;To register specific HTML elements as services mapping ID so that&amp;nbsp;the user is mapped to the ID&amp;nbsp;while viewing the element, use &lt;code&gt;&lt;a href="/community/11/w/api-documentation/65767/core_5f00_v2_5f00_servicepresence-script-api#RenderAttributes"&gt;core_v2_servicePresence.RenderAttributes()&lt;/a&gt;&lt;/code&gt;&lt;span&gt;.&amp;nbsp;This method will render the proper attributes&amp;nbsp;to include inline with any HTML element.&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50i"&gt;&lt;/h3&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50g"&gt;&lt;a id="User_Presence" name="User_Presence"&gt;&lt;/a&gt;User Presence&lt;/h3&gt;
&lt;p&gt;User Presence is built atop sockets and content presence. After all, user records are content records, too.&lt;/p&gt;
&lt;p&gt;User presence is a set of related&amp;nbsp;UIs, APIs which track and render a user&amp;#39;s overall presence to the site.&lt;/p&gt;
&lt;h4&gt;&lt;a id="UI" name="UI"&gt;&lt;/a&gt;UI&lt;/h4&gt;
&lt;p&gt;The service is responsible for the presence indicator often&amp;nbsp;displayed alongside the user&amp;nbsp;names.&lt;/p&gt;
&lt;p&gt;&lt;img alt=" " src="/resized-image/__size/320x240/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence.png" /&gt;&lt;/p&gt;
&lt;h4&gt;&lt;a id="API" name="API"&gt;&lt;/a&gt;API&lt;/h4&gt;
&lt;p&gt;Live-updating user presence indicators&amp;nbsp;can be easily&amp;nbsp;rendered with &lt;code&gt;&lt;a href="/community/11/w/api-documentation/65797/core_5f00_v2_5f00_ui-script-api#UserPresence"&gt;core_v2_ui.UserPresence()&lt;/a&gt;&lt;/code&gt;. These are an easy way to add benefits of realtime-updating presence to your UI to&amp;nbsp;improve engagement in your community.&lt;/p&gt;
&lt;p&gt;Of note, core_v2_ui.UserPresence is, itself, built on top of these&amp;nbsp;APIs. It renders a &lt;a href="/community/11/w/api-documentation/65143/ui-javascript-api-module"&gt;UI component&lt;/a&gt; which presents&amp;nbsp;an indicator dot wrapped with content presence HTML attributes&amp;nbsp;registering&amp;nbsp;the&amp;nbsp;accessing user as present to the&amp;nbsp;user being indicated so that socket messages sent on users&amp;#39; presence change events&amp;nbsp;can be delivered to anyone viewing the changed users&amp;#39; indicators.&lt;/p&gt;
&lt;p&gt;A user&amp;#39;s current presence is an attribute of the user&amp;#39;s entity, returned from REST, Script, or In-Process APIs. Like other user property changes, changes to their presence can be handled with events.&lt;/p&gt;
&lt;p&gt;Similar to content and service presence mappings, users&amp;#39; presences are automatically set to offline whenever the user closes all of their browser windows and tabs or after the last of their content presence mappings expire.&lt;/p&gt;
&lt;h4&gt;&lt;a id="Privacy" name="Privacy"&gt;&lt;/a&gt;Privacy&lt;/h4&gt;
&lt;p&gt;The platform has the options for&amp;nbsp;&lt;strong&gt;Enable Presence Tracking&lt;/strong&gt;,&amp;nbsp;&lt;strong&gt;Allow Members To Toggle Presence Tracking Enablement &lt;/strong&gt;and&lt;strong&gt; Default Presence Tracking Enablement Value &amp;nbsp;&lt;/strong&gt;available under Membership in the Membership Options panel in Administration. &amp;nbsp;&lt;strong&gt;Enable Presence Tracking&amp;nbsp;&lt;/strong&gt;controls whether user presence tracking is available for the community. &amp;nbsp;If tracking is enabled, &amp;nbsp;&lt;strong&gt;Allow Members To Toggle Presence Tracking Enablement&lt;/strong&gt; controls whether or not each user should have the option to disable tracking of their online status. If that option is enabled the&amp;nbsp;&lt;strong&gt;Default Presence Tracking Enablement Value&amp;nbsp;&lt;/strong&gt;is also available. &amp;nbsp;If users are giving the option to control their presence tracking, the&amp;nbsp;&lt;strong&gt;Enable presence tracking&lt;/strong&gt; option will be available in the membership settings.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence-admin.png"&gt;&lt;img alt=" " src="/resized-image/__size/550x539/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence-admin.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l50j"&gt;&lt;a id="Example_Socket_using_Content_Presence_Service" name="Example_Socket_using_Content_Presence_Service"&gt;&lt;/a&gt;Example Socket using Content Presence&lt;/h2&gt;
&lt;p&gt;This example will&amp;nbsp;create an &lt;code&gt;ISocket&lt;/code&gt; implementation that will send socket messages to users when a vote is received or changed on an idea. By combining the socket implementation with the content presence service, the socket messages can be sent only to those users who are currently viewing the idea that received the vote.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50k"&gt;&lt;a id="Server_Side" name="Server_Side"&gt;&lt;/a&gt;Server Side&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;ISocket&lt;/code&gt; implementation will use the &lt;em&gt;ideavotes&lt;/em&gt; for the &lt;code&gt;SocketName &lt;/code&gt;and maintain a reference to the &lt;code&gt;SocketController&lt;/code&gt; for later use in our example.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;ISocketController _sockets;
public string SocketName =&amp;gt; &amp;quot;ideavotes&amp;quot;;

public void SetController(ISocketController controller)
{
    _sockets = controller;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The example class will need to send a message whenever an idea is&amp;nbsp;voted on, this can be accomplished by attaching to the Idea Vote Events for these actions in our plugin&amp;#39;s &lt;code&gt;Initialize&lt;/code&gt; method. &amp;nbsp;In each event handler, we will call the same method SendVoteCounts passing the idea id for the vote.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public void Initialize()
{
    _ideas = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IIdeas&amp;gt;();

    _ideaVotes = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IVotes&amp;gt;();
    _ideaVotes.Events.AfterCreate += VoteCreated;
    _ideaVotes.Events.AfterDelete += VoteDeleted;
    _ideaVotes.Events.AfterUpdate += VoteUpdated;
}

private void VoteCreated(VoteAfterCreateEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}

private void VoteUpdated(VoteAfterUpdateEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}

private void VoteDeleted(VoteAfterDeleteEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;In the SendVoteCounts method, the number of up and down votes will be retrieved and the&amp;nbsp;&lt;code&gt;_sockets.Clients.SendToUsersPresentToContent &lt;/code&gt;method will be used to send a message to all users who are currently present to that idea.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;void SendVoteCounts(Guid ideaId)
{
    var idea = _ideas.Get(ideaId);
    if (idea != null &amp;amp;&amp;amp; !idea.HasErrors())
    {
        var upVotes =
            _ideaVotes.List(new VotesListOptions() {IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = true });

        var downVotes =
            _ideaVotes.List(new VotesListOptions() { IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = false });

        // send socket message with updated totals
        _sockets.Clients.SendToUsersPresentToContent(idea.ContentId, &amp;quot;ideavoted&amp;quot;, new
        {
            contentId = idea.ContentId,
            contentTypeId = _ideas.ContentTypeId,
            yesVotes = upVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;,
            noVotes = downVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;
        });
    }
}&lt;/pre&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50l"&gt;&lt;a id="Client_Side" name="Client_Side"&gt;&lt;/a&gt;Client Side&lt;/h3&gt;
&lt;p&gt;Once this plugin is compiled and enabled on the community site, each time an idea is voted on any user who is viewing that idea will receive an &lt;em&gt;ideavoted&amp;nbsp;&lt;/em&gt;socket message. &amp;nbsp;For this example, we can use a widget to see these messages. &amp;nbsp;The example will&amp;nbsp;make use of the&amp;nbsp;&lt;code&gt;$.telligent.evolution.sockets.ideavotes&lt;/code&gt; API that is automatically generated for our &lt;code&gt;ISocket&lt;/code&gt; implementation. &amp;nbsp;That API will enable the widget to listen for messages from the custom socket. &amp;nbsp;In this case, the message&amp;#39;s data will output to the browser&amp;#39;s console window.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="javascript"&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
	jQuery.telligent.evolution.sockets.ideavotes.on(&amp;#39;ideavoted&amp;#39;, function(data) {
		console.log(data);
	});
});
&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The widget can be placed on the Idea page or Idea List page,&amp;nbsp;you will be able to see the messages for the ideas you are currently viewing when any vote is received on the idea(s) you are currently viewing.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50m"&gt;&lt;a id="Completed_Sample" name="Completed_Sample"&gt;&lt;/a&gt;Completed Sample&lt;/h3&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;using System;
using Telligent.Evolution.Extensibility.Ideation.Api;
using Telligent.Evolution.Extensibility.Sockets.Version1;
using Telligent.Evolution.Extensibility.Version1;

namespace Telligent.Evolution.Examples
{
    public class VoteSocket : IPlugin, ISocket
    {
        ISocketController _sockets;
        IIdeas _ideas;
        IVotes _ideaVotes;

        public string Name =&amp;gt; &amp;quot;Idea Vote Sockets&amp;quot;;
        public string Description =&amp;gt; &amp;quot;Enables live updates to idea votes.&amp;quot;;
        public string SocketName =&amp;gt; &amp;quot;ideavotes&amp;quot;;

        public void Initialize()
        {
            _ideas = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IIdeas&amp;gt;();

            _ideaVotes = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IVotes&amp;gt;();
            _ideaVotes.Events.AfterCreate += VoteCreated;
            _ideaVotes.Events.AfterDelete += VoteDeleted;
            _ideaVotes.Events.AfterUpdate += VoteUpdated;
        }

        public void SetController(ISocketController controller)
        {
            _sockets = controller;
        }

        private void VoteCreated(VoteAfterCreateEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        private void VoteUpdated(VoteAfterUpdateEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        private void VoteDeleted(VoteAfterDeleteEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        void SendVoteCounts(Guid ideaId)
        {
            var idea = _ideas.Get(ideaId);
            if (idea != null &amp;amp;&amp;amp; !idea.HasErrors())
            {
                var upVotes =
                    _ideaVotes.List(new VotesListOptions() {IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = true });

                var downVotes =
                    _ideaVotes.List(new VotesListOptions() { IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = false });

                // send socket message with updated totals
                _sockets.Clients.SendToUsersPresentToContent(idea.ContentId, &amp;quot;ideavoted&amp;quot;, new
                {
                    contentId = idea.ContentId,
                    contentTypeId = _ideas.ContentTypeId,
                    yesVotes = upVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;,
                    noVotes = downVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;
                });
            }
        }
    }
}
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="xml"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;
&amp;lt;scriptedContentFragments&amp;gt;
  &amp;lt;scriptedContentFragment name=&amp;quot;Idea Socket Presence Test&amp;quot; version=&amp;quot;10.0.0.0&amp;quot; description=&amp;quot;&amp;quot; instanceIdentifier=&amp;quot;c7e0a2c7d2b44ab08f22d8938ef03a06&amp;quot; theme=&amp;quot;&amp;quot; isCacheable=&amp;quot;false&amp;quot; varyCacheByUser=&amp;quot;false&amp;quot; showHeaderByDefault=&amp;quot;false&amp;quot; cssClass=&amp;quot;&amp;quot; provider=&amp;quot;7bb87a0cc5864a9392ae5b9e5f9747b7&amp;quot;&amp;gt;
    &amp;lt;contentScript&amp;gt;&amp;lt;![CDATA[

&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
	jQuery.telligent.evolution.sockets.ideavotes.on(&amp;#39;ideavoted&amp;#39;, function(data) {
		console.log(data);
	});
});
&amp;lt;/script&amp;gt;

]]&amp;gt;&amp;lt;/contentScript&amp;gt;
  &amp;lt;/scriptedContentFragment&amp;gt;
&amp;lt;/scriptedContentFragments&amp;gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l50a"&gt;&lt;a id="Scale-out" name="Scale-out"&gt;&lt;/a&gt;Scale-out&lt;/h2&gt;
&lt;h3 id="mcetoc_1dio78l50b"&gt;&lt;a id="Overview" name="Overview"&gt;&lt;/a&gt;Overview&lt;/h3&gt;
&lt;p&gt;While multiple users connected to a single web node are easy enough to reason about, this becomes more complicated&amp;nbsp;when there are multiple app nodes and&amp;nbsp;a job server. Consider&amp;nbsp;the case of User A on Server X and User B on Server Y where User A intends to send a real-time chat socket message to User B. The socket message must not only be sent to a different user, it must be sent to that user from a different server entirely. Or consider the case of a plugin running in the context of a job on the job server instead of a web node which also intends to send a socket message to a user, such as a socket-based message&amp;nbsp;that some delayed process has completed. The job server is not connected directly to any users, and so needs to communicate with the web nodes in order to deliver socket messages.&lt;/p&gt;
&lt;p&gt;These scenarios are already&amp;nbsp;&lt;em&gt;automatically and transparently&lt;/em&gt; supported through the use of the message bus.&amp;nbsp;&lt;strong&gt;Verint Community requires the use of a&amp;nbsp;message bus&lt;/strong&gt;. Verint Community comes with&amp;nbsp;two possible message bus services built in, the Socket Message Bus Windows Service as well as the lower performance&amp;nbsp;Database Message Bus. At least one of these services or another conforming message bus is required to be enabled as part of the installation of Community.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50c"&gt;&lt;a id="Socket_Message_Bus_Server" name="Socket_Message_Bus_Server"&gt;&lt;/a&gt;Socket Message Bus Service&lt;/h3&gt;
&lt;p&gt;Verint&amp;nbsp;Community comes with the Socket Message Bus Windows Service and its corresponding &lt;code&gt;ISocketMessageBus&lt;/code&gt; plugin-based connector, &lt;em&gt;Socket Message Bus Service &lt;/em&gt;available in&lt;em&gt; Administration &amp;gt; Site &amp;gt; Message Buses&lt;/em&gt;. This is simply a Windows Service which echoes messages it receives to all connected Verint&amp;nbsp;Community instances.&lt;/p&gt;
&lt;p&gt;Community also includes an alternative Database Message Bus which&amp;nbsp;has lower performance, but requires no separate service installation.&amp;nbsp;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50d"&gt;&lt;a id="Custom_Message_Bus" name="Custom_Message_Bus"&gt;&lt;/a&gt;Custom Message Bus&lt;/h3&gt;
&lt;p&gt;In cases where a community would prefer to use an existing third party message bus solution, custom &lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus plugins&lt;/a&gt; can be written against it and deployed. An example could be a message bus service which supports multiple Verint&amp;nbsp;Community communities on a single bus server by potentially adding an identifier to the string messages sent and received by the plugin for routing the message on the bus server.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50e"&gt;&lt;a id="Generic_Messages" name="Generic_Messages"&gt;&lt;/a&gt;Generic Messages&lt;/h3&gt;
&lt;p&gt;Custom logic in &lt;code&gt;ISocket&lt;/code&gt; plugins can also make use of the message bus directly. Generic messages can be useful for keeping small amounts&amp;nbsp;of state synchronized in realtime across application instances.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt; injected into &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; plugins contains an instance of an &lt;a href="/developers/w/developer90/50167.imessagebuscontroller-plugin-supplementary-type"&gt;IMessageBusController&lt;/a&gt;. The &lt;a href="/developers/w/developer90/50167.imessagebuscontroller-plugin-supplementary-type"&gt;IMessageBusController&lt;/a&gt; exposes events for when generic messages are received from instances of the application along with a method for sending them.&lt;/p&gt;
&lt;p&gt;A useful pattern for state change is to send a generic message to the bus, and only handle it once it is re-received. This allows all instances to know about the state. Additionally, the instance that sends it receives the message immediately without having to wait for the round-trip, and is made aware of the local origin of the message. In this manner, the sender can also be exclusively responsible for potentially persisting the state change elsewhere.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;controller.MessageBus.Publish(&amp;quot;something.happened&amp;quot;,&amp;quot;&amp;quot;);
controller.MessageBus.Received += (sender, e) =&amp;gt;
{
    if (e.MessageName == &amp;quot;something.happened&amp;quot;)
    {
        // update some local caches
        // ...
        if (e.Source == BusMessageSource.Local)
        {
            // update DB
            // ...
        }
    }
};&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l50n"&gt;&lt;a id="Tips_and_Tricks" name="Tips_and_Tricks"&gt;&lt;/a&gt;Additional Notes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Socket connections are only established for authenticated, non-system, users&lt;/li&gt;
&lt;li&gt;User disconnection events are raised whenever&amp;nbsp;a user&amp;#39;s last window&amp;nbsp;or tab for a&amp;nbsp;browser closes, as they all share a single connection. Disconnection events can also raise when plugins refresh.&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: socket, messaging, presence, bus&lt;/div&gt;
</description></item><item><title>Sockets and Presence</title><link>https://community.telligent.com/community/11/w/developer-training/65063/sockets-and-presence/revision/8</link><pubDate>Tue, 20 Aug 2019 22:03:47 GMT</pubDate><guid isPermaLink="false">f141b2d7-5f01-47b0-ab4d-105e12603c36</guid><dc:creator>Michael Monteleone</dc:creator><comments>https://community.telligent.com/community/11/w/developer-training/65063/sockets-and-presence#comments</comments><description>Revision 8 posted to Developer Training by Michael Monteleone on 08/20/2019 22:03:47&lt;br /&gt;
&lt;p&gt;The Socket Framework provides support for &lt;strong&gt;real-time two-way communication between Verint Community and the browser&lt;/strong&gt;. This enables&amp;nbsp;receiving and sending messages directly to specific users or scoped&amp;nbsp;groups of users.&lt;/p&gt;
&lt;p&gt;[toc]&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l500"&gt;&lt;a id="When_would_I_want_to_use_sockets" name="When_would_I_want_to_use_sockets"&gt;&lt;/a&gt;When would I want to use sockets or presence?&lt;/h2&gt;
&lt;p&gt;Sockets are useful when you need to push messages from the server to the browser. An easy example to consider is a notification popup that is pushed to a user in the event of an action occurring on the server. Sockets are the mechanism through which built-in platform features including notifications, chat, live activity streams, forum threads, comment threads,&amp;nbsp;theme previews, presence indicators, tracing, and more communicate with the browser.&amp;nbsp;Socket plugins can&amp;nbsp;be developed to easily power other functionality like real-time whiteboards, analytics, or even games.&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l501"&gt;&lt;a id="Overview" name="Overview"&gt;&lt;/a&gt;Overview&lt;/h2&gt;
&lt;p&gt;Built on top of &lt;a href="http://signalr.net/"&gt;SignalR&lt;/a&gt;, the Socket Framework inherits all of SignalR&amp;#39;s performance, stability, and diversity of browser support over underlying WebSocket, server-sent event, or&amp;nbsp;long polling transports. Because it is Verint&amp;nbsp;Community-specific, the Socket Framework can provide:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;[[Plugins|Plugin]] based extensibility&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Both built-in and third-party [[Plugins|plugin]] can implement their own &lt;em&gt;sockets&lt;/em&gt; which each define a pair of server and client methods and events for bi-directional communication, all multiplexed over a single&amp;nbsp;underlying connection to the server.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Presence&lt;/strong&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Users&amp;#39; site presence as well as their presence to individual pieces of content regardless of how and where that content is viewed&amp;nbsp;is&amp;nbsp;tracked&amp;nbsp;to enable&amp;nbsp;delivery of messages scoped only to&amp;nbsp;users viewing&amp;nbsp;specific&amp;nbsp;content. Additionally, Service Presence supports a similar, but non-content-based scoping of messages.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scale-out and reliability&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;All sockets are multiplexed across&amp;nbsp;a single connection between&amp;nbsp;the server and browser. Additionally,&amp;nbsp;the browser shares the same, single, connection across all of its windows and&amp;nbsp;tabs, transparently identifying a single window or tab at a time to serve&amp;nbsp;as the connection&amp;#39;s host.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Socket connections are reliably maintained and reconnect after any disconnections with randomized, exponential, retry backoffs.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;To support scale-out to multiple application instances and&amp;nbsp;delivery&amp;nbsp;of socket messages from plugins&amp;nbsp;running outside of web contexts in the job server, Verint&amp;nbsp;Community automatically distributes message sending&amp;nbsp;across a bus.&amp;nbsp;Community&amp;nbsp;bundles two&amp;nbsp;possible message bus servers: the Socket Message Bus Service as well as the lower-performing Database Message Bus. Alternatively, Verint&amp;nbsp;Community can use &lt;em&gt;any&lt;/em&gt; message bus service through plugin extensibility. The configuration of which message bus server to use, if any at all, is defined by [[Plugins|plugin]]-based connectors, which can be enabled or disabled through standard plugin management without restarting the application. Socket plugins also expose the underlying bus for use as a way to keep real-time application state in synchronization across multiple instances as needed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="mcetoc_1dio78l502"&gt;&lt;a id="API" name="API"&gt;&lt;/a&gt;API&lt;/h2&gt;
&lt;p&gt;The server-side API exists as a set of interfaces implementable by [[Plugins|plugins]].&lt;/p&gt;
&lt;p&gt;&lt;img alt=" " src="/resized-image/__size/640x480/__key/communityserver-wikis-components-files/00-00-00-12-83/sockets.png" /&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l503"&gt;&lt;a id="ISocket_Plugin" name="ISocket_Plugin"&gt;&lt;/a&gt;&lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket Plugin&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A socket is defined by a [[Plugins|plugin]] which implements the &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; interface. A single socket plugin represents a single channel of communication between the server and browser. For example, a socket plugin may represent all functionality related to sending and receiving realtime chat messages. A single socket plugin can send and receive arbitrary messages and optional data with those messages, but can only send or receive messages sent by or to the same socket plugin.&lt;/p&gt;
&lt;p&gt;Socket plugins are injected with instances of &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt; exposes an instance of an &lt;a href="/developers/w/developer90/50149.iclientscontroller-plugin-supplementary-type"&gt;IClientsController&lt;/a&gt; which contains events for when a user connects, disconnects, or sends a message from the browser. The &lt;a href="/developers/w/developer90/50149.iclientscontroller-plugin-supplementary-type"&gt;IClientsController&lt;/a&gt; also supports sending messages to a user, to all users present to specific&amp;nbsp;content or services, or broadcasting to all users.&lt;/p&gt;
&lt;p&gt;Each enabled socket plugin yields a corresponding client-side API.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l504"&gt;&lt;a id="ISocketMessageBus_Plugin" name="ISocketMessageBus_Plugin"&gt;&lt;/a&gt;&lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus Plugin&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Multiple-application instance scale-out and message delivery from non-web contexts like job server plugins is automatically&amp;nbsp;supported&amp;nbsp;by&amp;nbsp;the&amp;nbsp;enablement of plugins which implement the &lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus&lt;/a&gt; interface. Verint&amp;nbsp;Community bundles two default implementations to connect to either the Socket Message Bus Service or the Database Message Bus, but also supports integrating with other message busses as well. For details, see the discussion on Scale-Out.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l505"&gt;&lt;a id="Client-Side" name="Client-Side"&gt;&lt;/a&gt;Client-Side&lt;/h3&gt;
&lt;h4&gt;&lt;a id="Socket_Endpoints" name="Socket_Endpoints"&gt;&lt;/a&gt;Socket Endpoints&lt;/h4&gt;
&lt;p&gt;Each &lt;code&gt;ISocket&lt;/code&gt; plugin implements a &lt;code&gt;SocketName&lt;/code&gt;. This one-word string becomes the name of the client-side API. For example, given the socket:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public class MySocket : ISocket
{
    // ...

    string SocketName =&amp;gt; &amp;quot;mySocket&amp;quot;;

    // ...
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Then the following JavaScript API will be automatically exposed:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="javascript"&gt;// receive and handle a message with optional data from the server
jQuery.telligent.evolution.sockets.mySocket.on(messageName, function(data) {
   // handle
});

// send data to the server an optional object message
jQuery.telligent.evolution.sockets.mySocket.send(messageName, data);&lt;/pre&gt;&lt;/p&gt;
&lt;h4&gt;&lt;a id="Initiation" name="Initiation"&gt;&lt;/a&gt;Initiation&lt;/h4&gt;
&lt;p&gt;Before attempting to send or receive messages from the client side, the Socket Framework must initiate itself. This happens automatically, and when complete, it publishes a &lt;a href="/developers/w/developer90/50006.socket-connected-client-message"&gt;socket.connected&lt;/a&gt; &lt;a href="/developers/w/developer90/50024.messaging-javascript-api-module"&gt;client-side message&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="javascript"&gt;jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
    // set up message listeners or send messages
});&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l506"&gt;&lt;a id="Example_Socket" name="Example_Socket"&gt;&lt;/a&gt;Simple Example Socket&lt;/h2&gt;
&lt;p&gt;The following shows a basic example of a socket which routes greetings from one user to another. A user provides the user name of another community member, clicks &amp;#39;greet&amp;#39;, and an alert is displayed to the other user.&lt;/p&gt;
&lt;p&gt;Greetings are initiated from a user via a widget, sent via the client-side socket API to the &lt;code&gt;ISocket&lt;/code&gt; plugin, and then delivered to the recipient user where the same widget instance for the other user will display the message in a JavaScript &lt;code&gt;alert()&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l507"&gt;&lt;a id="Server_Side" name="Server_Side"&gt;&lt;/a&gt;Server Side&lt;/h3&gt;
&lt;p&gt;Create a new [[Plugins|plugin]] which implements the &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; interface. Its &lt;code&gt;Name&lt;/code&gt;, &lt;code&gt;Description&lt;/code&gt;, and &lt;code&gt;Initialize()&lt;/code&gt; are unimportant. For &lt;code&gt;SocketName&lt;/code&gt; and &lt;code&gt;SetController()&lt;/code&gt;, use the following:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public string SocketName =&amp;gt; &amp;quot;greeter&amp;quot;;

public void SetController(ISocketController controller)
{
    controller.Clients.Received += (sender, e) =&amp;gt;
    {
        // if this was a greting message, let&amp;#39;s process it
        if (e.MessageName == &amp;quot;greet&amp;quot;)
        {
            // get the associated recipient user
            // data passed from the client side is available on the dynamic MessageData object
            var to = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;Telligent.Evolution.Extensibility.Api.Version1.IUsers&amp;gt;().Users.Get(new Telligent.Evolution.Extensibility.Api.Version1.UsersGetOptions { Username = (string)e.MessageData.Recipient });

            // get the sender user
            var from = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;Telligent.Evolution.Extensibility.Api.Version1.IUsers&amp;gt;().Get(new Telligent.Evolution.Extensibility.Api.Version1.UsersGetOptions { Id = e.UserId });

            // send a new message to the recipient
            controller.Clients.Send(to.Id.GetValueOrDefault(), &amp;quot;greet&amp;quot;, new
            {
                Message = String.Format(&amp;quot;Hello {0}, from {1}&amp;quot;, to.DisplayName, from.DisplayName)
            });
        }
    };
}&lt;/pre&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l508"&gt;&lt;a id="Client_Side" name="Client_Side"&gt;&lt;/a&gt;Client Side&lt;/h3&gt;
&lt;p&gt;In Widget Studio, create a new widget&amp;nbsp;with content:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="velocity"&gt;## set up some unique ids for interface elements
#set($recipientInputId = $core_v2_widget.UniqueId(&amp;#39;recipient&amp;#39;))
#set($sendLinkId = $core_v2_widget.UniqueId(&amp;#39;greet&amp;#39;))

## basic interface
&amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;$recipientInputId&amp;quot; /&amp;gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;$sendLinkId&amp;quot;&amp;gt;Greet&amp;lt;/a&amp;gt;

&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
// Wait for socket to be connected
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {

    // when &amp;#39;Greet&amp;#39; is clicked, send a message to be delivered to the recipient
    jQuery(&amp;#39;#$sendLinkId&amp;#39;).on(&amp;#39;click&amp;#39;, function(e) {
        e.preventDefault();

        jQuery.telligent.evolution.sockets.greeter.send(&amp;#39;greet&amp;#39;, {
            Recipient: jQuery(&amp;#39;#$recipientInputId&amp;#39;).val()
        });
    });

    // when a &amp;#39;greet&amp;#39; message is received from the socket, display it as an alert
    jQuery.telligent.evolution.sockets.greeter.on(&amp;#39;greet&amp;#39;, function(data){
        alert(data.Message);
    });
});
&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Note use of the &lt;a href="/developers/w/developer90/50006.socket-connected-client-message"&gt;socket.connected&lt;/a&gt; &lt;a href="/developers/w/developer90/50024.messaging-javascript-api-module"&gt;client-side message&lt;/a&gt; as well as the automatically-generated &lt;code&gt;jQuery.telligent.evolution.sockets.testSocket&lt;/code&gt; API.&lt;/p&gt;
&lt;p&gt;The result is a simple UI that enables sending a greeting to another user by their user name.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter.png"&gt;&lt;img style="border:1px solid #DDD;width:264px;" alt=" " src="/resized-image/__size/640x480/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter_2D00_greeted.png"&gt;&lt;img style="border:1px solid #DDD;width:485px;" alt=" " src="/resized-image/__size/640x480/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter_2D00_greeted.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l509"&gt;&lt;a id="Download" name="Download"&gt;&lt;/a&gt;Download&lt;/h3&gt;
&lt;p&gt;The complete sample can be downloaded:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/SocketSample_2E00_cs"&gt;community.telligent.com/.../SocketSample_2E00_cs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/5314.GreeterUI_2D00_Widget.xml"&gt;community.telligent.com/.../5314.GreeterUI_2D00_Widget.xml&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l50f"&gt;&lt;a id="Presence_Services" name="Presence_Services"&gt;&lt;/a&gt;Presence Services&lt;/h2&gt;
&lt;p&gt;Being able to send messages directly to individual users is a great start. However, there is often a need to send messages to specific groups of users, i.e. messages about new replies to all users viewing a given forum thread so that it may&amp;nbsp;update its UI&amp;nbsp;in realtime. To that end, presence services enable sending messages to users scoped by their &lt;em&gt;presence&lt;/em&gt; to pieces of [[content|The Content Model]] or abstract &lt;em&gt;service&lt;/em&gt;&amp;nbsp;groupings.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50h"&gt;&lt;a id="Content_Presence" name="Content_Presence"&gt;&lt;/a&gt;Content Presence&lt;/h3&gt;
&lt;p&gt;The Content Presence service tracks which &lt;span&gt;[[content|&lt;/span&gt;&lt;span&gt;The Content Model]]&lt;/span&gt; users are currently viewing. This enables the platform to deliver updates to&amp;nbsp;users in real time regarding&amp;nbsp;changes to content they are currently viewing. &lt;strong&gt;Importantly&lt;/strong&gt;, this can mean in whatever or wherever way that the content is presented. For example, a user viewing a forum thread&amp;#39;s question&amp;nbsp;in a group&amp;#39;s&amp;nbsp;activity stream is considered and tracked&amp;nbsp;as present to that forum&amp;nbsp;thread&amp;nbsp;the same&amp;nbsp;as a user on the forum thread&amp;#39;s own page. Also importantly, content presence even takes into account whether the content&amp;#39;s UI is scrolled into view. For example, a user is&amp;nbsp;&lt;em&gt;not&lt;/em&gt; be present to another forum thread whose activity story is&amp;nbsp;scrolled out of browser view in the activity stream.&lt;/p&gt;
&lt;h4&gt;&lt;/h4&gt;
&lt;h4&gt;&lt;a id="Content_Presence_Mappings" name="Content_Presence_Mappings"&gt;&lt;/a&gt;Content Presence&amp;nbsp;Mappings&lt;/h4&gt;
&lt;p&gt;To understand content presence APIs, it is important to first understand &lt;em&gt;the ways in which&amp;nbsp;content presence mappings are created and removed:&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Page Context&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;The service uses [[URL context|Page Definition and URL Routing]] to track what content the using is currently viewing. As long as a user is on a URL with content context, the user is present to those content records. For example,&amp;nbsp;if a user is viewing a blog post, the content service would be aware that the user is present to&amp;nbsp;that blog post, the blog, and even the post&amp;#39;s author&amp;#39;s content records. So, sending a socket message to any of those three content IDs would deliver it to the viewing user.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HTML presence&amp;nbsp;attributes&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;In addition to overall page context, specific portions of a page&amp;#39;s UI can identify themselves as representing specific content, so that while a user is viewing that UI, the user also is also mapped as present to the&amp;nbsp;content. These identifications are represented as attributes added to the HTML&amp;nbsp;element.&amp;nbsp;The activity stream uses such HTML presence attributes to wrap stories in the stream so that the user is present to stories&amp;#39; corresponding content, and only when those stories are scrolled into view.&lt;/li&gt;
&lt;li&gt;HTML presence&amp;nbsp;attributes can be added to through the &lt;code&gt;core_v2_contentPresence.RenderAttributes&lt;/code&gt; method. &amp;nbsp;This method will render the proper attributes to automatically track a user&amp;#39;s content presence, when the decorated element is currently visible on the page they are viewing. &amp;nbsp;The comment stream and activity stream are two examples where this method is in use.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;APIs&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&amp;nbsp;In-Process, Rest and Script&amp;nbsp;APIs are available to directly add and remove&amp;nbsp;presence mappings, though these are rarely needed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Content presence mappings are&amp;nbsp;&lt;em&gt;automatically removed&lt;/em&gt;&amp;nbsp;when they expire. As long as a user is on a page, the page is pinging back to the server to identify that the user is online, and to identify the list of content records the user is present to, whether they were&amp;nbsp;identified by the overall page&amp;#39;s context, or the currently scrolled elements decorated with&amp;nbsp;HTML presence attributes. Presence mappings that have not been refreshed for across a few&amp;nbsp;of these pings are considered expired and unmapped, thereby removing the user from receipt of socket messages&amp;nbsp;sent to users present to the content. Since&amp;nbsp;all windows and tabs of a single browser share a single socket connection, the single connection sends a ping identifying present content records across &lt;em&gt;all&lt;/em&gt; open windows and tabs.&lt;/p&gt;
&lt;h4&gt;&lt;a id="Content_Presence_API" name="Content_Presence_API"&gt;&lt;/a&gt;Content Presence API&lt;/h4&gt;
&lt;p&gt;Content presence APIs enable sending messages, querying total presence counts, and registering specific presence mappings.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;To send messages&lt;/em&gt;, use &lt;a href="/community/11/w/api-documentation/64162/iclientscontroller-plugin-supplementary-type"&gt;IClientsController.SendToUsersPresentToContent(Guid contentId, string messageName)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To query&lt;em&gt;&amp;nbsp;metadata summaries&lt;/em&gt; about users present to a given piece of content via &lt;a href="/11/w/api-documentation/63974/contentpresence-in-process-api-service"&gt;&lt;code&gt;IContentPresence&lt;/code&gt;&lt;/a&gt; or&amp;nbsp;&lt;code&gt;&lt;a href="/community/11/w/api-documentation/65749/core_5f00_v2_5f00_contentpresence-script-api"&gt;core_v2_contentPresence.GetSummary()&lt;/a&gt;. &lt;/code&gt;This metadata&amp;nbsp;is just a count summary, and may&amp;nbsp;be delayed.&lt;/p&gt;
&lt;p&gt;To register specific HTML elements as representing content so that&amp;nbsp;the user is mapped to the content while viewing the element, use &lt;code&gt;&lt;a href="/community/11/w/api-documentation/65749/core_5f00_v2_5f00_contentpresence-script-api#RenderAttributes"&gt;core_v2_contentPresence.RenderAttributes()&lt;/a&gt;&lt;/code&gt;&lt;span&gt;.&amp;nbsp;This method will render the proper attributes&amp;nbsp;to include inline with any HTML element, such as a &amp;lt;div&amp;gt; wrapping an activity stream story, or a &amp;lt;span&amp;gt; surrounding a like button.&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50i"&gt;&lt;a id="Service_Presence" name="Service_Presence"&gt;&lt;/a&gt;Service Presence&lt;/h3&gt;
&lt;p&gt;Service Presence is nearly identical to&amp;nbsp;Content Presence in that it enables&amp;nbsp;mapping a user&amp;#39;s presence and&amp;nbsp;sending socket messages to users based on those mappings. However, while Content Presence is&amp;nbsp;designed specifically for Content IDs and Content Type IDs and automatically maps users to content by their page context, service presence allows mapping users to &lt;em&gt;any arbitrary Guid&lt;/em&gt;. As such, there are no automatically-created service presence mappings. Service presence mappings can only be registered by specific&amp;nbsp;&lt;em&gt;HTML presence attributes&lt;/em&gt; or the APIs (rarely&amp;nbsp;used). (Please see the above discussion on Content Presence Mappings for a discussion on how such attributes work.)&lt;/p&gt;
&lt;p&gt;In this way, a widget can define an HTML element to contain&amp;nbsp;a service presence mapping of any arbitrary ID.&amp;nbsp;Any user viewing that widget will be considered present to that ID &amp;quot;service&amp;quot;. And a socket plugin can then deliver a message to any user viewing&amp;nbsp;that widget by the same arbitrary service presence ID.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Similar to content presence, service presence mappings&amp;nbsp;automatically expire.&lt;/p&gt;
&lt;p&gt;While less frequently needed than content presence, service presence provides flexibility for edge cases.&lt;/p&gt;
&lt;h4&gt;&lt;a id="Service_Presence_API" name="Service_Presence_API"&gt;&lt;/a&gt;Service Presence API&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;To send messages&lt;/em&gt;, use &lt;a href="/community/11/w/api-documentation/64162/iclientscontroller-plugin-supplementary-type"&gt;IClientsController.SendToUsersPresentToContent(Guid contentId, string messageName)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To query&lt;em&gt;&amp;nbsp;metadata summaries&lt;/em&gt; about users present to an ID via &lt;a href="/community/11/w/api-documentation/64069/servicepresence-in-process-api-service"&gt;&lt;code&gt;IServicePresence&lt;/code&gt;&lt;/a&gt; or&amp;nbsp;&lt;code&gt;&lt;a href="/community/11/w/api-documentation/65767/core_5f00_v2_5f00_servicepresence-script-api#GetSummary"&gt;core_v2_servicePresence.GetSummary()&lt;/a&gt;. &lt;/code&gt;This metadata&amp;nbsp;is just a count summary, and may&amp;nbsp;be delayed.&lt;/p&gt;
&lt;p&gt;To register specific HTML elements as services mapping ID so that&amp;nbsp;the user is mapped to the ID&amp;nbsp;while viewing the element, use &lt;code&gt;&lt;a href="/community/11/w/api-documentation/65767/core_5f00_v2_5f00_servicepresence-script-api#RenderAttributes"&gt;core_v2_servicePresence.RenderAttributes()&lt;/a&gt;&lt;/code&gt;&lt;span&gt;.&amp;nbsp;This method will render the proper attributes&amp;nbsp;to include inline with any HTML element.&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50i"&gt;&lt;/h3&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50g"&gt;&lt;a id="User_Presence" name="User_Presence"&gt;&lt;/a&gt;User Presence&lt;/h3&gt;
&lt;p&gt;User Presence is built atop sockets and content presence. After all, user records are content records, too.&lt;/p&gt;
&lt;p&gt;User presence is a set of related&amp;nbsp;UIs, APIs which track and render a user&amp;#39;s overall presence to the site.&lt;/p&gt;
&lt;h4&gt;&lt;a id="UI" name="UI"&gt;&lt;/a&gt;UI&lt;/h4&gt;
&lt;p&gt;The service is responsible for the presence indicator often&amp;nbsp;displayed alongside the user&amp;nbsp;names.&lt;/p&gt;
&lt;p&gt;&lt;img alt=" " src="/resized-image/__size/320x240/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence.png" /&gt;&lt;/p&gt;
&lt;h4&gt;&lt;a id="API" name="API"&gt;&lt;/a&gt;API&lt;/h4&gt;
&lt;p&gt;Live-updating user presence indicators&amp;nbsp;can be easily&amp;nbsp;rendered with &lt;code&gt;&lt;a href="/community/11/w/api-documentation/65797/core_5f00_v2_5f00_ui-script-api#UserPresence"&gt;core_v2_ui.UserPresence()&lt;/a&gt;&lt;/code&gt;. These are an easy way to add benefits of realtime-updating presence to your UI to&amp;nbsp;improve engagement in your community.&lt;/p&gt;
&lt;p&gt;Of note, core_v2_ui.UserPresence is, itself, built on top of these&amp;nbsp;APIs. It renders a &lt;a href="/community/11/w/api-documentation/65143/ui-javascript-api-module"&gt;UI component&lt;/a&gt; which presents&amp;nbsp;an indicator dot wrapped with content presence HTML attributes&amp;nbsp;registering&amp;nbsp;the&amp;nbsp;accessing user as present to the&amp;nbsp;user being indicated so that socket messages sent on users&amp;#39; presence change events&amp;nbsp;can be delivered to anyone viewing the changed users&amp;#39; indicators.&lt;/p&gt;
&lt;p&gt;A user&amp;#39;s current presence is an attribute of the user&amp;#39;s entity, returned from REST, Script, or In-Process APIs. Like other user property changes, changes to their presence can be handled with events.&lt;/p&gt;
&lt;p&gt;Similar to content and service presence mappings, users&amp;#39; presences are automatically set to offline whenever the user closes all of their browser windows and tabs or after the last of their content presence mappings expire.&lt;/p&gt;
&lt;h4&gt;&lt;a id="Privacy" name="Privacy"&gt;&lt;/a&gt;Privacy&lt;/h4&gt;
&lt;p&gt;The platform has the options for&amp;nbsp;&lt;strong&gt;Enable Presence Tracking&lt;/strong&gt;,&amp;nbsp;&lt;strong&gt;Allow Members To Toggle Presence Tracking Enablement &lt;/strong&gt;and&lt;strong&gt; Default Presence Tracking Enablement Value &amp;nbsp;&lt;/strong&gt;available under Membership in the Membership Options panel in Administration. &amp;nbsp;&lt;strong&gt;Enable Presence Tracking&amp;nbsp;&lt;/strong&gt;controls whether user presence tracking is available for the community. &amp;nbsp;If tracking is enabled, &amp;nbsp;&lt;strong&gt;Allow Members To Toggle Presence Tracking Enablement&lt;/strong&gt; controls whether or not each user should have the option to disable tracking of their online status. If that option is enabled the&amp;nbsp;&lt;strong&gt;Default Presence Tracking Enablement Value&amp;nbsp;&lt;/strong&gt;is also available. &amp;nbsp;If users are giving the option to control their presence tracking, the&amp;nbsp;&lt;strong&gt;Enable presence tracking&lt;/strong&gt; option will be available in the membership settings.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence-admin.png"&gt;&lt;img alt=" " src="/resized-image/__size/550x539/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence-admin.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l50j"&gt;&lt;a id="Example_Socket_using_Content_Presence_Service" name="Example_Socket_using_Content_Presence_Service"&gt;&lt;/a&gt;Example Socket using Content Presence&lt;/h2&gt;
&lt;p&gt;This example will&amp;nbsp;create an &lt;code&gt;ISocket&lt;/code&gt; implementation that will send socket messages to users when a vote is received or changed on an idea. By combining the socket implementation with the content presence service, the socket messages can be sent only to those users who are currently viewing the idea that received the vote.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50k"&gt;&lt;a id="Server_Side" name="Server_Side"&gt;&lt;/a&gt;Server Side&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;ISocket&lt;/code&gt; implementation will use the &lt;em&gt;ideavotes&lt;/em&gt; for the &lt;code&gt;SocketName &lt;/code&gt;and maintain a reference to the &lt;code&gt;SocketController&lt;/code&gt; for later use in our example.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;ISocketController _sockets;
public string SocketName =&amp;gt; &amp;quot;ideavotes&amp;quot;;

public void SetController(ISocketController controller)
{
    _sockets = controller;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The example class will need to send a message whenever an idea is&amp;nbsp;voted on, this can be accomplished by attaching to the Idea Vote Events for these actions in our plugin&amp;#39;s &lt;code&gt;Initialize&lt;/code&gt; method. &amp;nbsp;In each event handler, we will call the same method SendVoteCounts passing the idea id for the vote.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public void Initialize()
{
    _ideas = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IIdeas&amp;gt;();

    _ideaVotes = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IVotes&amp;gt;();
    _ideaVotes.Events.AfterCreate += VoteCreated;
    _ideaVotes.Events.AfterDelete += VoteDeleted;
    _ideaVotes.Events.AfterUpdate += VoteUpdated;
}

private void VoteCreated(VoteAfterCreateEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}

private void VoteUpdated(VoteAfterUpdateEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}

private void VoteDeleted(VoteAfterDeleteEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;In the SendVoteCounts method, the number of up and down votes will be retrieved and the&amp;nbsp;&lt;code&gt;_sockets.Clients.SendToUsersPresentToContent &lt;/code&gt;method will be used to send a message to all users who are currently present to that idea.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;void SendVoteCounts(Guid ideaId)
{
    var idea = _ideas.Get(ideaId);
    if (idea != null &amp;amp;&amp;amp; !idea.HasErrors())
    {
        var upVotes =
            _ideaVotes.List(new VotesListOptions() {IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = true });

        var downVotes =
            _ideaVotes.List(new VotesListOptions() { IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = false });

        // send socket message with updated totals
        _sockets.Clients.SendToUsersPresentToContent(idea.ContentId, &amp;quot;ideavoted&amp;quot;, new
        {
            contentId = idea.ContentId,
            contentTypeId = _ideas.ContentTypeId,
            yesVotes = upVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;,
            noVotes = downVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;
        });
    }
}&lt;/pre&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50l"&gt;&lt;a id="Client_Side" name="Client_Side"&gt;&lt;/a&gt;Client Side&lt;/h3&gt;
&lt;p&gt;Once this plugin is compiled and enabled on the community site, each time an idea is voted on any user who is viewing that idea will receive an &lt;em&gt;ideavoted&amp;nbsp;&lt;/em&gt;socket message. &amp;nbsp;For this example, we can use a widget to see these messages. &amp;nbsp;The example will&amp;nbsp;make use of the&amp;nbsp;&lt;code&gt;$.telligent.evolution.sockets.ideavotes&lt;/code&gt; API that is automatically generated for our &lt;code&gt;ISocket&lt;/code&gt; implementation. &amp;nbsp;That API will enable the widget to listen for messages from the custom socket. &amp;nbsp;In this case, the message&amp;#39;s data will output to the browser&amp;#39;s console window.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="javascript"&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
	jQuery.telligent.evolution.sockets.ideavotes.on(&amp;#39;ideavoted&amp;#39;, function(data) {
		console.log(data);
	});
});
&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The widget can be placed on the Idea page or Idea List page,&amp;nbsp;you will be able to see the messages for the ideas you are currently viewing when any vote is received on the idea(s) you are currently viewing.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50m"&gt;&lt;a id="Completed_Sample" name="Completed_Sample"&gt;&lt;/a&gt;Completed Sample&lt;/h3&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;using System;
using Telligent.Evolution.Extensibility.Ideation.Api;
using Telligent.Evolution.Extensibility.Sockets.Version1;
using Telligent.Evolution.Extensibility.Version1;

namespace Telligent.Evolution.Examples
{
    public class VoteSocket : IPlugin, ISocket
    {
        ISocketController _sockets;
        IIdeas _ideas;
        IVotes _ideaVotes;

        public string Name =&amp;gt; &amp;quot;Idea Vote Sockets&amp;quot;;
        public string Description =&amp;gt; &amp;quot;Enables live updates to idea votes.&amp;quot;;
        public string SocketName =&amp;gt; &amp;quot;ideavotes&amp;quot;;

        public void Initialize()
        {
            _ideas = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IIdeas&amp;gt;();

            _ideaVotes = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IVotes&amp;gt;();
            _ideaVotes.Events.AfterCreate += VoteCreated;
            _ideaVotes.Events.AfterDelete += VoteDeleted;
            _ideaVotes.Events.AfterUpdate += VoteUpdated;
        }

        public void SetController(ISocketController controller)
        {
            _sockets = controller;
        }

        private void VoteCreated(VoteAfterCreateEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        private void VoteUpdated(VoteAfterUpdateEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        private void VoteDeleted(VoteAfterDeleteEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        void SendVoteCounts(Guid ideaId)
        {
            var idea = _ideas.Get(ideaId);
            if (idea != null &amp;amp;&amp;amp; !idea.HasErrors())
            {
                var upVotes =
                    _ideaVotes.List(new VotesListOptions() {IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = true });

                var downVotes =
                    _ideaVotes.List(new VotesListOptions() { IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = false });

                // send socket message with updated totals
                _sockets.Clients.SendToUsersPresentToContent(idea.ContentId, &amp;quot;ideavoted&amp;quot;, new
                {
                    contentId = idea.ContentId,
                    contentTypeId = _ideas.ContentTypeId,
                    yesVotes = upVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;,
                    noVotes = downVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;
                });
            }
        }
    }
}
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="xml"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;
&amp;lt;scriptedContentFragments&amp;gt;
  &amp;lt;scriptedContentFragment name=&amp;quot;Idea Socket Presence Test&amp;quot; version=&amp;quot;10.0.0.0&amp;quot; description=&amp;quot;&amp;quot; instanceIdentifier=&amp;quot;c7e0a2c7d2b44ab08f22d8938ef03a06&amp;quot; theme=&amp;quot;&amp;quot; isCacheable=&amp;quot;false&amp;quot; varyCacheByUser=&amp;quot;false&amp;quot; showHeaderByDefault=&amp;quot;false&amp;quot; cssClass=&amp;quot;&amp;quot; provider=&amp;quot;7bb87a0cc5864a9392ae5b9e5f9747b7&amp;quot;&amp;gt;
    &amp;lt;contentScript&amp;gt;&amp;lt;![CDATA[

&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
	jQuery.telligent.evolution.sockets.ideavotes.on(&amp;#39;ideavoted&amp;#39;, function(data) {
		console.log(data);
	});
});
&amp;lt;/script&amp;gt;

]]&amp;gt;&amp;lt;/contentScript&amp;gt;
  &amp;lt;/scriptedContentFragment&amp;gt;
&amp;lt;/scriptedContentFragments&amp;gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l50a"&gt;&lt;a id="Scale-out" name="Scale-out"&gt;&lt;/a&gt;Scale-out&lt;/h2&gt;
&lt;h3 id="mcetoc_1dio78l50b"&gt;&lt;a id="Overview" name="Overview"&gt;&lt;/a&gt;Overview&lt;/h3&gt;
&lt;p&gt;While multiple users connected to a single web node are easy enough to reason about, this becomes more complicated&amp;nbsp;when there are multiple app nodes and&amp;nbsp;a job server. Consider&amp;nbsp;the case of User A on Server X and User B on Server Y where User A intends to send a real-time chat socket message to User B. The socket message must not only be sent to a different user, it must be sent to that user from a different server entirely. Or consider the case of a plugin running in the context of a job on the job server instead of a web node which also intends to send a socket message to a user, such as a socket-based message&amp;nbsp;that some delayed process has completed. The job server is not connected directly to any users, and so needs to communicate with the web nodes in order to deliver socket messages.&lt;/p&gt;
&lt;p&gt;These scenarios are already&amp;nbsp;&lt;em&gt;automatically and transparently&lt;/em&gt; supported through the use of the message bus.&amp;nbsp;&lt;strong&gt;Verint Community requires the use of a&amp;nbsp;message bus&lt;/strong&gt;. Verint Community comes with&amp;nbsp;two possible message bus services built in, the Socket Message Bus Windows Service as well as the lower performance&amp;nbsp;Database Message Bus. At least one of these services or another conforming message bus is required to be enabled as part of the installation of Community.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50c"&gt;&lt;a id="Socket_Message_Bus_Server" name="Socket_Message_Bus_Server"&gt;&lt;/a&gt;Socket Message Bus Service&lt;/h3&gt;
&lt;p&gt;Verint&amp;nbsp;Community comes with the Socket Message Bus Windows Service and its corresponding &lt;code&gt;ISocketMessageBus&lt;/code&gt; plugin-based connector, &lt;em&gt;Socket Message Bus Service &lt;/em&gt;available in&lt;em&gt; Administration &amp;gt; Site &amp;gt; Message Buses&lt;/em&gt;. This is simply a Windows Service which echoes messages it receives to all connected Verint&amp;nbsp;Community instances.&lt;/p&gt;
&lt;p&gt;Community also includes an alternative Database Message Bus which&amp;nbsp;has lower performance, but requires no separate service installation.&amp;nbsp;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50d"&gt;&lt;a id="Custom_Message_Bus" name="Custom_Message_Bus"&gt;&lt;/a&gt;Custom Message Bus&lt;/h3&gt;
&lt;p&gt;In cases where a community would prefer to use an existing third party message bus solution, custom &lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus plugins&lt;/a&gt; can be written against it and deployed. An example could be a message bus service which supports multiple Verint&amp;nbsp;Community communities on a single bus server by potentially adding an identifier to the string messages sent and received by the plugin for routing the message on the bus server.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50e"&gt;&lt;a id="Generic_Messages" name="Generic_Messages"&gt;&lt;/a&gt;Generic Messages&lt;/h3&gt;
&lt;p&gt;Custom logic in &lt;code&gt;ISocket&lt;/code&gt; plugins can also make use of the message bus directly. Generic messages can be useful for keeping small amounts&amp;nbsp;of state synchronized in realtime across application instances.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt; injected into &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; plugins contains an instance of an &lt;a href="/developers/w/developer90/50167.imessagebuscontroller-plugin-supplementary-type"&gt;IMessageBusController&lt;/a&gt;. The &lt;a href="/developers/w/developer90/50167.imessagebuscontroller-plugin-supplementary-type"&gt;IMessageBusController&lt;/a&gt; exposes events for when generic messages are received from instances of the application along with a method for sending them.&lt;/p&gt;
&lt;p&gt;A useful pattern for state change is to send a generic message to the bus, and only handle it once it is re-received. This allows all instances to know about the state. Additionally, the instance that sends it receives the message immediately without having to wait for the round-trip, and is made aware of the local origin of the message. In this manner, the sender can also be exclusively responsible for potentially persisting the state change elsewhere.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;controller.MessageBus.Publish(&amp;quot;something.happened&amp;quot;,&amp;quot;&amp;quot;);
controller.MessageBus.Received += (sender, e) =&amp;gt;
{
    if (e.MessageName == &amp;quot;something.happened&amp;quot;)
    {
        // update some local caches
        // ...
        if (e.Source == BusMessageSource.Local)
        {
            // update DB
            // ...
        }
    }
};&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l50n"&gt;&lt;a id="Tips_and_Tricks" name="Tips_and_Tricks"&gt;&lt;/a&gt;Additional Notes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Socket connections are only established for authenticated, non-system, users&lt;/li&gt;
&lt;li&gt;User disconnection events are raised whenever&amp;nbsp;a user&amp;#39;s last window&amp;nbsp;or tab for a&amp;nbsp;browser closes, as they all share a single connection. Disconnection events can also raise when plugins refresh.&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: socket, messaging, presence, bus&lt;/div&gt;
</description></item><item><title>Sockets and Presence</title><link>https://community.telligent.com/community/11/w/developer-training/65063/sockets-and-presence/revision/7</link><pubDate>Tue, 20 Aug 2019 22:02:04 GMT</pubDate><guid isPermaLink="false">f141b2d7-5f01-47b0-ab4d-105e12603c36</guid><dc:creator>Michael Monteleone</dc:creator><comments>https://community.telligent.com/community/11/w/developer-training/65063/sockets-and-presence#comments</comments><description>Revision 7 posted to Developer Training by Michael Monteleone on 08/20/2019 22:02:04&lt;br /&gt;
&lt;p&gt;The Socket Framework provides support for &lt;strong&gt;real-time two-way communication between Verint Community and the browser&lt;/strong&gt;. This enables&amp;nbsp;receiving and sending messages directly to specific users or scoped&amp;nbsp;groups of users.&lt;/p&gt;
&lt;p&gt;[toc]&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l500"&gt;&lt;a id="When_would_I_want_to_use_sockets" name="When_would_I_want_to_use_sockets"&gt;&lt;/a&gt;When would I want to use sockets or presence?&lt;/h2&gt;
&lt;p&gt;Sockets are useful when you need to push messages from the server to the browser. An easy example to consider is a notification popup that is pushed to a user in the event of an action occurring on the server. Sockets are the mechanism through which built-in platform features including notifications, chat, live activity streams, forum threads, comment threads,&amp;nbsp;theme previews, presence indicators, tracing, and more communicate with the browser.&amp;nbsp;Socket plugins can&amp;nbsp;be developed to easily power other functionality like real-time whiteboards, analytics, or even games.&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l501"&gt;&lt;a id="Overview" name="Overview"&gt;&lt;/a&gt;Overview&lt;/h2&gt;
&lt;p&gt;Built on top of &lt;a href="http://signalr.net/"&gt;SignalR&lt;/a&gt;, the Socket Framework inherits all of SignalR&amp;#39;s performance, stability, and diversity of browser support over underlying WebSocket, server-sent event, or&amp;nbsp;long polling transports. Because it is Verint&amp;nbsp;Community-specific, the Socket Framework can provide:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;[[Plugins|Plugin]] based extensibility&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Both built-in and third-party [[Plugins|plugin]] can implement their own &lt;em&gt;sockets&lt;/em&gt; which each define a pair of server and client methods and events for bi-directional communication, all multiplexed over a single&amp;nbsp;underlying connection to the server.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Presence&lt;/strong&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Users&amp;#39; site presence as well as their presence to individual pieces of content regardless of how and where that content is viewed&amp;nbsp;is&amp;nbsp;tracked&amp;nbsp;to enable&amp;nbsp;delivery of messages scoped only to&amp;nbsp;users viewing&amp;nbsp;specific&amp;nbsp;content. Additionally, Service Presence supports a similar, but non-content-based scoping of messages.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scale-out and reliability&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;All sockets are multiplexed across&amp;nbsp;a single connection between&amp;nbsp;the server and browser. Additionally,&amp;nbsp;the browser shares the same, single, connection across all of its windows and&amp;nbsp;tabs, transparently identifying a single window or tab at a time to serve&amp;nbsp;as the connection&amp;#39;s host.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Socket connections are reliably maintained and reconnect after any disconnections with randomized, exponential, retry backoffs.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;To support scale-out to multiple application instances and&amp;nbsp;delivery&amp;nbsp;of socket messages from plugins&amp;nbsp;running outside of web contexts in the job server, Verint&amp;nbsp;Community automatically distributes message sending&amp;nbsp;across a bus.&amp;nbsp;Community&amp;nbsp;bundles two&amp;nbsp;possible message bus servers: the Socket Message Bus Service as well as the lower-performing Database Message Bus. Alternatively, Verint&amp;nbsp;Community can use &lt;em&gt;any&lt;/em&gt; message bus service through plugin extensibility. The configuration of which message bus server to use, if any at all, is defined by [[Plugins|plugin]]-based connectors, which can be enabled or disabled through standard plugin management without restarting the application. Socket plugins also expose the underlying bus for use as a way to keep real-time application state in synchronization across multiple instances as needed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="mcetoc_1dio78l502"&gt;&lt;a id="API" name="API"&gt;&lt;/a&gt;API&lt;/h2&gt;
&lt;p&gt;The server-side API exists as a set of interfaces implementable by [[Plugins|plugins]].&lt;/p&gt;
&lt;p&gt;&lt;img alt=" " src="/resized-image/__size/640x480/__key/communityserver-wikis-components-files/00-00-00-12-83/sockets.png" /&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l503"&gt;&lt;a id="ISocket_Plugin" name="ISocket_Plugin"&gt;&lt;/a&gt;&lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket Plugin&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A socket is defined by a [[Plugins|plugin]] which implements the &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; interface. A single socket plugin represents a single channel of communication between the server and browser. For example, a socket plugin may represent all functionality related to sending and receiving realtime chat messages. A single socket plugin can send and receive arbitrary messages and optional data with those messages, but can only send or receive messages sent by or to the same socket plugin.&lt;/p&gt;
&lt;p&gt;Socket plugins are injected with instances of &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt; exposes an instance of an &lt;a href="/developers/w/developer90/50149.iclientscontroller-plugin-supplementary-type"&gt;IClientsController&lt;/a&gt; which contains events for when a user connects, disconnects, or sends a message from the browser. The &lt;a href="/developers/w/developer90/50149.iclientscontroller-plugin-supplementary-type"&gt;IClientsController&lt;/a&gt; also supports sending messages to a user, to all users present to specific&amp;nbsp;content or services, or broadcasting to all users.&lt;/p&gt;
&lt;p&gt;Each enabled socket plugin yields a corresponding client-side API.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l504"&gt;&lt;a id="ISocketMessageBus_Plugin" name="ISocketMessageBus_Plugin"&gt;&lt;/a&gt;&lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus Plugin&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Multiple-application instance scale-out and message delivery from non-web contexts like job server plugins is automatically&amp;nbsp;supported&amp;nbsp;by&amp;nbsp;the&amp;nbsp;enablement of plugins which implement the &lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus&lt;/a&gt; interface. Verint&amp;nbsp;Community bundles two default implementations to connect to either the Socket Message Bus Service or the Database Message Bus, but also supports integrating with other message busses as well. For details, see the discussion on Scale-Out.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l505"&gt;&lt;a id="Client-Side" name="Client-Side"&gt;&lt;/a&gt;Client-Side&lt;/h3&gt;
&lt;h4&gt;&lt;a id="Socket_Endpoints" name="Socket_Endpoints"&gt;&lt;/a&gt;Socket Endpoints&lt;/h4&gt;
&lt;p&gt;Each &lt;code&gt;ISocket&lt;/code&gt; plugin implements a &lt;code&gt;SocketName&lt;/code&gt;. This one-word string becomes the name of the client-side API. For example, given the socket:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public class MySocket : ISocket
{
    // ...

    string SocketName =&amp;gt; &amp;quot;mySocket&amp;quot;;

    // ...
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Then the following JavaScript API will be automatically exposed:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="javascript"&gt;// receive and handle a message with optional data from the server
jQuery.telligent.evolution.sockets.mySocket.on(messageName, function(data) {
   // handle
});

// send data to the server an optional object message
jQuery.telligent.evolution.sockets.mySocket.send(messageName, data);&lt;/pre&gt;&lt;/p&gt;
&lt;h4&gt;&lt;a id="Initiation" name="Initiation"&gt;&lt;/a&gt;Initiation&lt;/h4&gt;
&lt;p&gt;Before attempting to send or receive messages from the client side, the Socket Framework must initiate itself. This happens automatically, and when complete, it publishes a &lt;a href="/developers/w/developer90/50006.socket-connected-client-message"&gt;socket.connected&lt;/a&gt; &lt;a href="/developers/w/developer90/50024.messaging-javascript-api-module"&gt;client-side message&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="javascript"&gt;jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
    // set up message listeners or send messages
});&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l506"&gt;&lt;a id="Example_Socket" name="Example_Socket"&gt;&lt;/a&gt;Simple Example Socket&lt;/h2&gt;
&lt;p&gt;The following shows a basic example of a socket which routes greetings from one user to another. A user provides the user name of another community member, clicks &amp;#39;greet&amp;#39;, and an alert is displayed to the other user.&lt;/p&gt;
&lt;p&gt;Greetings are initiated from a user via a widget, sent via the client-side socket API to the &lt;code&gt;ISocket&lt;/code&gt; plugin, and then delivered to the recipient user where the same widget instance for the other user will display the message in a JavaScript &lt;code&gt;alert()&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l507"&gt;&lt;a id="Server_Side" name="Server_Side"&gt;&lt;/a&gt;Server Side&lt;/h3&gt;
&lt;p&gt;Create a new [[Plugins|plugin]] which implements the &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; interface. Its &lt;code&gt;Name&lt;/code&gt;, &lt;code&gt;Description&lt;/code&gt;, and &lt;code&gt;Initialize()&lt;/code&gt; are unimportant. For &lt;code&gt;SocketName&lt;/code&gt; and &lt;code&gt;SetController()&lt;/code&gt;, use the following:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public string SocketName =&amp;gt; &amp;quot;greeter&amp;quot;;

public void SetController(ISocketController controller)
{
    controller.Clients.Received += (sender, e) =&amp;gt;
    {
        // if this was a greting message, let&amp;#39;s process it
        if (e.MessageName == &amp;quot;greet&amp;quot;)
        {
            // get the associated recipient user
            // data passed from the client side is available on the dynamic MessageData object
            var to = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;Telligent.Evolution.Extensibility.Api.Version1.IUsers&amp;gt;().Users.Get(new Telligent.Evolution.Extensibility.Api.Version1.UsersGetOptions { Username = (string)e.MessageData.Recipient });

            // get the sender user
            var from = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;Telligent.Evolution.Extensibility.Api.Version1.IUsers&amp;gt;().Get(new Telligent.Evolution.Extensibility.Api.Version1.UsersGetOptions { Id = e.UserId });

            // send a new message to the recipient
            controller.Clients.Send(to.Id.GetValueOrDefault(), &amp;quot;greet&amp;quot;, new
            {
                Message = String.Format(&amp;quot;Hello {0}, from {1}&amp;quot;, to.DisplayName, from.DisplayName)
            });
        }
    };
}&lt;/pre&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l508"&gt;&lt;a id="Client_Side" name="Client_Side"&gt;&lt;/a&gt;Client Side&lt;/h3&gt;
&lt;p&gt;In Widget Studio, create a new widget&amp;nbsp;with content:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="velocity"&gt;## set up some unique ids for interface elements
#set($recipientInputId = $core_v2_widget.UniqueId(&amp;#39;recipient&amp;#39;))
#set($sendLinkId = $core_v2_widget.UniqueId(&amp;#39;greet&amp;#39;))

## basic interface
&amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;$recipientInputId&amp;quot; /&amp;gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;$sendLinkId&amp;quot;&amp;gt;Greet&amp;lt;/a&amp;gt;

&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
// Wait for socket to be connected
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {

    // when &amp;#39;Greet&amp;#39; is clicked, send a message to be delivered to the recipient
    jQuery(&amp;#39;#$sendLinkId&amp;#39;).on(&amp;#39;click&amp;#39;, function(e) {
        e.preventDefault();

        jQuery.telligent.evolution.sockets.greeter.send(&amp;#39;greet&amp;#39;, {
            Recipient: jQuery(&amp;#39;#$recipientInputId&amp;#39;).val()
        });
    });

    // when a &amp;#39;greet&amp;#39; message is received from the socket, display it as an alert
    jQuery.telligent.evolution.sockets.greeter.on(&amp;#39;greet&amp;#39;, function(data){
        alert(data.Message);
    });
});
&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Note use of the &lt;a href="/developers/w/developer90/50006.socket-connected-client-message"&gt;socket.connected&lt;/a&gt; &lt;a href="/developers/w/developer90/50024.messaging-javascript-api-module"&gt;client-side message&lt;/a&gt; as well as the automatically-generated &lt;code&gt;jQuery.telligent.evolution.sockets.testSocket&lt;/code&gt; API.&lt;/p&gt;
&lt;p&gt;The result is a simple UI that enables sending a greeting to another user by their user name.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter.png"&gt;&lt;img style="border:1px solid #DDD;width:264px;" alt=" " src="/resized-image/__size/640x480/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter_2D00_greeted.png"&gt;&lt;img style="border:1px solid #DDD;width:485px;" alt=" " src="/resized-image/__size/640x480/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter_2D00_greeted.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l509"&gt;&lt;a id="Download" name="Download"&gt;&lt;/a&gt;Download&lt;/h3&gt;
&lt;p&gt;The complete sample can be downloaded:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/SocketSample_2E00_cs"&gt;community.telligent.com/.../SocketSample_2E00_cs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/5314.GreeterUI_2D00_Widget.xml"&gt;community.telligent.com/.../5314.GreeterUI_2D00_Widget.xml&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l50f"&gt;&lt;a id="Presence_Services" name="Presence_Services"&gt;&lt;/a&gt;Presence Services&lt;/h2&gt;
&lt;p&gt;Being able to send messages directly to individual users is a great start. However, there is often a need to send messages to specific groups of users, i.e. messages about new replies to all users viewing a given forum thread so that it may&amp;nbsp;update its UI&amp;nbsp;in realtime. To that end, presence services enable sending messages to users scoped by their &lt;em&gt;presence&lt;/em&gt; to pieces of [content|The Content Model] or abstract &lt;em&gt;service&lt;/em&gt;&amp;nbsp;groupings.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50h"&gt;&lt;a id="Content_Presence" name="Content_Presence"&gt;&lt;/a&gt;Content Presence&lt;/h3&gt;
&lt;p&gt;The Content Presence service tracks which &lt;span&gt;[content|&lt;/span&gt;&lt;span&gt;The Content Model]&lt;/span&gt; users are currently viewing. This enables the platform to deliver updates to&amp;nbsp;users in real time regarding&amp;nbsp;changes to content they are currently viewing. &lt;strong&gt;Importantly&lt;/strong&gt;, this can mean in whatever or wherever way that the content is presented. For example, a user viewing a forum thread&amp;#39;s question&amp;nbsp;in a group&amp;#39;s&amp;nbsp;activity stream is considered and tracked&amp;nbsp;as present to that forum&amp;nbsp;thread&amp;nbsp;the same&amp;nbsp;as a user on the forum thread&amp;#39;s own page. Also importantly, content presence even takes into account whether the content&amp;#39;s UI is scrolled into view. For example, a user is&amp;nbsp;&lt;em&gt;not&lt;/em&gt; be present to another forum thread whose activity story is&amp;nbsp;scrolled out of browser view in the activity stream.&lt;/p&gt;
&lt;h4&gt;&lt;/h4&gt;
&lt;h4&gt;&lt;a id="Content_Presence_Mappings" name="Content_Presence_Mappings"&gt;&lt;/a&gt;Content Presence&amp;nbsp;Mappings&lt;/h4&gt;
&lt;p&gt;To understand content presence APIs, it is important to first understand &lt;em&gt;the ways in which&amp;nbsp;content presence mappings are created and removed:&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Page Context&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;The service uses [URL context|Page Definition and URL Routing] to track what content the using is currently viewing. As long as a user is on a URL with content context, the user is present to those content records. For example,&amp;nbsp;if a user is viewing a blog post, the content service would be aware that the user is present to&amp;nbsp;that blog post, the blog, and even the post&amp;#39;s author&amp;#39;s content records. So, sending a socket message to any of those three content IDs would deliver it to the viewing user.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HTML presence&amp;nbsp;attributes&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;In addition to overall page context, specific portions of a page&amp;#39;s UI can identify themselves as representing specific content, so that while a user is viewing that UI, the user also is also mapped as present to the&amp;nbsp;content. These identifications are represented as attributes added to the HTML&amp;nbsp;element.&amp;nbsp;The activity stream uses such HTML presence attributes to wrap stories in the stream so that the user is present to stories&amp;#39; corresponding content, and only when those stories are scrolled into view.&lt;/li&gt;
&lt;li&gt;HTML presence&amp;nbsp;attributes can be added to through the &lt;code&gt;core_v2_contentPresence.RenderAttributes&lt;/code&gt; method. &amp;nbsp;This method will render the proper attributes to automatically track a user&amp;#39;s content presence, when the decorated element is currently visible on the page they are viewing. &amp;nbsp;The comment stream and activity stream are two examples where this method is in use.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;APIs&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&amp;nbsp;In-Process, Rest and Script&amp;nbsp;APIs are available to directly add and remove&amp;nbsp;presence mappings, though these are rarely needed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Content presence mappings are&amp;nbsp;&lt;em&gt;automatically removed&lt;/em&gt;&amp;nbsp;when they expire. As long as a user is on a page, the page is pinging back to the server to identify that the user is online, and to identify the list of content records the user is present to, whether they were&amp;nbsp;identified by the overall page&amp;#39;s context, or the currently scrolled elements decorated with&amp;nbsp;HTML presence attributes. Presence mappings that have not been refreshed for across a few&amp;nbsp;of these pings are considered expired and unmapped, thereby removing the user from receipt of socket messages&amp;nbsp;sent to users present to the content. Since&amp;nbsp;all windows and tabs of a single browser share a single socket connection, the single connection sends a ping identifying present content records across &lt;em&gt;all&lt;/em&gt; open windows and tabs.&lt;/p&gt;
&lt;h4&gt;&lt;a id="Content_Presence_API" name="Content_Presence_API"&gt;&lt;/a&gt;Content Presence API&lt;/h4&gt;
&lt;p&gt;Content presence APIs enable sending messages, querying total presence counts, and registering specific presence mappings.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;To send messages&lt;/em&gt;, use &lt;a href="/community/11/w/api-documentation/64162/iclientscontroller-plugin-supplementary-type"&gt;IClientsController.SendToUsersPresentToContent(Guid contentId, string messageName)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To query&lt;em&gt;&amp;nbsp;metadata summaries&lt;/em&gt; about users present to a given piece of content via &lt;a href="/11/w/api-documentation/63974/contentpresence-in-process-api-service"&gt;&lt;code&gt;IContentPresence&lt;/code&gt;&lt;/a&gt; or&amp;nbsp;&lt;code&gt;&lt;a href="/community/11/w/api-documentation/65749/core_5f00_v2_5f00_contentpresence-script-api"&gt;core_v2_contentPresence.GetSummary()&lt;/a&gt;. &lt;/code&gt;This metadata&amp;nbsp;is just a count summary, and may&amp;nbsp;be delayed.&lt;/p&gt;
&lt;p&gt;To register specific HTML elements as representing content so that&amp;nbsp;the user is mapped to the content while viewing the element, use &lt;code&gt;&lt;a href="/community/11/w/api-documentation/65749/core_5f00_v2_5f00_contentpresence-script-api#RenderAttributes"&gt;core_v2_contentPresence.RenderAttributes()&lt;/a&gt;&lt;/code&gt;&lt;span&gt;.&amp;nbsp;This method will render the proper attributes&amp;nbsp;to include inline with any HTML element, such as a &amp;lt;div&amp;gt; wrapping an activity stream story, or a &amp;lt;span&amp;gt; surrounding a like button.&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50i"&gt;&lt;a id="Service_Presence" name="Service_Presence"&gt;&lt;/a&gt;Service Presence&lt;/h3&gt;
&lt;p&gt;Service Presence is nearly identical to&amp;nbsp;Content Presence in that it enables&amp;nbsp;mapping a user&amp;#39;s presence and&amp;nbsp;sending socket messages to users based on those mappings. However, while Content Presence is&amp;nbsp;designed specifically for Content IDs and Content Type IDs and automatically maps users to content by their page context, service presence allows mapping users to &lt;em&gt;any arbitrary Guid&lt;/em&gt;. As such, there are no automatically-created service presence mappings. Service presence mappings can only be registered by specific&amp;nbsp;&lt;em&gt;HTML presence attributes&lt;/em&gt; or the APIs (rarely&amp;nbsp;used). (Please see the above discussion on Content Presence Mappings for a discussion on how such attributes work.)&lt;/p&gt;
&lt;p&gt;In this way, a widget can define an HTML element to contain&amp;nbsp;a service presence mapping of any arbitrary ID.&amp;nbsp;Any user viewing that widget will be considered present to that ID &amp;quot;service&amp;quot;. And a socket plugin can then deliver a message to any user viewing&amp;nbsp;that widget by the same arbitrary service presence ID.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Similar to content presence, service presence mappings&amp;nbsp;automatically expire.&lt;/p&gt;
&lt;p&gt;While less frequently needed than content presence, service presence provides flexibility for edge cases.&lt;/p&gt;
&lt;h4&gt;&lt;a id="Service_Presence_API" name="Service_Presence_API"&gt;&lt;/a&gt;Service Presence API&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;To send messages&lt;/em&gt;, use &lt;a href="/community/11/w/api-documentation/64162/iclientscontroller-plugin-supplementary-type"&gt;IClientsController.SendToUsersPresentToContent(Guid contentId, string messageName)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To query&lt;em&gt;&amp;nbsp;metadata summaries&lt;/em&gt; about users present to an ID via &lt;a href="/community/11/w/api-documentation/64069/servicepresence-in-process-api-service"&gt;&lt;code&gt;IServicePresence&lt;/code&gt;&lt;/a&gt; or&amp;nbsp;&lt;code&gt;&lt;a href="/community/11/w/api-documentation/65767/core_5f00_v2_5f00_servicepresence-script-api#GetSummary"&gt;core_v2_servicePresence.GetSummary()&lt;/a&gt;. &lt;/code&gt;This metadata&amp;nbsp;is just a count summary, and may&amp;nbsp;be delayed.&lt;/p&gt;
&lt;p&gt;To register specific HTML elements as services mapping ID so that&amp;nbsp;the user is mapped to the ID&amp;nbsp;while viewing the element, use &lt;code&gt;&lt;a href="/community/11/w/api-documentation/65767/core_5f00_v2_5f00_servicepresence-script-api#RenderAttributes"&gt;core_v2_servicePresence.RenderAttributes()&lt;/a&gt;&lt;/code&gt;&lt;span&gt;.&amp;nbsp;This method will render the proper attributes&amp;nbsp;to include inline with any HTML element.&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50i"&gt;&lt;/h3&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50g"&gt;&lt;a id="User_Presence" name="User_Presence"&gt;&lt;/a&gt;User Presence&lt;/h3&gt;
&lt;p&gt;User Presence is built atop sockets and content presence. After all, user records are content records, too.&lt;/p&gt;
&lt;p&gt;User presence is a set of related&amp;nbsp;UIs, APIs which track and render a user&amp;#39;s overall presence to the site.&lt;/p&gt;
&lt;h4&gt;&lt;a id="UI" name="UI"&gt;&lt;/a&gt;UI&lt;/h4&gt;
&lt;p&gt;The service is responsible for the presence indicator often&amp;nbsp;displayed alongside the user&amp;nbsp;names.&lt;/p&gt;
&lt;p&gt;&lt;img alt=" " src="/resized-image/__size/320x240/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence.png" /&gt;&lt;/p&gt;
&lt;h4&gt;&lt;a id="API" name="API"&gt;&lt;/a&gt;API&lt;/h4&gt;
&lt;p&gt;Live-updating user presence indicators&amp;nbsp;can be easily&amp;nbsp;rendered with &lt;code&gt;&lt;a href="/community/11/w/api-documentation/65797/core_5f00_v2_5f00_ui-script-api#UserPresence"&gt;core_v2_ui.UserPresence()&lt;/a&gt;&lt;/code&gt;. These are an easy way to add benefits of realtime-updating presence to your UI to&amp;nbsp;improve engagement in your community.&lt;/p&gt;
&lt;p&gt;Of note, core_v2_ui.UserPresence is, itself, built on top of these&amp;nbsp;APIs. It renders a &lt;a href="/community/11/w/api-documentation/65143/ui-javascript-api-module"&gt;UI component&lt;/a&gt; which presents&amp;nbsp;an indicator dot wrapped with content presence HTML attributes&amp;nbsp;registering&amp;nbsp;the&amp;nbsp;accessing user as present to the&amp;nbsp;user being indicated so that socket messages sent on users&amp;#39; presence change events&amp;nbsp;can be delivered to anyone viewing the changed users&amp;#39; indicators.&lt;/p&gt;
&lt;p&gt;A user&amp;#39;s current presence is an attribute of the user&amp;#39;s entity, returned from REST, Script, or In-Process APIs. Like other user property changes, changes to their presence can be handled with events.&lt;/p&gt;
&lt;p&gt;Similar to content and service presence mappings, users&amp;#39; presences are automatically set to offline whenever the user closes all of their browser windows and tabs or after the last of their content presence mappings expire.&lt;/p&gt;
&lt;h4&gt;&lt;a id="Privacy" name="Privacy"&gt;&lt;/a&gt;Privacy&lt;/h4&gt;
&lt;p&gt;The platform has the options for&amp;nbsp;&lt;strong&gt;Enable Presence Tracking&lt;/strong&gt;,&amp;nbsp;&lt;strong&gt;Allow Members To Toggle Presence Tracking Enablement &lt;/strong&gt;and&lt;strong&gt; Default Presence Tracking Enablement Value &amp;nbsp;&lt;/strong&gt;available under Membership in the Membership Options panel in Administration. &amp;nbsp;&lt;strong&gt;Enable Presence Tracking&amp;nbsp;&lt;/strong&gt;controls whether user presence tracking is available for the community. &amp;nbsp;If tracking is enabled, &amp;nbsp;&lt;strong&gt;Allow Members To Toggle Presence Tracking Enablement&lt;/strong&gt; controls whether or not each user should have the option to disable tracking of their online status. If that option is enabled the&amp;nbsp;&lt;strong&gt;Default Presence Tracking Enablement Value&amp;nbsp;&lt;/strong&gt;is also available. &amp;nbsp;If users are giving the option to control their presence tracking, the&amp;nbsp;&lt;strong&gt;Enable presence tracking&lt;/strong&gt; option will be available in the membership settings.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence-admin.png"&gt;&lt;img alt=" " src="/resized-image/__size/550x539/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence-admin.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l50j"&gt;&lt;a id="Example_Socket_using_Content_Presence_Service" name="Example_Socket_using_Content_Presence_Service"&gt;&lt;/a&gt;Example Socket using Content Presence&lt;/h2&gt;
&lt;p&gt;This example will&amp;nbsp;create an &lt;code&gt;ISocket&lt;/code&gt; implementation that will send socket messages to users when a vote is received or changed on an idea. By combining the socket implementation with the content presence service, the socket messages can be sent only to those users who are currently viewing the idea that received the vote.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50k"&gt;&lt;a id="Server_Side" name="Server_Side"&gt;&lt;/a&gt;Server Side&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;ISocket&lt;/code&gt; implementation will use the &lt;em&gt;ideavotes&lt;/em&gt; for the &lt;code&gt;SocketName &lt;/code&gt;and maintain a reference to the &lt;code&gt;SocketController&lt;/code&gt; for later use in our example.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;ISocketController _sockets;
public string SocketName =&amp;gt; &amp;quot;ideavotes&amp;quot;;

public void SetController(ISocketController controller)
{
    _sockets = controller;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The example class will need to send a message whenever an idea is&amp;nbsp;voted on, this can be accomplished by attaching to the Idea Vote Events for these actions in our plugin&amp;#39;s &lt;code&gt;Initialize&lt;/code&gt; method. &amp;nbsp;In each event handler, we will call the same method SendVoteCounts passing the idea id for the vote.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public void Initialize()
{
    _ideas = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IIdeas&amp;gt;();

    _ideaVotes = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IVotes&amp;gt;();
    _ideaVotes.Events.AfterCreate += VoteCreated;
    _ideaVotes.Events.AfterDelete += VoteDeleted;
    _ideaVotes.Events.AfterUpdate += VoteUpdated;
}

private void VoteCreated(VoteAfterCreateEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}

private void VoteUpdated(VoteAfterUpdateEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}

private void VoteDeleted(VoteAfterDeleteEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;In the SendVoteCounts method, the number of up and down votes will be retrieved and the&amp;nbsp;&lt;code&gt;_sockets.Clients.SendToUsersPresentToContent &lt;/code&gt;method will be used to send a message to all users who are currently present to that idea.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;void SendVoteCounts(Guid ideaId)
{
    var idea = _ideas.Get(ideaId);
    if (idea != null &amp;amp;&amp;amp; !idea.HasErrors())
    {
        var upVotes =
            _ideaVotes.List(new VotesListOptions() {IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = true });

        var downVotes =
            _ideaVotes.List(new VotesListOptions() { IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = false });

        // send socket message with updated totals
        _sockets.Clients.SendToUsersPresentToContent(idea.ContentId, &amp;quot;ideavoted&amp;quot;, new
        {
            contentId = idea.ContentId,
            contentTypeId = _ideas.ContentTypeId,
            yesVotes = upVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;,
            noVotes = downVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;
        });
    }
}&lt;/pre&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50l"&gt;&lt;a id="Client_Side" name="Client_Side"&gt;&lt;/a&gt;Client Side&lt;/h3&gt;
&lt;p&gt;Once this plugin is compiled and enabled on the community site, each time an idea is voted on any user who is viewing that idea will receive an &lt;em&gt;ideavoted&amp;nbsp;&lt;/em&gt;socket message. &amp;nbsp;For this example, we can use a widget to see these messages. &amp;nbsp;The example will&amp;nbsp;make use of the&amp;nbsp;&lt;code&gt;$.telligent.evolution.sockets.ideavotes&lt;/code&gt; API that is automatically generated for our &lt;code&gt;ISocket&lt;/code&gt; implementation. &amp;nbsp;That API will enable the widget to listen for messages from the custom socket. &amp;nbsp;In this case, the message&amp;#39;s data will output to the browser&amp;#39;s console window.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="javascript"&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
	jQuery.telligent.evolution.sockets.ideavotes.on(&amp;#39;ideavoted&amp;#39;, function(data) {
		console.log(data);
	});
});
&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The widget can be placed on the Idea page or Idea List page,&amp;nbsp;you will be able to see the messages for the ideas you are currently viewing when any vote is received on the idea(s) you are currently viewing.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50m"&gt;&lt;a id="Completed_Sample" name="Completed_Sample"&gt;&lt;/a&gt;Completed Sample&lt;/h3&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;using System;
using Telligent.Evolution.Extensibility.Ideation.Api;
using Telligent.Evolution.Extensibility.Sockets.Version1;
using Telligent.Evolution.Extensibility.Version1;

namespace Telligent.Evolution.Examples
{
    public class VoteSocket : IPlugin, ISocket
    {
        ISocketController _sockets;
        IIdeas _ideas;
        IVotes _ideaVotes;

        public string Name =&amp;gt; &amp;quot;Idea Vote Sockets&amp;quot;;
        public string Description =&amp;gt; &amp;quot;Enables live updates to idea votes.&amp;quot;;
        public string SocketName =&amp;gt; &amp;quot;ideavotes&amp;quot;;

        public void Initialize()
        {
            _ideas = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IIdeas&amp;gt;();

            _ideaVotes = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IVotes&amp;gt;();
            _ideaVotes.Events.AfterCreate += VoteCreated;
            _ideaVotes.Events.AfterDelete += VoteDeleted;
            _ideaVotes.Events.AfterUpdate += VoteUpdated;
        }

        public void SetController(ISocketController controller)
        {
            _sockets = controller;
        }

        private void VoteCreated(VoteAfterCreateEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        private void VoteUpdated(VoteAfterUpdateEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        private void VoteDeleted(VoteAfterDeleteEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        void SendVoteCounts(Guid ideaId)
        {
            var idea = _ideas.Get(ideaId);
            if (idea != null &amp;amp;&amp;amp; !idea.HasErrors())
            {
                var upVotes =
                    _ideaVotes.List(new VotesListOptions() {IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = true });

                var downVotes =
                    _ideaVotes.List(new VotesListOptions() { IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = false });

                // send socket message with updated totals
                _sockets.Clients.SendToUsersPresentToContent(idea.ContentId, &amp;quot;ideavoted&amp;quot;, new
                {
                    contentId = idea.ContentId,
                    contentTypeId = _ideas.ContentTypeId,
                    yesVotes = upVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;,
                    noVotes = downVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;
                });
            }
        }
    }
}
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="xml"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;
&amp;lt;scriptedContentFragments&amp;gt;
  &amp;lt;scriptedContentFragment name=&amp;quot;Idea Socket Presence Test&amp;quot; version=&amp;quot;10.0.0.0&amp;quot; description=&amp;quot;&amp;quot; instanceIdentifier=&amp;quot;c7e0a2c7d2b44ab08f22d8938ef03a06&amp;quot; theme=&amp;quot;&amp;quot; isCacheable=&amp;quot;false&amp;quot; varyCacheByUser=&amp;quot;false&amp;quot; showHeaderByDefault=&amp;quot;false&amp;quot; cssClass=&amp;quot;&amp;quot; provider=&amp;quot;7bb87a0cc5864a9392ae5b9e5f9747b7&amp;quot;&amp;gt;
    &amp;lt;contentScript&amp;gt;&amp;lt;![CDATA[

&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
	jQuery.telligent.evolution.sockets.ideavotes.on(&amp;#39;ideavoted&amp;#39;, function(data) {
		console.log(data);
	});
});
&amp;lt;/script&amp;gt;

]]&amp;gt;&amp;lt;/contentScript&amp;gt;
  &amp;lt;/scriptedContentFragment&amp;gt;
&amp;lt;/scriptedContentFragments&amp;gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l50a"&gt;&lt;a id="Scale-out" name="Scale-out"&gt;&lt;/a&gt;Scale-out&lt;/h2&gt;
&lt;h3 id="mcetoc_1dio78l50b"&gt;&lt;a id="Overview" name="Overview"&gt;&lt;/a&gt;Overview&lt;/h3&gt;
&lt;p&gt;While multiple users connected to a single web node are easy enough to reason about, this becomes more complicated&amp;nbsp;when there are multiple app nodes and&amp;nbsp;a job server. Consider&amp;nbsp;the case of User A on Server X and User B on Server Y where User A intends to send a real-time chat socket message to User B. The socket message must not only be sent to a different user, it must be sent to that user from a different server entirely. Or consider the case of a plugin running in the context of a job on the job server instead of a web node which also intends to send a socket message to a user, such as a socket-based message&amp;nbsp;that some delayed process has completed. The job server is not connected directly to any users, and so needs to communicate with the web nodes in order to deliver socket messages.&lt;/p&gt;
&lt;p&gt;These scenarios are already&amp;nbsp;&lt;em&gt;automatically and transparently&lt;/em&gt; supported through the use of the message bus.&amp;nbsp;&lt;strong&gt;Verint Community requires the use of a&amp;nbsp;message bus&lt;/strong&gt;. Verint Community comes with&amp;nbsp;two possible message bus services built in, the Socket Message Bus Windows Service as well as the lower performance&amp;nbsp;Database Message Bus. At least one of these services or another conforming message bus is required to be enabled as part of the installation of Community.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50c"&gt;&lt;a id="Socket_Message_Bus_Server" name="Socket_Message_Bus_Server"&gt;&lt;/a&gt;Socket Message Bus Service&lt;/h3&gt;
&lt;p&gt;Verint&amp;nbsp;Community comes with the Socket Message Bus Windows Service and its corresponding &lt;code&gt;ISocketMessageBus&lt;/code&gt; plugin-based connector, &lt;em&gt;Socket Message Bus Service &lt;/em&gt;available in&lt;em&gt; Administration &amp;gt; Site &amp;gt; Message Buses&lt;/em&gt;. This is simply a Windows Service which echoes messages it receives to all connected Verint&amp;nbsp;Community instances.&lt;/p&gt;
&lt;p&gt;Community also includes an alternative Database Message Bus which&amp;nbsp;has lower performance, but requires no separate service installation.&amp;nbsp;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50d"&gt;&lt;a id="Custom_Message_Bus" name="Custom_Message_Bus"&gt;&lt;/a&gt;Custom Message Bus&lt;/h3&gt;
&lt;p&gt;In cases where a community would prefer to use an existing third party message bus solution, custom &lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus plugins&lt;/a&gt; can be written against it and deployed. An example could be a message bus service which supports multiple Verint&amp;nbsp;Community communities on a single bus server by potentially adding an identifier to the string messages sent and received by the plugin for routing the message on the bus server.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50e"&gt;&lt;a id="Generic_Messages" name="Generic_Messages"&gt;&lt;/a&gt;Generic Messages&lt;/h3&gt;
&lt;p&gt;Custom logic in &lt;code&gt;ISocket&lt;/code&gt; plugins can also make use of the message bus directly. Generic messages can be useful for keeping small amounts&amp;nbsp;of state synchronized in realtime across application instances.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt; injected into &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; plugins contains an instance of an &lt;a href="/developers/w/developer90/50167.imessagebuscontroller-plugin-supplementary-type"&gt;IMessageBusController&lt;/a&gt;. The &lt;a href="/developers/w/developer90/50167.imessagebuscontroller-plugin-supplementary-type"&gt;IMessageBusController&lt;/a&gt; exposes events for when generic messages are received from instances of the application along with a method for sending them.&lt;/p&gt;
&lt;p&gt;A useful pattern for state change is to send a generic message to the bus, and only handle it once it is re-received. This allows all instances to know about the state. Additionally, the instance that sends it receives the message immediately without having to wait for the round-trip, and is made aware of the local origin of the message. In this manner, the sender can also be exclusively responsible for potentially persisting the state change elsewhere.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;controller.MessageBus.Publish(&amp;quot;something.happened&amp;quot;,&amp;quot;&amp;quot;);
controller.MessageBus.Received += (sender, e) =&amp;gt;
{
    if (e.MessageName == &amp;quot;something.happened&amp;quot;)
    {
        // update some local caches
        // ...
        if (e.Source == BusMessageSource.Local)
        {
            // update DB
            // ...
        }
    }
};&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l50n"&gt;&lt;a id="Tips_and_Tricks" name="Tips_and_Tricks"&gt;&lt;/a&gt;Additional Notes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Socket connections are only established for authenticated, non-system, users&lt;/li&gt;
&lt;li&gt;User disconnection events are raised whenever&amp;nbsp;a user&amp;#39;s last window&amp;nbsp;or tab for a&amp;nbsp;browser closes, as they all share a single connection. Disconnection events can also raise when plugins refresh.&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: socket, messaging, presence, bus&lt;/div&gt;
</description></item><item><title>Sockets and Presence</title><link>https://community.telligent.com/community/11/w/developer-training/65063/sockets-and-presence/revision/6</link><pubDate>Tue, 20 Aug 2019 21:55:04 GMT</pubDate><guid isPermaLink="false">f141b2d7-5f01-47b0-ab4d-105e12603c36</guid><dc:creator>Michael Monteleone</dc:creator><comments>https://community.telligent.com/community/11/w/developer-training/65063/sockets-and-presence#comments</comments><description>Revision 6 posted to Developer Training by Michael Monteleone on 08/20/2019 21:55:04&lt;br /&gt;
&lt;p&gt;The Socket Framework provides support for &lt;strong&gt;real-time two-way communication between Verint Community and the browser&lt;/strong&gt;. This enables&amp;nbsp;receiving and sending messages directly to specific users or scoped&amp;nbsp;groups of users.&lt;/p&gt;
&lt;p&gt;[toc]&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l500"&gt;&lt;a id="When_would_I_want_to_use_sockets" name="When_would_I_want_to_use_sockets"&gt;&lt;/a&gt;When would I want to use sockets or presence?&lt;/h2&gt;
&lt;p&gt;Sockets are useful when you need to push messages from the server to the browser. An easy example to consider is a notification popup that is pushed to a user in the event of an action occurring on the server. Sockets are the mechanism through which built-in platform features including notifications, chat, live activity streams, forum threads, comment threads,&amp;nbsp;theme previews, presence indicators, tracing, and more communicate with the browser.&amp;nbsp;Socket plugins can&amp;nbsp;be developed to easily power other functionality like real-time whiteboards, analytics, or even games.&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l501"&gt;&lt;a id="Overview" name="Overview"&gt;&lt;/a&gt;Overview&lt;/h2&gt;
&lt;p&gt;Built on top of &lt;a href="http://signalr.net/"&gt;SignalR&lt;/a&gt;, the Socket Framework inherits all of SignalR&amp;#39;s performance, stability, and diversity of browser support over underlying WebSocket, server-sent event, or&amp;nbsp;long polling transports. Because it is Verint&amp;nbsp;Community-specific, the Socket Framework can provide:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;[[Plugins|Plugin]] based extensibility&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Both built-in and third-party [[Plugins|plugin]] can implement their own &lt;em&gt;sockets&lt;/em&gt; which each define a pair of server and client methods and events for bi-directional communication, all multiplexed over a single&amp;nbsp;underlying connection to the server.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Presence&lt;/strong&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Users&amp;#39; site presence as well as their presence to individual pieces of content regardless of how and where that content is viewed&amp;nbsp;is&amp;nbsp;tracked&amp;nbsp;to enable&amp;nbsp;delivery of messages scoped only to&amp;nbsp;users viewing&amp;nbsp;specific&amp;nbsp;content. Additionally, Service Presence supports a similar, but non-content-based scoping of messages.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scale-out and reliability&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;All sockets are multiplexed across&amp;nbsp;a single connection between&amp;nbsp;the server and browser. Additionally,&amp;nbsp;the browser shares the same, single, connection across all of its windows and&amp;nbsp;tabs, transparently identifying a single window or tab at a time to serve&amp;nbsp;as the connection&amp;#39;s host.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Socket connections are reliably maintained and reconnect after any disconnections with randomized, exponential, retry backoffs.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;To support scale-out to multiple application instances and&amp;nbsp;delivery&amp;nbsp;of socket messages from plugins&amp;nbsp;running outside of web contexts in the job server, Verint&amp;nbsp;Community automatically distributes message sending&amp;nbsp;across a bus.&amp;nbsp;Community&amp;nbsp;bundles two&amp;nbsp;possible message bus servers: the Socket Message Bus Service as well as the lower-performing Database Message Bus. Alternatively, Verint&amp;nbsp;Community can use &lt;em&gt;any&lt;/em&gt; message bus service through plugin extensibility. The configuration of which message bus server to use, if any at all, is defined by [[Plugins|plugin]]-based connectors, which can be enabled or disabled through standard plugin management without restarting the application. Socket plugins also expose the underlying bus for use as a way to keep real-time application state in synchronization across multiple instances as needed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="mcetoc_1dio78l502"&gt;&lt;a id="API" name="API"&gt;&lt;/a&gt;API&lt;/h2&gt;
&lt;p&gt;The server-side API exists as a set of interfaces implementable by [[Plugins|plugins]].&lt;/p&gt;
&lt;p&gt;&lt;img alt=" " src="/resized-image/__size/640x480/__key/communityserver-wikis-components-files/00-00-00-12-83/sockets.png" /&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l503"&gt;&lt;a id="ISocket_Plugin" name="ISocket_Plugin"&gt;&lt;/a&gt;&lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket Plugin&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A socket is defined by a [[Plugins|plugin]] which implements the &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; interface. A single socket plugin represents a single channel of communication between the server and browser. For example, a socket plugin may represent all functionality related to sending and receiving realtime chat messages. A single socket plugin can send and receive arbitrary messages and optional data with those messages, but can only send or receive messages sent by or to the same socket plugin.&lt;/p&gt;
&lt;p&gt;Socket plugins are injected with instances of &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt; exposes an instance of an &lt;a href="/developers/w/developer90/50149.iclientscontroller-plugin-supplementary-type"&gt;IClientsController&lt;/a&gt; which contains events for when a user connects, disconnects, or sends a message from the browser. The &lt;a href="/developers/w/developer90/50149.iclientscontroller-plugin-supplementary-type"&gt;IClientsController&lt;/a&gt; also supports sending messages to a user, to all users present to specific&amp;nbsp;content or services, or broadcasting to all users.&lt;/p&gt;
&lt;p&gt;Each enabled socket plugin yields a corresponding client-side API.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l504"&gt;&lt;a id="ISocketMessageBus_Plugin" name="ISocketMessageBus_Plugin"&gt;&lt;/a&gt;&lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus Plugin&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Multiple-application instance scale-out and message delivery from non-web contexts like job server plugins is automatically&amp;nbsp;supported&amp;nbsp;by&amp;nbsp;the&amp;nbsp;enablement of plugins which implement the &lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus&lt;/a&gt; interface. Verint&amp;nbsp;Community bundles two default implementations to connect to either the Socket Message Bus Service or the Database Message Bus, but also supports integrating with other message busses as well. For details, see the discussion on Scale-Out.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l505"&gt;&lt;a id="Client-Side" name="Client-Side"&gt;&lt;/a&gt;Client-Side&lt;/h3&gt;
&lt;h4&gt;&lt;a id="Socket_Endpoints" name="Socket_Endpoints"&gt;&lt;/a&gt;Socket Endpoints&lt;/h4&gt;
&lt;p&gt;Each &lt;code&gt;ISocket&lt;/code&gt; plugin implements a &lt;code&gt;SocketName&lt;/code&gt;. This one-word string becomes the name of the client-side API. For example, given the socket:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public class MySocket : ISocket
{
    // ...

    string SocketName =&amp;gt; &amp;quot;mySocket&amp;quot;;

    // ...
}&lt;/pre&gt;&lt;/p&gt;
&lt;pre class="brush: csharp"&gt;&lt;/pre&gt;
&lt;p&gt;Then the following JavaScript API will be automatically exposed:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="javascript"&gt;// receive and handle a message with optional data from the server
jQuery.telligent.evolution.sockets.mySocket.on(messageName, function(data) {
   // handle
});

// send data to the server an optional object message
jQuery.telligent.evolution.sockets.mySocket.send(messageName, data);&lt;/pre&gt;&lt;/p&gt;
&lt;h4&gt;&lt;a id="Initiation" name="Initiation"&gt;&lt;/a&gt;Initiation&lt;/h4&gt;
&lt;p&gt;Before attempting to send or receive messages from the client side, the Socket Framework must initiate itself. This happens automatically, and when complete, it publishes a &lt;a href="/developers/w/developer90/50006.socket-connected-client-message"&gt;socket.connected&lt;/a&gt; &lt;a href="/developers/w/developer90/50024.messaging-javascript-api-module"&gt;client-side message&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="javascript"&gt;jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
    // set up message listeners or send messages
});&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l506"&gt;&lt;a id="Example_Socket" name="Example_Socket"&gt;&lt;/a&gt;Simple Example Socket&lt;/h2&gt;
&lt;p&gt;The following shows a basic example of a socket which routes greetings from one user to another. A user provides the user name of another community member, clicks &amp;#39;greet&amp;#39;, and an alert is displayed to the other user.&lt;/p&gt;
&lt;p&gt;Greetings are initiated from a user via a widget, sent via the client-side socket API to the &lt;code&gt;ISocket&lt;/code&gt; plugin, and then delivered to the recipient user where the same widget instance for the other user will display the message in a JavaScript &lt;code&gt;alert()&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l507"&gt;&lt;a id="Server_Side" name="Server_Side"&gt;&lt;/a&gt;Server Side&lt;/h3&gt;
&lt;p&gt;Create a new [[Plugins|plugin]] which implements the &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; interface. Its &lt;code&gt;Name&lt;/code&gt;, &lt;code&gt;Description&lt;/code&gt;, and &lt;code&gt;Initialize()&lt;/code&gt; are unimportant. For &lt;code&gt;SocketName&lt;/code&gt; and &lt;code&gt;SetController()&lt;/code&gt;, use the following:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public string SocketName =&amp;gt; &amp;quot;greeter&amp;quot;;

public void SetController(ISocketController controller)
{
    controller.Clients.Received += (sender, e) =&amp;gt;
    {
        // if this was a greting message, let&amp;#39;s process it
        if (e.MessageName == &amp;quot;greet&amp;quot;)
        {
            // get the associated recipient user
            // data passed from the client side is available on the dynamic MessageData object
            var to = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;Telligent.Evolution.Extensibility.Api.Version1.IUsers&amp;gt;().Users.Get(new Telligent.Evolution.Extensibility.Api.Version1.UsersGetOptions { Username = (string)e.MessageData.Recipient });

            // get the sender user
            var from = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;Telligent.Evolution.Extensibility.Api.Version1.IUsers&amp;gt;().Get(new Telligent.Evolution.Extensibility.Api.Version1.UsersGetOptions { Id = e.UserId });

            // send a new message to the recipient
            controller.Clients.Send(to.Id.GetValueOrDefault(), &amp;quot;greet&amp;quot;, new
            {
                Message = String.Format(&amp;quot;Hello {0}, from {1}&amp;quot;, to.DisplayName, from.DisplayName)
            });
        }
    };
}&lt;/pre&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l508"&gt;&lt;a id="Client_Side" name="Client_Side"&gt;&lt;/a&gt;Client Side&lt;/h3&gt;
&lt;p&gt;In Widget Studio, create a new widget&amp;nbsp;with content:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="velocity"&gt;## set up some unique ids for interface elements
#set($recipientInputId = $core_v2_widget.UniqueId(&amp;#39;recipient&amp;#39;))
#set($sendLinkId = $core_v2_widget.UniqueId(&amp;#39;greet&amp;#39;))

## basic interface
&amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;$recipientInputId&amp;quot; /&amp;gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;$sendLinkId&amp;quot;&amp;gt;Greet&amp;lt;/a&amp;gt;

&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
// Wait for socket to be connected
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {

    // when &amp;#39;Greet&amp;#39; is clicked, send a message to be delivered to the recipient
    jQuery(&amp;#39;#$sendLinkId&amp;#39;).on(&amp;#39;click&amp;#39;, function(e) {
        e.preventDefault();

        jQuery.telligent.evolution.sockets.greeter.send(&amp;#39;greet&amp;#39;, {
            Recipient: jQuery(&amp;#39;#$recipientInputId&amp;#39;).val()
        });
    });

    // when a &amp;#39;greet&amp;#39; message is received from the socket, display it as an alert
    jQuery.telligent.evolution.sockets.greeter.on(&amp;#39;greet&amp;#39;, function(data){
        alert(data.Message);
    });
});
&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Note use of the &lt;a href="/developers/w/developer90/50006.socket-connected-client-message"&gt;socket.connected&lt;/a&gt; &lt;a href="/developers/w/developer90/50024.messaging-javascript-api-module"&gt;client-side message&lt;/a&gt; as well as the automatically-generated &lt;code&gt;jQuery.telligent.evolution.sockets.testSocket&lt;/code&gt; API.&lt;/p&gt;
&lt;p&gt;The result is a simple UI that enables sending a greeting to another user by their user name.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter.png"&gt;&lt;img style="border:1px solid #DDD;width:264px;" alt=" " src="/resized-image/__size/640x480/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter_2D00_greeted.png"&gt;&lt;img style="border:1px solid #DDD;width:485px;" alt=" " src="/resized-image/__size/640x480/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter_2D00_greeted.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l509"&gt;&lt;a id="Download" name="Download"&gt;&lt;/a&gt;Download&lt;/h3&gt;
&lt;p&gt;The complete sample can be downloaded:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/1680_2E00_SocketSample_2E00_cs"&gt;community.telligent.com/.../1680_2E00_SocketSample_2E00_cs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/5314.GreeterUI_2D00_Widget.xml"&gt;community.telligent.com/.../5314.GreeterUI_2D00_Widget.xml&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l50f"&gt;&lt;a id="Presence_Services" name="Presence_Services"&gt;&lt;/a&gt;Presence Services&lt;/h2&gt;
&lt;p&gt;Being able to send messages directly to individual users is a great start. However, there is often a need to send messages to specific groups of users, i.e. messages about new replies to all users viewing a given forum thread so that it may&amp;nbsp;update its UI&amp;nbsp;in realtime. To that end, presence services enable sending messages to users scoped by their &lt;em&gt;presence&lt;/em&gt; to pieces of [The Content Model|content] or abstract &lt;em&gt;service&lt;/em&gt;&amp;nbsp;groupings.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50h"&gt;&lt;a id="Content_Presence" name="Content_Presence"&gt;&lt;/a&gt;Content Presence&lt;/h3&gt;
&lt;p&gt;The Content Presence service tracks which &lt;span&gt;[&lt;/span&gt;&lt;span&gt;The Content Model|content]&lt;/span&gt; users are currently viewing. This enables the platform to deliver updates to&amp;nbsp;users in real time regarding&amp;nbsp;changes to content they are currently viewing. &lt;strong&gt;Importantly&lt;/strong&gt;, this can mean in whatever or wherever way that the content is presented. For example, a user viewing a forum thread&amp;#39;s question&amp;nbsp;in a group&amp;#39;s&amp;nbsp;activity stream is considered and tracked&amp;nbsp;as present to that forum&amp;nbsp;thread&amp;nbsp;the same&amp;nbsp;as a user on the forum thread&amp;#39;s own page. Also importantly, content presence even takes into account whether the content&amp;#39;s UI is scrolled into view. For example, a user is&amp;nbsp;&lt;em&gt;not&lt;/em&gt; be present to another forum thread whose activity story is&amp;nbsp;scrolled out of browser view in the activity stream.&lt;/p&gt;
&lt;h4&gt;&lt;/h4&gt;
&lt;h4&gt;&lt;a id="Content_Presence_Mappings" name="Content_Presence_Mappings"&gt;&lt;/a&gt;Content Presence&amp;nbsp;Mappings&lt;/h4&gt;
&lt;p&gt;To understand content presence APIs, it is important to first understand &lt;em&gt;the ways in which&amp;nbsp;content presence mappings are created and removed:&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Page Context&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;The service uses [Page Definition and URL Routing|URL context] to track what content the using is currently viewing. As long as a user is on a URL with content context, the user is present to those content records. For example,&amp;nbsp;if a user is viewing a blog post, the content service would be aware that the user is present to&amp;nbsp;that blog post, the blog, and even the post&amp;#39;s author&amp;#39;s content records. So, sending a socket message to any of those three content IDs would deliver it to the viewing user.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HTML presence&amp;nbsp;attributes&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;In addition to overall page context, specific portions of a page&amp;#39;s UI can identify themselves as representing specific content, so that while a user is viewing that UI, the user also is also mapped as present to the&amp;nbsp;content. These identifications are represented as attributes added to the HTML&amp;nbsp;element.&amp;nbsp;The activity stream uses such HTML presence attributes to wrap stories in the stream so that the user is present to stories&amp;#39; corresponding content, and only when those stories are scrolled into view.&lt;/li&gt;
&lt;li&gt;HTML presence&amp;nbsp;attributes can be added to through the &lt;code&gt;core_v2_contentPresence.RenderAttributes&lt;/code&gt; method. &amp;nbsp;This method will render the proper attributes to automatically track a user&amp;#39;s content presence, when the decorated element is currently visible on the page they are viewing. &amp;nbsp;The comment stream and activity stream are two examples where this method is in use.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;APIs&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&amp;nbsp;In-Process, Rest and Script&amp;nbsp;APIs are available to directly add and remove&amp;nbsp;presence mappings, though these are rarely needed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Content presence mappings are&amp;nbsp;&lt;em&gt;automatically removed&lt;/em&gt;&amp;nbsp;when they expire. As long as a user is on a page, the page is pinging back to the server to identify that the user is online, and to identify the list of content records the user is present to, whether they were&amp;nbsp;identified by the overall page&amp;#39;s context, or the currently scrolled elements decorated with&amp;nbsp;HTML presence attributes. Presence mappings that have not been refreshed for across a few&amp;nbsp;of these pings are considered expired and unmapped, thereby removing the user from receipt of socket messages&amp;nbsp;sent to users present to the content. Since&amp;nbsp;all windows and tabs of a single browser share a single socket connection, the single connection sends a ping identifying present content records across &lt;em&gt;all&lt;/em&gt; open windows and tabs.&lt;/p&gt;
&lt;h4&gt;&lt;a id="Content_Presence_API" name="Content_Presence_API"&gt;&lt;/a&gt;Content Presence API&lt;/h4&gt;
&lt;p&gt;Content presence APIs enable sending messages, querying total presence counts, and registering specific presence mappings.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;To send messages&lt;/em&gt;, use &lt;a href="/community/11/w/api-documentation/64162/iclientscontroller-plugin-supplementary-type"&gt;IClientsController.SendToUsersPresentToContent(Guid contentId, string messageName)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To query&lt;em&gt;&amp;nbsp;metadata summaries&lt;/em&gt; about users present to a given piece of content via &lt;a href="/11/w/api-documentation/63974/contentpresence-in-process-api-service"&gt;&lt;code&gt;IContentPresence&lt;/code&gt;&lt;/a&gt; or&amp;nbsp;&lt;code&gt;&lt;a href="/community/11/w/api-documentation/65749/core_5f00_v2_5f00_contentpresence-script-api"&gt;core_v2_contentPresence.GetSummary()&lt;/a&gt;. &lt;/code&gt;This metadata&amp;nbsp;is just a count summary, and may&amp;nbsp;be delayed.&lt;/p&gt;
&lt;p&gt;To register specific HTML elements as representing content so that&amp;nbsp;the user is mapped to the content while viewing the element, use &lt;code&gt;&lt;a href="/community/11/w/api-documentation/65749/core_5f00_v2_5f00_contentpresence-script-api#RenderAttributes"&gt;core_v2_contentPresence.RenderAttributes()&lt;/a&gt;&lt;/code&gt;&lt;span&gt;.&amp;nbsp;This method will render the proper attributes&amp;nbsp;to include inline with any HTML element, such as a &amp;lt;div&amp;gt; wrapping an activity stream story, or a &amp;lt;span&amp;gt; surrounding a like button.&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50i"&gt;&lt;a id="Service_Presence" name="Service_Presence"&gt;&lt;/a&gt;Service Presence&lt;/h3&gt;
&lt;p&gt;Service Presence is nearly identical to&amp;nbsp;Content Presence in that it enables&amp;nbsp;mapping a user&amp;#39;s presence and&amp;nbsp;sending socket messages to users based on those mappings. However, while Content Presence is&amp;nbsp;designed specifically for Content IDs and Content Type IDs and automatically maps users to content by their page context, service presence allows mapping users to &lt;em&gt;any arbitrary Guid&lt;/em&gt;. As such, there are no automatically-created service presence mappings. Service presence mappings can only be registered by specific&amp;nbsp;&lt;em&gt;HTML presence attributes&lt;/em&gt; or the APIs (rarely&amp;nbsp;used). (Please see the above discussion on Content Presence Mappings for a discussion on how such attributes work.)&lt;/p&gt;
&lt;p&gt;In this way, a widget can define an HTML element to contain&amp;nbsp;a service presence mapping of any arbitrary ID.&amp;nbsp;Any user viewing that widget will be considered present to that ID &amp;quot;service&amp;quot;. And a socket plugin can then deliver a message to any user viewing&amp;nbsp;that widget by the same arbitrary service presence ID.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Similar to content presence, service presence mappings&amp;nbsp;automatically expire.&lt;/p&gt;
&lt;p&gt;While less frequently needed than content presence, service presence provides flexibility for edge cases.&lt;/p&gt;
&lt;h4&gt;&lt;a id="Service_Presence_API" name="Service_Presence_API"&gt;&lt;/a&gt;Service Presence API&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;To send messages&lt;/em&gt;, use &lt;a href="/community/11/w/api-documentation/64162/iclientscontroller-plugin-supplementary-type"&gt;IClientsController.SendToUsersPresentToContent(Guid contentId, string messageName)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To query&lt;em&gt;&amp;nbsp;metadata summaries&lt;/em&gt; about users present to an ID via &lt;a href="/community/11/w/api-documentation/64069/servicepresence-in-process-api-service"&gt;&lt;code&gt;IServicePresence&lt;/code&gt;&lt;/a&gt; or&amp;nbsp;&lt;code&gt;&lt;a href="/community/11/w/api-documentation/65767/core_5f00_v2_5f00_servicepresence-script-api#GetSummary"&gt;core_v2_servicePresence.GetSummary()&lt;/a&gt;. &lt;/code&gt;This metadata&amp;nbsp;is just a count summary, and may&amp;nbsp;be delayed.&lt;/p&gt;
&lt;p&gt;To register specific HTML elements as services mapping ID so that&amp;nbsp;the user is mapped to the ID&amp;nbsp;while viewing the element, use &lt;code&gt;&lt;a href="/community/11/w/api-documentation/65767/core_5f00_v2_5f00_servicepresence-script-api#RenderAttributes"&gt;core_v2_servicePresence.RenderAttributes()&lt;/a&gt;&lt;/code&gt;&lt;span&gt;.&amp;nbsp;This method will render the proper attributes&amp;nbsp;to include inline with any HTML element.&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50i"&gt;&lt;/h3&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50g"&gt;&lt;a id="User_Presence" name="User_Presence"&gt;&lt;/a&gt;User Presence&lt;/h3&gt;
&lt;p&gt;User Presence is built atop sockets and content presence. After all, user records are content records, too.&lt;/p&gt;
&lt;p&gt;User presence is a set of related&amp;nbsp;UIs, APIs which track and render a user&amp;#39;s overall presence to the site.&lt;/p&gt;
&lt;h4&gt;&lt;a id="UI" name="UI"&gt;&lt;/a&gt;UI&lt;/h4&gt;
&lt;p&gt;The service is responsible for the presence indicator often&amp;nbsp;displayed alongside the user&amp;nbsp;names.&lt;/p&gt;
&lt;p&gt;&lt;img alt=" " src="/resized-image/__size/320x240/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence.png" /&gt;&lt;/p&gt;
&lt;h4&gt;&lt;a id="API" name="API"&gt;&lt;/a&gt;API&lt;/h4&gt;
&lt;p&gt;Live-updating user presence indicators&amp;nbsp;can be easily&amp;nbsp;rendered with &lt;code&gt;&lt;a href="/community/11/w/api-documentation/65797/core_5f00_v2_5f00_ui-script-api#UserPresence"&gt;core_v2_ui.UserPresence()&lt;/a&gt;&lt;/code&gt;. These are an easy way to add benefits of realtime-updating presence to your UI to&amp;nbsp;improve engagement in your community.&lt;/p&gt;
&lt;p&gt;Of note, core_v2_ui.UserPresence is, itself, built on top of these&amp;nbsp;APIs. It renders a &lt;a href="/community/11/w/api-documentation/65143/ui-javascript-api-module"&gt;UI component&lt;/a&gt; which presents&amp;nbsp;an indicator dot wrapped with content presence HTML attributes&amp;nbsp;registering&amp;nbsp;the&amp;nbsp;accessing user as present to the&amp;nbsp;user being indicated so that socket messages sent on users&amp;#39; presence change events&amp;nbsp;can be delivered to anyone viewing the changed users&amp;#39; indicators.&lt;/p&gt;
&lt;p&gt;A user&amp;#39;s current presence is an attribute of the user&amp;#39;s entity, returned from REST, Script, or In-Process APIs. Like other user property changes, changes to their presence can be handled with events.&lt;/p&gt;
&lt;p&gt;Similar to content and service presence mappings, users&amp;#39; presences are automatically set to offline whenever the user closes all of their browser windows and tabs or after the last of their content presence mappings expire.&lt;/p&gt;
&lt;h4&gt;&lt;a id="Privacy" name="Privacy"&gt;&lt;/a&gt;Privacy&lt;/h4&gt;
&lt;p&gt;The platform has the options for&amp;nbsp;&lt;strong&gt;Enable Presence Tracking&lt;/strong&gt;,&amp;nbsp;&lt;strong&gt;Allow Members To Toggle Presence Tracking Enablement &lt;/strong&gt;and&lt;strong&gt; Default Presence Tracking Enablement Value &amp;nbsp;&lt;/strong&gt;available under Membership in the Membership Options panel in Administration. &amp;nbsp;&lt;strong&gt;Enable Presence Tracking&amp;nbsp;&lt;/strong&gt;controls whether user presence tracking is available for the community. &amp;nbsp;If tracking is enabled, &amp;nbsp;&lt;strong&gt;Allow Members To Toggle Presence Tracking Enablement&lt;/strong&gt; controls whether or not each user should have the option to disable tracking of their online status. If that option is enabled the&amp;nbsp;&lt;strong&gt;Default Presence Tracking Enablement Value&amp;nbsp;&lt;/strong&gt;is also available. &amp;nbsp;If users are giving the option to control their presence tracking, the&amp;nbsp;&lt;strong&gt;Enable presence tracking&lt;/strong&gt; option will be available in the membership settings.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence-admin.png"&gt;&lt;img alt=" " src="/resized-image/__size/550x539/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence-admin.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l50j"&gt;&lt;a id="Example_Socket_using_Content_Presence_Service" name="Example_Socket_using_Content_Presence_Service"&gt;&lt;/a&gt;Example Socket using Content Presence&lt;/h2&gt;
&lt;p&gt;This example will&amp;nbsp;create an &lt;code&gt;ISocket&lt;/code&gt; implementation that will send socket messages to users when a vote is received or changed on an idea. By combining the socket implementation with the content presence service, the socket messages can be sent only to those users who are currently viewing the idea that received the vote.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50k"&gt;&lt;a id="Server_Side" name="Server_Side"&gt;&lt;/a&gt;Server Side&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;ISocket&lt;/code&gt; implementation will use the &lt;em&gt;ideavotes&lt;/em&gt; for the &lt;code&gt;SocketName &lt;/code&gt;and maintain a reference to the &lt;code&gt;SocketController&lt;/code&gt; for later use in our example.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;ISocketController _sockets;
public string SocketName =&amp;gt; &amp;quot;ideavotes&amp;quot;;

public void SetController(ISocketController controller)
{
    _sockets = controller;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The example class will need to send a message whenever an idea is&amp;nbsp;voted on, this can be accomplished by attaching to the Idea Vote Events for these actions in our plugin&amp;#39;s &lt;code&gt;Initialize&lt;/code&gt; method. &amp;nbsp;In each event handler, we will call the same method SendVoteCounts passing the idea id for the vote.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public void Initialize()
{
    _ideas = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IIdeas&amp;gt;();

    _ideaVotes = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IVotes&amp;gt;();
    _ideaVotes.Events.AfterCreate += VoteCreated;
    _ideaVotes.Events.AfterDelete += VoteDeleted;
    _ideaVotes.Events.AfterUpdate += VoteUpdated;
}

private void VoteCreated(VoteAfterCreateEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}

private void VoteUpdated(VoteAfterUpdateEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}

private void VoteDeleted(VoteAfterDeleteEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;In the SendVoteCounts method, the number of up and down votes will be retrieved and the&amp;nbsp;&lt;code&gt;_sockets.Clients.SendToUsersPresentToContent &lt;/code&gt;method will be used to send a message to all users who are currently present to that idea.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;void SendVoteCounts(Guid ideaId)
{
    var idea = _ideas.Get(ideaId);
    if (idea != null &amp;amp;&amp;amp; !idea.HasErrors())
    {
        var upVotes =
            _ideaVotes.List(new VotesListOptions() {IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = true });

        var downVotes =
            _ideaVotes.List(new VotesListOptions() { IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = false });

        // send socket message with updated totals
        _sockets.Clients.SendToUsersPresentToContent(idea.ContentId, &amp;quot;ideavoted&amp;quot;, new
        {
            contentId = idea.ContentId,
            contentTypeId = _ideas.ContentTypeId,
            yesVotes = upVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;,
            noVotes = downVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;
        });
    }
}&lt;/pre&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50l"&gt;&lt;a id="Client_Side" name="Client_Side"&gt;&lt;/a&gt;Client Side&lt;/h3&gt;
&lt;p&gt;Once this plugin is compiled and enabled on the community site, each time an idea is voted on any user who is viewing that idea will receive an &lt;em&gt;ideavoted&amp;nbsp;&lt;/em&gt;socket message. &amp;nbsp;For this example, we can use a widget to see these messages. &amp;nbsp;The example will&amp;nbsp;make use of the&amp;nbsp;&lt;code&gt;$.telligent.evolution.sockets.ideavotes&lt;/code&gt; API that is automatically generated for our &lt;code&gt;ISocket&lt;/code&gt; implementation. &amp;nbsp;That API will enable the widget to listen for messages from the custom socket. &amp;nbsp;In this case, the message&amp;#39;s data will output to the browser&amp;#39;s console window.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="javascript"&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
	jQuery.telligent.evolution.sockets.ideavotes.on(&amp;#39;ideavoted&amp;#39;, function(data) {
		console.log(data);
	});
});
&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The widget can be placed on the Idea page or Idea List page,&amp;nbsp;you will be able to see the messages for the ideas you are currently viewing when any vote is received on the idea(s) you are currently viewing.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50m"&gt;&lt;a id="Completed_Sample" name="Completed_Sample"&gt;&lt;/a&gt;Completed Sample&lt;/h3&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;using System;
using Telligent.Evolution.Extensibility.Ideation.Api;
using Telligent.Evolution.Extensibility.Sockets.Version1;
using Telligent.Evolution.Extensibility.Version1;

namespace Telligent.Evolution.Examples
{
    public class VoteSocket : IPlugin, ISocket
    {
        ISocketController _sockets;
        IIdeas _ideas;
        IVotes _ideaVotes;

        public string Name =&amp;gt; &amp;quot;Idea Vote Sockets&amp;quot;;
        public string Description =&amp;gt; &amp;quot;Enables live updates to idea votes.&amp;quot;;
        public string SocketName =&amp;gt; &amp;quot;ideavotes&amp;quot;;

        public void Initialize()
        {
            _ideas = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IIdeas&amp;gt;();

            _ideaVotes = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IVotes&amp;gt;();
            _ideaVotes.Events.AfterCreate += VoteCreated;
            _ideaVotes.Events.AfterDelete += VoteDeleted;
            _ideaVotes.Events.AfterUpdate += VoteUpdated;
        }

        public void SetController(ISocketController controller)
        {
            _sockets = controller;
        }

        private void VoteCreated(VoteAfterCreateEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        private void VoteUpdated(VoteAfterUpdateEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        private void VoteDeleted(VoteAfterDeleteEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        void SendVoteCounts(Guid ideaId)
        {
            var idea = _ideas.Get(ideaId);
            if (idea != null &amp;amp;&amp;amp; !idea.HasErrors())
            {
                var upVotes =
                    _ideaVotes.List(new VotesListOptions() {IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = true });

                var downVotes =
                    _ideaVotes.List(new VotesListOptions() { IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = false });

                // send socket message with updated totals
                _sockets.Clients.SendToUsersPresentToContent(idea.ContentId, &amp;quot;ideavoted&amp;quot;, new
                {
                    contentId = idea.ContentId,
                    contentTypeId = _ideas.ContentTypeId,
                    yesVotes = upVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;,
                    noVotes = downVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;
                });
            }
        }
    }
}
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="xml"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;
&amp;lt;scriptedContentFragments&amp;gt;
  &amp;lt;scriptedContentFragment name=&amp;quot;Idea Socket Presence Test&amp;quot; version=&amp;quot;10.0.0.0&amp;quot; description=&amp;quot;&amp;quot; instanceIdentifier=&amp;quot;c7e0a2c7d2b44ab08f22d8938ef03a06&amp;quot; theme=&amp;quot;&amp;quot; isCacheable=&amp;quot;false&amp;quot; varyCacheByUser=&amp;quot;false&amp;quot; showHeaderByDefault=&amp;quot;false&amp;quot; cssClass=&amp;quot;&amp;quot; provider=&amp;quot;7bb87a0cc5864a9392ae5b9e5f9747b7&amp;quot;&amp;gt;
    &amp;lt;contentScript&amp;gt;&amp;lt;![CDATA[

&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
	jQuery.telligent.evolution.sockets.ideavotes.on(&amp;#39;ideavoted&amp;#39;, function(data) {
		console.log(data);
	});
});
&amp;lt;/script&amp;gt;

]]&amp;gt;&amp;lt;/contentScript&amp;gt;
  &amp;lt;/scriptedContentFragment&amp;gt;
&amp;lt;/scriptedContentFragments&amp;gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l50a"&gt;&lt;a id="Scale-out" name="Scale-out"&gt;&lt;/a&gt;Scale-out&lt;/h2&gt;
&lt;h3 id="mcetoc_1dio78l50b"&gt;&lt;a id="Overview" name="Overview"&gt;&lt;/a&gt;Overview&lt;/h3&gt;
&lt;p&gt;While multiple users connected to a single web node are easy enough to reason about, this becomes more complicated&amp;nbsp;when there are multiple app nodes and&amp;nbsp;a job server. Consider&amp;nbsp;the case of User A on Server X and User B on Server Y where User A intends to send a real-time chat socket message to User B. The socket message must not only be sent to a different user, it must be sent to that user from a different server entirely. Or consider the case of a plugin running in the context of a job on the job server instead of a web node which also intends to send a socket message to a user, such as a socket-based message&amp;nbsp;that some delayed process has completed. The job server is not connected directly to any users, and so needs to communicate with the web nodes in order to deliver socket messages.&lt;/p&gt;
&lt;p&gt;These scenarios are already&amp;nbsp;&lt;em&gt;automatically and transparently&lt;/em&gt; supported through the use of the message bus.&amp;nbsp;&lt;strong&gt;Verint Community requires the use of a&amp;nbsp;message bus&lt;/strong&gt;. Verint Community comes with&amp;nbsp;two possible message bus services built in, the Socket Message Bus Windows Service as well as the lower performance&amp;nbsp;Database Message Bus. At least one of these services or another conforming message bus is required to be enabled as part of the installation of Community.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50c"&gt;&lt;a id="Socket_Message_Bus_Server" name="Socket_Message_Bus_Server"&gt;&lt;/a&gt;Socket Message Bus Service&lt;/h3&gt;
&lt;p&gt;Verint&amp;nbsp;Community comes with the Socket Message Bus Windows Service and its corresponding &lt;code&gt;ISocketMessageBus&lt;/code&gt; plugin-based connector, &lt;em&gt;Socket Message Bus Service &lt;/em&gt;available in&lt;em&gt; Administration &amp;gt; Site &amp;gt; Message Buses&lt;/em&gt;. This is simply a Windows Service which echoes messages it receives to all connected Verint&amp;nbsp;Community instances.&lt;/p&gt;
&lt;p&gt;Community also includes an alternative Database Message Bus which&amp;nbsp;has lower performance, but requires no separate service installation.&amp;nbsp;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50d"&gt;&lt;a id="Custom_Message_Bus" name="Custom_Message_Bus"&gt;&lt;/a&gt;Custom Message Bus&lt;/h3&gt;
&lt;p&gt;In cases where a community would prefer to use an existing third party message bus solution, custom &lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus plugins&lt;/a&gt; can be written against it and deployed. An example could be a message bus service which supports multiple Verint&amp;nbsp;Community communities on a single bus server by potentially adding an identifier to the string messages sent and received by the plugin for routing the message on the bus server.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50e"&gt;&lt;a id="Generic_Messages" name="Generic_Messages"&gt;&lt;/a&gt;Generic Messages&lt;/h3&gt;
&lt;p&gt;Custom logic in &lt;code&gt;ISocket&lt;/code&gt; plugins can also make use of the message bus directly. Generic messages can be useful for keeping small amounts&amp;nbsp;of state synchronized in realtime across application instances.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt; injected into &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; plugins contains an instance of an &lt;a href="/developers/w/developer90/50167.imessagebuscontroller-plugin-supplementary-type"&gt;IMessageBusController&lt;/a&gt;. The &lt;a href="/developers/w/developer90/50167.imessagebuscontroller-plugin-supplementary-type"&gt;IMessageBusController&lt;/a&gt; exposes events for when generic messages are received from instances of the application along with a method for sending them.&lt;/p&gt;
&lt;p&gt;A useful pattern for state change is to send a generic message to the bus, and only handle it once it is re-received. This allows all instances to know about the state. Additionally, the instance that sends it receives the message immediately without having to wait for the round-trip, and is made aware of the local origin of the message. In this manner, the sender can also be exclusively responsible for potentially persisting the state change elsewhere.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;controller.MessageBus.Publish(&amp;quot;something.happened&amp;quot;,&amp;quot;&amp;quot;);
controller.MessageBus.Received += (sender, e) =&amp;gt;
{
    if (e.MessageName == &amp;quot;something.happened&amp;quot;)
    {
        // update some local caches
        // ...
        if (e.Source == BusMessageSource.Local)
        {
            // update DB
            // ...
        }
    }
};&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l50n"&gt;&lt;a id="Tips_and_Tricks" name="Tips_and_Tricks"&gt;&lt;/a&gt;Additional Notes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Socket connections are only established for authenticated, non-system, users&lt;/li&gt;
&lt;li&gt;User disconnection events are raised whenever&amp;nbsp;a user&amp;#39;s last window&amp;nbsp;or tab for a&amp;nbsp;browser closes, as they all share a single connection. Disconnection events can also raise when plugins refresh.&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: socket, messaging, presence, bus&lt;/div&gt;
</description></item><item><title>Sockets and Presence</title><link>https://community.telligent.com/community/11/w/developer-training/65063/sockets-and-presence/revision/5</link><pubDate>Tue, 20 Aug 2019 21:47:45 GMT</pubDate><guid isPermaLink="false">f141b2d7-5f01-47b0-ab4d-105e12603c36</guid><dc:creator>Michael Monteleone</dc:creator><comments>https://community.telligent.com/community/11/w/developer-training/65063/sockets-and-presence#comments</comments><description>Revision 5 posted to Developer Training by Michael Monteleone on 08/20/2019 21:47:45&lt;br /&gt;
&lt;p&gt;The Socket Framework provides support for &lt;strong&gt;real-time two-way communication between Verint Community and the browser&lt;/strong&gt;. This enables&amp;nbsp;receiving and sending messages directly to specific users or scoped&amp;nbsp;groups of users.&lt;/p&gt;
&lt;p&gt;[toc]&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l500"&gt;&lt;a id="When_would_I_want_to_use_sockets" name="When_would_I_want_to_use_sockets"&gt;&lt;/a&gt;When would I want to use sockets or presence?&lt;/h2&gt;
&lt;p&gt;Sockets are useful when you need to push messages from the server to the browser. An easy example to consider is a notification popup that is pushed to a user in the event of an action occurring on the server. Sockets are the mechanism through which built-in platform features including notifications, chat, live activity streams, forum threads, comment threads,&amp;nbsp;theme previews, presence indicators, tracing, and more communicate with the browser.&amp;nbsp;Socket plugins can&amp;nbsp;be developed to easily power other functionality like real-time whiteboards, analytics, or even games.&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l501"&gt;&lt;a id="Overview" name="Overview"&gt;&lt;/a&gt;Overview&lt;/h2&gt;
&lt;p&gt;Built on top of &lt;a href="http://signalr.net/"&gt;SignalR&lt;/a&gt;, the Socket Framework inherits all of SignalR&amp;#39;s performance, stability, and diversity of browser support over underlying WebSocket, server-sent event, or&amp;nbsp;long polling transports. Because it is Verint&amp;nbsp;Community-specific, the Socket Framework can provide:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;[[Plugins|Plugin]] based extensibility&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Both built-in and third-party [[Plugins|plugin]] can implement their own &lt;em&gt;sockets&lt;/em&gt; which each define a pair of server and client methods and events for bi-directional communication, all multiplexed over a single&amp;nbsp;underlying connection to the server.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Presence&lt;/strong&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Users&amp;#39; site presence as well as their presence to individual pieces of content regardless of how and where that content is viewed&amp;nbsp;is&amp;nbsp;tracked&amp;nbsp;to enable&amp;nbsp;delivery of messages scoped only to&amp;nbsp;users viewing&amp;nbsp;specific&amp;nbsp;content. Additionally, Service Presence supports a similar, but non-content-based scoping of messages.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scale-out and reliability&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;All sockets are multiplexed across&amp;nbsp;a single connection between&amp;nbsp;the server and browser. Additionally,&amp;nbsp;the browser shares the same, single, connection across all of its windows and&amp;nbsp;tabs, transparently identifying a single window or tab at a time to serve&amp;nbsp;as the connection&amp;#39;s host.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Socket connections are reliably maintained and reconnect after any disconnections with randomized, exponential, retry backoffs.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;To support scale-out to multiple application instances and&amp;nbsp;delivery&amp;nbsp;of socket messages from plugins&amp;nbsp;running outside of web contexts in the job server, Verint&amp;nbsp;Community automatically distributes message sending&amp;nbsp;across a bus.&amp;nbsp;Community&amp;nbsp;bundles two&amp;nbsp;possible message bus servers: the Socket Message Bus Service as well as the lower-performing Database Message Bus. Alternatively, Verint&amp;nbsp;Community can use &lt;em&gt;any&lt;/em&gt; message bus service through plugin extensibility. The configuration of which message bus server to use, if any at all, is defined by [[Plugins|plugin]]-based connectors, which can be enabled or disabled through standard plugin management without restarting the application. Socket plugins also expose the underlying bus for use as a way to keep real-time application state in synchronization across multiple instances as needed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="mcetoc_1dio78l502"&gt;&lt;a id="API" name="API"&gt;&lt;/a&gt;API&lt;/h2&gt;
&lt;p&gt;The server-side API exists as a set of interfaces implementable by [[Plugins|plugins]].&lt;/p&gt;
&lt;p&gt;&lt;img src="/resized-image/__size/640x480/__key/communityserver-wikis-components-files/00-00-00-12-83/sockets.png" alt=" " /&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l503"&gt;&lt;a id="ISocket_Plugin" name="ISocket_Plugin"&gt;&lt;/a&gt;&lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket Plugin&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A socket is defined by a [[Plugins|plugin]] which implements the &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; interface. A single socket plugin represents a single channel of communication between the server and browser. For example, a socket plugin may represent all functionality related to sending and receiving realtime chat messages. A single socket plugin can send and receive arbitrary messages and optional data with those messages, but can only send or receive messages sent by or to the same socket plugin.&lt;/p&gt;
&lt;p&gt;Socket plugins are injected with instances of &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt; exposes an instance of an &lt;a href="/developers/w/developer90/50149.iclientscontroller-plugin-supplementary-type"&gt;IClientsController&lt;/a&gt; which contains events for when a user connects, disconnects, or sends a message from the browser. The &lt;a href="/developers/w/developer90/50149.iclientscontroller-plugin-supplementary-type"&gt;IClientsController&lt;/a&gt; also supports sending messages to a user, to all users present to specific&amp;nbsp;content or services, or broadcasting to all users.&lt;/p&gt;
&lt;p&gt;Each enabled socket plugin yields a corresponding client-side API.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l504"&gt;&lt;a id="ISocketMessageBus_Plugin" name="ISocketMessageBus_Plugin"&gt;&lt;/a&gt;&lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus Plugin&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Multiple-application instance scale-out and message delivery from non-web contexts like job server plugins is automatically&amp;nbsp;supported&amp;nbsp;by&amp;nbsp;the&amp;nbsp;enablement of plugins which implement the &lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus&lt;/a&gt; interface. Verint&amp;nbsp;Community bundles two default implementations to connect to either the Socket Message Bus Service or the Database Message Bus, but also supports integrating with other message busses as well. For details, see the discussion on Scale-Out.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l505"&gt;&lt;a id="Client-Side" name="Client-Side"&gt;&lt;/a&gt;Client-Side&lt;/h3&gt;
&lt;h4&gt;&lt;a id="Socket_Endpoints" name="Socket_Endpoints"&gt;&lt;/a&gt;Socket Endpoints&lt;/h4&gt;
&lt;p&gt;Each &lt;code&gt;ISocket&lt;/code&gt; plugin implements a &lt;code&gt;SocketName&lt;/code&gt;. This one-word string becomes the name of the client-side API. For example, given the socket:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public class MySocket : ISocket
{
    // ...

    string SocketName { get { return &amp;quot;mySocket&amp;quot;; } }

    // ...
}&lt;/pre&gt;&lt;/p&gt;
&lt;pre class="brush: csharp"&gt;&lt;/pre&gt;
&lt;p&gt;Then the following JavaScript API will be automatically exposed:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="javascript"&gt;// receive and handle a message with optional data from the server
jQuery.telligent.evolution.sockets.mySocket.on(messageName, function(data) {
   // handle
});

// send data to the server an optional object message
jQuery.telligent.evolution.sockets.mySocket.send(messageName, data);&lt;/pre&gt;&lt;/p&gt;
&lt;h4&gt;&lt;a id="Initiation" name="Initiation"&gt;&lt;/a&gt;Initiation&lt;/h4&gt;
&lt;p&gt;Before attempting to send or receive messages from the client side, the Socket Framework must initiate itself. This happens automatically, and when complete, it publishes a &lt;a href="/developers/w/developer90/50006.socket-connected-client-message"&gt;socket.connected&lt;/a&gt; &lt;a href="/developers/w/developer90/50024.messaging-javascript-api-module"&gt;client-side message&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="javascript"&gt;$.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
    // set up message listeners or send messages
});&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l506"&gt;&lt;a id="Example_Socket" name="Example_Socket"&gt;&lt;/a&gt;Simple Example Socket&lt;/h2&gt;
&lt;p&gt;The following shows a basic example of a socket which routes greetings from one user to another. A user provides the user name of another community member, clicks &amp;#39;greet&amp;#39;, and an alert is displayed to the other user.&lt;/p&gt;
&lt;p&gt;Greetings are initiated from a user via a widget, sent via the client-side socket API to the &lt;code&gt;ISocket&lt;/code&gt; plugin, and then delivered to the recipient user where the same widget instance for the other user will display the message in a JavaScript &lt;code&gt;alert()&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l507"&gt;&lt;a id="Server_Side" name="Server_Side"&gt;&lt;/a&gt;Server Side&lt;/h3&gt;
&lt;p&gt;Create a new [[Plugins|plugin]] which implements the &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; interface. Its &lt;code&gt;Name&lt;/code&gt;, &lt;code&gt;Description&lt;/code&gt;, and &lt;code&gt;Initialize()&lt;/code&gt; are unimportant. For &lt;code&gt;SocketName&lt;/code&gt; and &lt;code&gt;SetController()&lt;/code&gt;, use the following:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public string SocketName =&amp;gt; &amp;quot;greeter&amp;quot;;

public void SetController(ISocketController controller)
{
    controller.Clients.Received += (sender, e) =&amp;gt;
    {
        // if this was a greting message, let&amp;#39;s process it
        if (e.MessageName == &amp;quot;greet&amp;quot;)
        {
            // get the associated recipient user
            // data passed from the client side is available on the dynamic MessageData object
            var to = PublicApi.Users.Get(new UsersGetOptions { Username = (string)e.MessageData.Recipient });

            // get the sender user
            var from = PublicApi.Users.Get(new UsersGetOptions { Id = e.UserId });

            // send a new message to the recipient
            controller.Clients.Send(to.Id.GetValueOrDefault(), &amp;quot;greet&amp;quot;, new
            {
                Message = String.Format(&amp;quot;Hello {0}, from {1}&amp;quot;, to.DisplayName, from.DisplayName)
            });
        }
    };
}&lt;/pre&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l508"&gt;&lt;a id="Client_Side" name="Client_Side"&gt;&lt;/a&gt;Client Side&lt;/h3&gt;
&lt;p&gt;In Widget Studio, create a new widget&amp;nbsp;with content:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="velocity"&gt;## set up some unique ids for interface elements
#set($recipientInputId = $core_v2_widget.UniqueId(&amp;#39;recipient&amp;#39;))
#set($sendLinkId = $core_v2_widget.UniqueId(&amp;#39;greet&amp;#39;))

## basic interface
&amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;$recipientInputId&amp;quot; /&amp;gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;$sendLinkId&amp;quot;&amp;gt;Greet&amp;lt;/a&amp;gt;

&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
// Wait for socket to be connected
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {

    // when &amp;#39;Greet&amp;#39; is clicked, send a message to be delivered to the recipient
    jQuery(&amp;#39;#$sendLinkId&amp;#39;).on(&amp;#39;click&amp;#39;, function(e) {
        e.preventDefault();

        jQuery.telligent.evolution.sockets.greeter.send(&amp;#39;greet&amp;#39;, {
            Recipient: jQuery(&amp;#39;#$recipientInputId&amp;#39;).val()
        });
    });

    // when a &amp;#39;greet&amp;#39; message is received from the socket, display it as an alert
    jQuery.telligent.evolution.sockets.greeter.on(&amp;#39;greet&amp;#39;, function(data){
        alert(data.Message);
    });
});
&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Note use of the &lt;a href="/developers/w/developer90/50006.socket-connected-client-message"&gt;socket.connected&lt;/a&gt; &lt;a href="/developers/w/developer90/50024.messaging-javascript-api-module"&gt;client-side message&lt;/a&gt; as well as the automatically-generated &lt;code&gt;jQuery.telligent.evolution.sockets.testSocket&lt;/code&gt; API.&lt;/p&gt;
&lt;p&gt;The result is a simple UI that enables sending a greeting to another user by their user name.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter.png"&gt;&lt;img style="border:1px solid #DDD;width:264px;" alt=" " src="/resized-image/__size/640x480/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter_2D00_greeted.png"&gt;&lt;img style="border:1px solid #DDD;width:485px;" alt=" " src="/resized-image/__size/640x480/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter_2D00_greeted.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l509"&gt;&lt;a id="Download" name="Download"&gt;&lt;/a&gt;Download&lt;/h3&gt;
&lt;p&gt;The complete sample can be downloaded:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/1680_2E00_SocketSample_2E00_cs"&gt;community.telligent.com/.../1680_2E00_SocketSample_2E00_cs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/5314.GreeterUI_2D00_Widget.xml"&gt;community.telligent.com/.../5314.GreeterUI_2D00_Widget.xml&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l50f"&gt;&lt;a id="Presence_Services" name="Presence_Services"&gt;&lt;/a&gt;Presence Services&lt;/h2&gt;
&lt;p&gt;Being able to send messages directly to individual users is a great start. However, there is often a need to send messages to specific groups of users, i.e. messages about new replies to all users viewing a given forum thread so that it may&amp;nbsp;update its UI&amp;nbsp;in realtime. To that end, presence services enable sending messages to users scoped by their &lt;em&gt;presence&lt;/em&gt; to pieces of [The Content Model|content] or abstract &lt;em&gt;service&lt;/em&gt;&amp;nbsp;groupings.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50h"&gt;&lt;a id="Content_Presence" name="Content_Presence"&gt;&lt;/a&gt;Content Presence&lt;/h3&gt;
&lt;p&gt;The Content Presence service tracks which &lt;span&gt;[&lt;/span&gt;&lt;span&gt;The Content Model|content]&lt;/span&gt; users are currently viewing. This enables the platform to deliver updates to&amp;nbsp;users in real time regarding&amp;nbsp;changes to content they are currently viewing. &lt;strong&gt;Importantly&lt;/strong&gt;, this can mean in whatever or wherever way that the content is presented. For example, a user viewing a forum thread&amp;#39;s question&amp;nbsp;in a group&amp;#39;s&amp;nbsp;activity stream is considered and tracked&amp;nbsp;as present to that forum&amp;nbsp;thread&amp;nbsp;the same&amp;nbsp;as a user on the forum thread&amp;#39;s own page. Also importantly, content presence even takes into account whether the content&amp;#39;s UI is scrolled into view. For example, a user is&amp;nbsp;&lt;em&gt;not&lt;/em&gt; be present to another forum thread whose activity story is&amp;nbsp;scrolled out of browser view in the activity stream.&lt;/p&gt;
&lt;h4&gt;&lt;/h4&gt;
&lt;h4&gt;&lt;a id="Content_Presence_Mappings" name="Content_Presence_Mappings"&gt;&lt;/a&gt;Content Presence&amp;nbsp;Mappings&lt;/h4&gt;
&lt;p&gt;To understand content presence APIs, it is important to first understand &lt;em&gt;the ways in which&amp;nbsp;content presence mappings are created and removed:&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Page Context&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;The service uses [Page Definition and URL Routing|URL context] to track what content the using is currently viewing. As long as a user is on a URL with content context, the user is present to those content records. For example,&amp;nbsp;if a user is viewing a blog post, the content service would be aware that the user is present to&amp;nbsp;that blog post, the blog, and even the post&amp;#39;s author&amp;#39;s content records. So, sending a socket message to any of those three content IDs would deliver it to the viewing user.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HTML presence&amp;nbsp;attributes&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;In addition to overall page context, specific portions of a page&amp;#39;s UI can identify themselves as representing specific content, so that while a user is viewing that UI, the user also is also mapped as present to the&amp;nbsp;content. These identifications are represented as attributes added to the HTML&amp;nbsp;element.&amp;nbsp;The activity stream uses such HTML presence attributes to wrap stories in the stream so that the user is present to stories&amp;#39; corresponding content, and only when those stories are scrolled into view.&lt;/li&gt;
&lt;li&gt;HTML presence&amp;nbsp;attributes can be added to through the &lt;code&gt;core_v2_contentPresence.RenderAttributes&lt;/code&gt; method. &amp;nbsp;This method will render the proper attributes to automatically track a user&amp;#39;s content presence, when the decorated element is currently visible on the page they are viewing. &amp;nbsp;The comment stream and activity stream are two examples where this method is in use.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;APIs&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&amp;nbsp;In-Process, Rest and Script&amp;nbsp;APIs are available to directly add and remove&amp;nbsp;presence mappings, though these are rarely needed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Content presence mappings are&amp;nbsp;&lt;em&gt;automatically removed&lt;/em&gt;&amp;nbsp;when they expire. As long as a user is on a page, the page is pinging back to the server to identify that the user is online, and to identify the list of content records the user is present to, whether they were&amp;nbsp;identified by the overall page&amp;#39;s context, or the currently scrolled elements decorated with&amp;nbsp;HTML presence attributes. Presence mappings that have not been refreshed for across a few&amp;nbsp;of these pings are considered expired and unmapped, thereby removing the user from receipt of socket messages&amp;nbsp;sent to users present to the content. Since&amp;nbsp;all windows and tabs of a single browser share a single socket connection, the single connection sends a ping identifying present content records across &lt;em&gt;all&lt;/em&gt; open windows and tabs.&lt;/p&gt;
&lt;h4&gt;&lt;a id="Content_Presence_API" name="Content_Presence_API"&gt;&lt;/a&gt;Content Presence API&lt;/h4&gt;
&lt;p&gt;Content presence APIs enable sending messages, querying total presence counts, and registering specific presence mappings.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;To send messages&lt;/em&gt;, use &lt;a href="/community/11/w/api-documentation/64162/iclientscontroller-plugin-supplementary-type"&gt;IClientsController.SendToUsersPresentToContent(Guid contentId, string messageName)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To query&lt;em&gt;&amp;nbsp;metadata summaries&lt;/em&gt; about users present to a given piece of content via &lt;a href="/11/w/api-documentation/63974/contentpresence-in-process-api-service"&gt;&lt;code&gt;IContentPresence&lt;/code&gt;&lt;/a&gt; or&amp;nbsp;&lt;code&gt;&lt;a href="/community/11/w/api-documentation/65749/core_5f00_v2_5f00_contentpresence-script-api"&gt;core_v2_contentPresence.GetSummary()&lt;/a&gt;. &lt;/code&gt;This metadata&amp;nbsp;is just a count summary, and may&amp;nbsp;be delayed.&lt;/p&gt;
&lt;p&gt;To register specific HTML elements as representing content so that&amp;nbsp;the user is mapped to the content while viewing the element, use &lt;code&gt;&lt;a href="/community/11/w/api-documentation/65749/core_5f00_v2_5f00_contentpresence-script-api#RenderAttributes"&gt;core_v2_contentPresence.RenderAttributes()&lt;/a&gt;&lt;/code&gt;&lt;span&gt;.&amp;nbsp;This method will render the proper attributes&amp;nbsp;to include inline with any HTML element, such as a &amp;lt;div&amp;gt; wrapping an activity stream story, or a &amp;lt;span&amp;gt; surrounding a like button.&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50i"&gt;&lt;a id="Service_Presence" name="Service_Presence"&gt;&lt;/a&gt;Service Presence&lt;/h3&gt;
&lt;p&gt;Service Presence is nearly identical to&amp;nbsp;Content Presence in that it enables&amp;nbsp;mapping a user&amp;#39;s presence and&amp;nbsp;sending socket messages to users based on those mappings. However, while Content Presence is&amp;nbsp;designed specifically for Content IDs and Content Type IDs and automatically maps users to content by their page context, service presence allows mapping users to &lt;em&gt;any arbitrary Guid&lt;/em&gt;. As such, there are no automatically-created service presence mappings. Service presence mappings can only be registered by specific&amp;nbsp;&lt;em&gt;HTML presence attributes&lt;/em&gt; or the APIs (rarely&amp;nbsp;used). (Please see the above discussion on Content Presence Mappings for a discussion on how such attributes work.)&lt;/p&gt;
&lt;p&gt;In this way, a widget can define an HTML element to contain&amp;nbsp;a service presence mapping of any arbitrary ID.&amp;nbsp;Any user viewing that widget will be considered present to that ID &amp;quot;service&amp;quot;. And a socket plugin can then deliver a message to any user viewing&amp;nbsp;that widget by the same arbitrary service presence ID.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Similar to content presence, service presence mappings&amp;nbsp;automatically expire.&lt;/p&gt;
&lt;p&gt;While less frequently needed than content presence, service presence provides flexibility for edge cases.&lt;/p&gt;
&lt;h4&gt;&lt;a id="Service_Presence_API" name="Service_Presence_API"&gt;&lt;/a&gt;Service Presence API&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;To send messages&lt;/em&gt;, use &lt;a href="/community/11/w/api-documentation/64162/iclientscontroller-plugin-supplementary-type"&gt;IClientsController.SendToUsersPresentToContent(Guid contentId, string messageName)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To query&lt;em&gt;&amp;nbsp;metadata summaries&lt;/em&gt; about users present to an ID via &lt;a href="/community/11/w/api-documentation/64069/servicepresence-in-process-api-service"&gt;&lt;code&gt;IServicePresence&lt;/code&gt;&lt;/a&gt; or&amp;nbsp;&lt;code&gt;&lt;a href="/community/11/w/api-documentation/65767/core_5f00_v2_5f00_servicepresence-script-api#GetSummary"&gt;core_v2_servicePresence.GetSummary()&lt;/a&gt;. &lt;/code&gt;This metadata&amp;nbsp;is just a count summary, and may&amp;nbsp;be delayed.&lt;/p&gt;
&lt;p&gt;To register specific HTML elements as services mapping ID so that&amp;nbsp;the user is mapped to the ID&amp;nbsp;while viewing the element, use &lt;code&gt;&lt;a href="/community/11/w/api-documentation/65767/core_5f00_v2_5f00_servicepresence-script-api#RenderAttributes"&gt;core_v2_servicePresence.RenderAttributes()&lt;/a&gt;&lt;/code&gt;&lt;span&gt;.&amp;nbsp;This method will render the proper attributes&amp;nbsp;to include inline with any HTML element.&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50i"&gt;&lt;/h3&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50g"&gt;&lt;a id="User_Presence" name="User_Presence"&gt;&lt;/a&gt;User Presence&lt;/h3&gt;
&lt;p&gt;User Presence is built atop sockets and content presence. After all, user records are content records, too.&lt;/p&gt;
&lt;p&gt;User presence is a set of related&amp;nbsp;UIs, APIs which track and render a user&amp;#39;s overall presence to the site.&lt;/p&gt;
&lt;h4&gt;&lt;a id="UI" name="UI"&gt;&lt;/a&gt;UI&lt;/h4&gt;
&lt;p&gt;The service is responsible for the presence indicator often&amp;nbsp;displayed alongside the user&amp;nbsp;names.&lt;/p&gt;
&lt;p&gt;&lt;img alt=" " src="/resized-image/__size/320x240/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence.png" /&gt;&lt;/p&gt;
&lt;h4&gt;&lt;a id="API" name="API"&gt;&lt;/a&gt;API&lt;/h4&gt;
&lt;p&gt;Live-updating user presence indicators&amp;nbsp;can be easily&amp;nbsp;rendered with &lt;code&gt;&lt;a href="/community/11/w/api-documentation/65797/core_5f00_v2_5f00_ui-script-api#UserPresence"&gt;core_v2_ui.UserPresence()&lt;/a&gt;&lt;/code&gt;. These are an easy way to add benefits of realtime-updating presence to your UI to&amp;nbsp;improve engagement in your community.&lt;/p&gt;
&lt;p&gt;Of note, core_v2_ui.UserPresence is, itself, built on top of these&amp;nbsp;APIs. It renders a &lt;a href="/community/11/w/api-documentation/65143/ui-javascript-api-module"&gt;UI component&lt;/a&gt; which presents&amp;nbsp;an indicator dot wrapped with content presence HTML attributes&amp;nbsp;registering&amp;nbsp;the&amp;nbsp;accessing user as present to the&amp;nbsp;user being indicated so that socket messages sent on users&amp;#39; presence change events&amp;nbsp;can be delivered to anyone viewing the changed users&amp;#39; indicators.&lt;/p&gt;
&lt;p&gt;A user&amp;#39;s current presence is an attribute of the user&amp;#39;s entity, returned from REST, Script, or In-Process APIs. Like other user property changes, changes to their presence can be handled with events.&lt;/p&gt;
&lt;p&gt;Similar to content and service presence mappings, users&amp;#39; presences are automatically set to offline whenever the user closes all of their browser windows and tabs or after the last of their content presence mappings expire.&lt;/p&gt;
&lt;h4&gt;&lt;a id="Privacy" name="Privacy"&gt;&lt;/a&gt;Privacy&lt;/h4&gt;
&lt;p&gt;The platform has the options for&amp;nbsp;&lt;strong&gt;Enable Presence Tracking&lt;/strong&gt;,&amp;nbsp;&lt;strong&gt;Allow Members To Toggle Presence Tracking Enablement &lt;/strong&gt;and&lt;strong&gt; Default Presence Tracking Enablement Value &amp;nbsp;&lt;/strong&gt;available under Membership in the Membership Options panel in Administration. &amp;nbsp;&lt;strong&gt;Enable Presence Tracking&amp;nbsp;&lt;/strong&gt;controls whether user presence tracking is available for the community. &amp;nbsp;If tracking is enabled, &amp;nbsp;&lt;strong&gt;Allow Members To Toggle Presence Tracking Enablement&lt;/strong&gt; controls whether or not each user should have the option to disable tracking of their online status. If that option is enabled the&amp;nbsp;&lt;strong&gt;Default Presence Tracking Enablement Value&amp;nbsp;&lt;/strong&gt;is also available. &amp;nbsp;If users are giving the option to control their presence tracking, the&amp;nbsp;&lt;strong&gt;Enable presence tracking&lt;/strong&gt; option will be available in the membership settings.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence-admin.png"&gt;&lt;img alt=" " src="/resized-image/__size/550x539/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence-admin.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l50j"&gt;&lt;a id="Example_Socket_using_Content_Presence_Service" name="Example_Socket_using_Content_Presence_Service"&gt;&lt;/a&gt;Example Socket using Content Presence&lt;/h2&gt;
&lt;p&gt;This example will&amp;nbsp;create an &lt;code&gt;ISocket&lt;/code&gt; implementation that will send socket messages to users when a vote is received or changed on an idea. By combining the socket implementation with the content presence service, the socket messages can be sent only to those users who are currently viewing the idea that received the vote.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50k"&gt;&lt;a id="Server_Side" name="Server_Side"&gt;&lt;/a&gt;Server Side&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;ISocket&lt;/code&gt; implementation will use the &lt;em&gt;ideavotes&lt;/em&gt; for the &lt;code&gt;SocketName &lt;/code&gt;and maintain a reference to the &lt;code&gt;SocketController&lt;/code&gt; for later use in our example.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;ISocketController _sockets;
public string SocketName =&amp;gt; &amp;quot;ideavotes&amp;quot;;

public void SetController(ISocketController controller)
{
    _sockets = controller;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The example class will need to send a message whenever an idea is&amp;nbsp;voted on, this can be accomplished by attaching to the Idea Vote Events for these actions in our plugin&amp;#39;s &lt;code&gt;Initialize&lt;/code&gt; method. &amp;nbsp;In each event handler, we will call the same method SendVoteCounts passing the idea id for the vote.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public void Initialize()
{
    _ideas = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IIdeas&amp;gt;();

    _ideaVotes = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IVotes&amp;gt;();
    _ideaVotes.Events.AfterCreate += VoteCreated;
    _ideaVotes.Events.AfterDelete += VoteDeleted;
    _ideaVotes.Events.AfterUpdate += VoteUpdated;
}

private void VoteCreated(VoteAfterCreateEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}

private void VoteUpdated(VoteAfterUpdateEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}

private void VoteDeleted(VoteAfterDeleteEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;In the SendVoteCounts method, the number of up and down votes will be retrieved and the&amp;nbsp;&lt;code&gt;_sockets.Clients.SendToUsersPresentToContent &lt;/code&gt;method will be used to send a message to all users who are currently present to that idea.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;void SendVoteCounts(Guid ideaId)
{
    var idea = _ideas.Get(ideaId);
    if (idea != null &amp;amp;&amp;amp; !idea.HasErrors())
    {
        var upVotes =
            _ideaVotes.List(new VotesListOptions() {IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = true });

        var downVotes =
            _ideaVotes.List(new VotesListOptions() { IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = false });

        // send socket message with updated totals
        _sockets.Clients.SendToUsersPresentToContent(idea.ContentId, &amp;quot;ideavoted&amp;quot;, new
        {
            contentId = idea.ContentId,
            contentTypeId = _ideas.ContentTypeId,
            yesVotes = upVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;,
            noVotes = downVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;
        });
    }
}&lt;/pre&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50l"&gt;&lt;a id="Client_Side" name="Client_Side"&gt;&lt;/a&gt;Client Side&lt;/h3&gt;
&lt;p&gt;Once this plugin is compiled and enabled on the community site, each time an idea is voted on any user who is viewing that idea will receive an &lt;em&gt;ideavoted&amp;nbsp;&lt;/em&gt;socket message. &amp;nbsp;For this example, we can use a widget to see these messages. &amp;nbsp;The example will&amp;nbsp;make use of the&amp;nbsp;&lt;code&gt;$.telligent.evolution.sockets.ideavotes&lt;/code&gt; API that is automatically generated for our &lt;code&gt;ISocket&lt;/code&gt; implementation. &amp;nbsp;That API will enable the widget to listen for messages from the custom socket. &amp;nbsp;In this case, the message&amp;#39;s data will output to the browser&amp;#39;s console window.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="javascript"&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
	jQuery.telligent.evolution.sockets.ideavotes.on(&amp;#39;ideavoted&amp;#39;, function(data) {
		console.log(data);
	});
});
&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The widget can be placed on the Idea page or Idea List page,&amp;nbsp;you will be able to see the messages for the ideas you are currently viewing when any vote is received on the idea(s) you are currently viewing.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50m"&gt;&lt;a id="Completed_Sample" name="Completed_Sample"&gt;&lt;/a&gt;Completed Sample&lt;/h3&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;using System;
using Telligent.Evolution.Extensibility.Ideation.Api;
using Telligent.Evolution.Extensibility.Sockets.Version1;
using Telligent.Evolution.Extensibility.Version1;

namespace Telligent.Evolution.Examples
{
    public class VoteSocket : IPlugin, ISocket
    {
        ISocketController _sockets;
        IIdeas _ideas;
        IVotes _ideaVotes;

        public string Name =&amp;gt; &amp;quot;Idea Vote Sockets&amp;quot;;
        public string Description =&amp;gt; &amp;quot;Enables live updates to idea votes.&amp;quot;;
        public string SocketName =&amp;gt; &amp;quot;ideavotes&amp;quot;;

        public void Initialize()
        {
            _ideas = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IIdeas&amp;gt;();

            _ideaVotes = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IVotes&amp;gt;();
            _ideaVotes.Events.AfterCreate += VoteCreated;
            _ideaVotes.Events.AfterDelete += VoteDeleted;
            _ideaVotes.Events.AfterUpdate += VoteUpdated;
        }

        public void SetController(ISocketController controller)
        {
            _sockets = controller;
        }

        private void VoteCreated(VoteAfterCreateEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        private void VoteUpdated(VoteAfterUpdateEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        private void VoteDeleted(VoteAfterDeleteEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        void SendVoteCounts(Guid ideaId)
        {
            var idea = _ideas.Get(ideaId);
            if (idea != null &amp;amp;&amp;amp; !idea.HasErrors())
            {
                var upVotes =
                    _ideaVotes.List(new VotesListOptions() {IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = true });

                var downVotes =
                    _ideaVotes.List(new VotesListOptions() { IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = false });

                // send socket message with updated totals
                _sockets.Clients.SendToUsersPresentToContent(idea.ContentId, &amp;quot;ideavoted&amp;quot;, new
                {
                    contentId = idea.ContentId,
                    contentTypeId = _ideas.ContentTypeId,
                    yesVotes = upVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;,
                    noVotes = downVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;
                });
            }
        }
    }
}
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="xml"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;
&amp;lt;scriptedContentFragments&amp;gt;
  &amp;lt;scriptedContentFragment name=&amp;quot;Idea Socket Presence Test&amp;quot; version=&amp;quot;10.0.0.0&amp;quot; description=&amp;quot;&amp;quot; instanceIdentifier=&amp;quot;c7e0a2c7d2b44ab08f22d8938ef03a06&amp;quot; theme=&amp;quot;&amp;quot; isCacheable=&amp;quot;false&amp;quot; varyCacheByUser=&amp;quot;false&amp;quot; showHeaderByDefault=&amp;quot;false&amp;quot; cssClass=&amp;quot;&amp;quot; provider=&amp;quot;7bb87a0cc5864a9392ae5b9e5f9747b7&amp;quot;&amp;gt;
    &amp;lt;contentScript&amp;gt;&amp;lt;![CDATA[

&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
	jQuery.telligent.evolution.sockets.ideavotes.on(&amp;#39;ideavoted&amp;#39;, function(data) {
		console.log(data);
	});
});
&amp;lt;/script&amp;gt;

]]&amp;gt;&amp;lt;/contentScript&amp;gt;
  &amp;lt;/scriptedContentFragment&amp;gt;
&amp;lt;/scriptedContentFragments&amp;gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l50a"&gt;&lt;a id="Scale-out" name="Scale-out"&gt;&lt;/a&gt;Scale-out&lt;/h2&gt;
&lt;h3 id="mcetoc_1dio78l50b"&gt;&lt;a id="Overview" name="Overview"&gt;&lt;/a&gt;Overview&lt;/h3&gt;
&lt;p&gt;While multiple users connected to a single web node are easy enough to reason about, this becomes more complicated&amp;nbsp;when there are multiple app nodes and&amp;nbsp;a job server. Consider&amp;nbsp;the case of User A on Server X and User B on Server Y where User A intends to send a real-time chat socket message to User B. The socket message must not only be sent to a different user, it must be sent to that user from a different server entirely. Or consider the case of a plugin running in the context of a job on the job server instead of a web node which also intends to send a socket message to a user, such as a socket-based message&amp;nbsp;that some delayed process has completed. The job server is not connected directly to any users, and so needs to communicate with the web nodes in order to deliver socket messages.&lt;/p&gt;
&lt;p&gt;These scenarios are already&amp;nbsp;&lt;em&gt;automatically and transparently&lt;/em&gt; supported through the use of the message bus.&amp;nbsp;&lt;strong&gt;Verint Community requires the use of a&amp;nbsp;message bus&lt;/strong&gt;. Verint Community comes with&amp;nbsp;two possible message bus services built in, the Socket Message Bus Windows Service as well as the lower performance&amp;nbsp;Database Message Bus. At least one of these services or another conforming message bus is required to be enabled as part of the installation of Community.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50c"&gt;&lt;a id="Socket_Message_Bus_Server" name="Socket_Message_Bus_Server"&gt;&lt;/a&gt;Socket Message Bus Service&lt;/h3&gt;
&lt;p&gt;Verint&amp;nbsp;Community comes with the Socket Message Bus Windows Service and its corresponding &lt;code&gt;ISocketMessageBus&lt;/code&gt; plugin-based connector, &lt;em&gt;Socket Message Bus Service &lt;/em&gt;available in&lt;em&gt; Administration &amp;gt; Site &amp;gt; Message Buses&lt;/em&gt;. This is simply a Windows Service which echoes messages it receives to all connected Verint&amp;nbsp;Community instances.&lt;/p&gt;
&lt;p&gt;Community also includes an alternative Database Message Bus which&amp;nbsp;has lower performance, but requires no separate service installation.&amp;nbsp;&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50d"&gt;&lt;a id="Custom_Message_Bus" name="Custom_Message_Bus"&gt;&lt;/a&gt;Custom Message Bus&lt;/h3&gt;
&lt;p&gt;In cases where a community would prefer to use an existing third party message bus solution, custom &lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus plugins&lt;/a&gt; can be written against it and deployed. An example could be a message bus service which supports multiple Verint&amp;nbsp;Community communities on a single bus server by potentially adding an identifier to the string messages sent and received by the plugin for routing the message on the bus server.&lt;/p&gt;
&lt;h3 id="mcetoc_1dio78l50e"&gt;&lt;a id="Generic_Messages" name="Generic_Messages"&gt;&lt;/a&gt;Generic Messages&lt;/h3&gt;
&lt;p&gt;Custom logic in &lt;code&gt;ISocket&lt;/code&gt; plugins can also make use of the message bus directly. Generic messages can be useful for keeping small amounts&amp;nbsp;of state synchronized in realtime across application instances.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt; injected into &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; plugins contains an instance of an &lt;a href="/developers/w/developer90/50167.imessagebuscontroller-plugin-supplementary-type"&gt;IMessageBusController&lt;/a&gt;. The &lt;a href="/developers/w/developer90/50167.imessagebuscontroller-plugin-supplementary-type"&gt;IMessageBusController&lt;/a&gt; exposes events for when generic messages are received from instances of the application along with a method for sending them.&lt;/p&gt;
&lt;p&gt;A useful pattern for state change is to send a generic message to the bus, and only handle it once it is re-received. This allows all instances to know about the state. Additionally, the instance that sends it receives the message immediately without having to wait for the round-trip, and is made aware of the local origin of the message. In this manner, the sender can also be exclusively responsible for potentially persisting the state change elsewhere.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;controller.MessageBus.Publish(&amp;quot;something.happened&amp;quot;,&amp;quot;&amp;quot;);
controller.MessageBus.Received += (sender, e) =&amp;gt;
{
    if (e.MessageName == &amp;quot;something.happened&amp;quot;)
    {
        // update some local caches
        // ...
        if (e.Source == BusMessageSource.Local)
        {
            // update DB
            // ...
        }
    }
};&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1dio78l50n"&gt;&lt;a id="Tips_and_Tricks" name="Tips_and_Tricks"&gt;&lt;/a&gt;Additional Notes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Socket connections are only established for authenticated, non-system, users&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Sockets and Presence</title><link>https://community.telligent.com/community/11/w/developer-training/65063/sockets-and-presence/revision/4</link><pubDate>Tue, 20 Aug 2019 17:12:35 GMT</pubDate><guid isPermaLink="false">f141b2d7-5f01-47b0-ab4d-105e12603c36</guid><dc:creator>Michael Monteleone</dc:creator><comments>https://community.telligent.com/community/11/w/developer-training/65063/sockets-and-presence#comments</comments><description>Revision 4 posted to Developer Training by Michael Monteleone on 08/20/2019 17:12:35&lt;br /&gt;
&lt;p&gt;The Socket Framework provides support for &lt;strong&gt;real-time two-way communication between Verint Community and the browser&lt;/strong&gt;. This enables&amp;nbsp;receiving and sending messages directly to specific users or scoped&amp;nbsp;groups of users.&lt;/p&gt;
&lt;p&gt;[toc]&lt;/p&gt;
&lt;h2&gt;&lt;a id="When_would_I_want_to_use_sockets" name="When_would_I_want_to_use_sockets"&gt;&lt;/a&gt;When would I want to use sockets?&lt;/h2&gt;
&lt;p&gt;Sockets are useful when you need to push messages from the server to the browser. An easy example to consider is a notification popup that is pushed to a user in the event of an action occurring on the server. Sockets are the mechanism through which built-in platform features including notifications, chat, live activity streams, forum threads, comment threads,&amp;nbsp;theme previews, presence indicators, tracing, and more communicate with the browser.&lt;/p&gt;
&lt;h2&gt;&lt;a id="Overview" name="Overview"&gt;&lt;/a&gt;Overview&lt;/h2&gt;
&lt;p&gt;Built on top of &lt;a href="http://signalr.net/"&gt;SignalR&lt;/a&gt;, the Socket Framework inherits all of SignalR&amp;#39;s performance, stability, and diversity of browser support over underlying WebSocket, server-sent event, or&amp;nbsp;long polling transports. Because it is Verint&amp;nbsp;Community-specific, the Socket Framework can provide:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;[[Plugins|Plugin]] based extensibility&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Both built-in and third-party [[Plugins|plugin]] can implement their own &lt;em&gt;sockets&lt;/em&gt; which each define a pair of server and client methods and events for bi-directional communication, all multiplexed over a single&amp;nbsp;underlying connection to the server.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Presence&lt;/strong&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Users&amp;#39; site presence as well as their presence to individual pieces of content regardless of how and where that content is presented&amp;nbsp;is&amp;nbsp;tracked&amp;nbsp;to enable&amp;nbsp;delivery of messages scoped only to&amp;nbsp;users viewing&amp;nbsp;specific&amp;nbsp;content. Additionally, Service Presence supports a similar, but non-content-based scoping of messages.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scale-out and reliability&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;All sockets are multiplexed over a single connection between&amp;nbsp;the server and browser. And the browser shares the same, single, connection across all of its windows and&amp;nbsp;tabs, transparently identifying a single window or tab at a time to function as the connection&amp;#39;s host.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Socket connections are reliably maintained, and reconnect after disconnections with randomized, exponential, retry backoffs.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;To support scale-out to multiple application instances and&amp;nbsp;delivery&amp;nbsp;of socket messages from plugins&amp;nbsp;running outside of web contexts in the job server, Verint&amp;nbsp;Community bundles two&amp;nbsp;possible message bus servers: the Socket Message Bus Service as well as the lower-performing Database Message Bus. Alternatively, Verint&amp;nbsp;Community can use &lt;em&gt;any&lt;/em&gt; message bus service through plugin extensibility. The configuration of which message bus server to use, if any at all, is defined by [[Plugins|plugin]]-based connectors, which can be enabled or disabled through standard plugin management without restarting the application. Socket plugins also expose the underlying message bus for use as a way to keep real-time application state in synchronization across multiple instances.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The socket framework powers &lt;span&gt;notifications, chat, live activity streams, forum threads, comment threads,&amp;nbsp;theme previews, presence indicators, tracing, and more&lt;/span&gt; in Community. Socket plugins can&amp;nbsp;be developed to easily power other functionality like real-time whiteboards, analytics, or even games.&lt;/p&gt;
&lt;p&gt;[DIAGRAM: Sockets]&lt;/p&gt;
&lt;h2&gt;&lt;a id="API" name="API"&gt;&lt;/a&gt;API&lt;/h2&gt;
&lt;p&gt;The server-side API exists as a set of interfaces implementable by [[Plugins|plugins]].&lt;/p&gt;
&lt;h3&gt;&lt;a id="ISocket_Plugin" name="ISocket_Plugin"&gt;&lt;/a&gt;&lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket Plugin&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A socket is defined by a [[Plugins|plugin]] which implements the &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; interface. A single socket plugin represents a single channel of communication between the server and browser. For example, a socket plugin may represent all functionality related to sending and receiving realtime chat messages. A single socket plugin can send and receive arbitrary messages and optional data with those messages, but can only send or receive messages sent by or to the same socket plugin.&lt;/p&gt;
&lt;p&gt;Socket plugins are injected with instances of &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt; exposes an instance of an &lt;a href="/developers/w/developer90/50149.iclientscontroller-plugin-supplementary-type"&gt;IClientsController&lt;/a&gt; which contains events for when a user connects, disconnects, or sends a message. The &lt;a href="/developers/w/developer90/50149.iclientscontroller-plugin-supplementary-type"&gt;IClientsController&lt;/a&gt; also supports sending messages to a user or broadcasting to all users.&lt;/p&gt;
&lt;p&gt;Each enabled socket plugin yields a corresponding client-side API.&lt;/p&gt;
&lt;p&gt;Socket plugins will often also implement the &lt;a href="/developers/w/developer90/50286.ihtmlheaderextension-plugin-type"&gt;IHtmlHeaderExtension&lt;/a&gt; interface to register JavaScript which handles or sends socket messages along with custom logic required by the plugin.&lt;/p&gt;
&lt;h3&gt;&lt;a id="ISocketMessageBus_Plugin" name="ISocketMessageBus_Plugin"&gt;&lt;/a&gt;&lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus Plugin&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Multiple-application instance scale-out is achieved through usage of plugins which implement the &lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus&lt;/a&gt; interface. Verint&amp;nbsp;Community bundles a default implementation, but supports integrating with other message busses as well. For details, see the discussion on Scale-Out.&lt;/p&gt;
&lt;h3&gt;&lt;a id="Client-Side" name="Client-Side"&gt;&lt;/a&gt;Client-Side&lt;/h3&gt;
&lt;h4&gt;&lt;a id="Socket_Endpoints" name="Socket_Endpoints"&gt;&lt;/a&gt;Socket Endpoints&lt;/h4&gt;
&lt;p&gt;Each &lt;code&gt;ISocket&lt;/code&gt; plugin implements a &lt;code&gt;SocketName&lt;/code&gt;. This one-word string becomes the name of the client-side API. For example, given the socket:&lt;/p&gt;
&lt;pre class="brush: csharp"&gt;public class MySocket : ISocket
{
    // ...

    string SocketName { get { return &amp;quot;mySocket&amp;quot;; } }

    // ...
}&lt;/pre&gt;
&lt;p&gt;Then the following JavaScript API will be automatically exposed:&lt;/p&gt;
&lt;pre class="brush: javascript"&gt;// receive and handle a message with optional data from the server
$.telligent.evolution.sockets.mySocket.on(messageName, function(data) {
   // handle
});

// send data to the server an optional object message
$.telligent.evolution.sockets.mySocket.send(messageName, data);&lt;/pre&gt;
&lt;h4&gt;&lt;a id="Initiation" name="Initiation"&gt;&lt;/a&gt;Initiation&lt;/h4&gt;
&lt;p&gt;Before attempting to send or receive messages from the client side, the Socket Framework must initiate itself. This happens automatically, and when complete, it publishes a &lt;a href="/developers/w/developer90/50006.socket-connected-client-message"&gt;socket.connected&lt;/a&gt; &lt;a href="/developers/w/developer90/50024.messaging-javascript-api-module"&gt;client-side message&lt;/a&gt;.&lt;/p&gt;
&lt;pre class="brush: javascript"&gt;$.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
    // set up message listeners or send messages
});&lt;/pre&gt;
&lt;h2&gt;&lt;a id="Example_Socket" name="Example_Socket"&gt;&lt;/a&gt;Example Socket&lt;/h2&gt;
&lt;p&gt;The following shows a basic example of a socket which routes greetings from one user to another. A user provides the user name of another community member, clicks &amp;#39;greet&amp;#39;, and an alert is displayed to the other user.&lt;/p&gt;
&lt;p&gt;Greetings are initiated from a user via a widget, sent via the client-side socket API to the &lt;code&gt;ISocket&lt;/code&gt; plugin, and then delivered to the recipient user where the same widget instance for the other user will display the message in a JavaScript &lt;code&gt;alert()&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;&lt;a id="Server_Side" name="Server_Side"&gt;&lt;/a&gt;Server Side&lt;/h3&gt;
&lt;p&gt;Create a new [[Plugins|plugin]] which implements the &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; interface. Its &lt;code&gt;Name&lt;/code&gt;, &lt;code&gt;Description&lt;/code&gt;, and &lt;code&gt;Initialize()&lt;/code&gt; are unimportant. For &lt;code&gt;SocketName&lt;/code&gt; and &lt;code&gt;SetController()&lt;/code&gt;, use the following:&lt;/p&gt;
&lt;pre class="brush: csharp"&gt;public string SocketName
{
    get { return &amp;quot;greeter&amp;quot;; }
}

public void SetController(ISocketController controller)
{
    controller.Clients.Received += (sender, e) =&amp;gt;
    {
        // if this was a greting message, let&amp;#39;s process it
        if (e.MessageName == &amp;quot;greet&amp;quot;)
        {
            // get the associated recipient user
            // data passed from the client side is available on the dynamic MessageData object
            var to = PublicApi.Users.Get(new UsersGetOptions { Username = (string)e.MessageData.Recipient });

            // get the sender user
            var from = PublicApi.Users.Get(new UsersGetOptions { Id = e.UserId });

            // send a new message to the recipient
            controller.Clients.Send(to.Id.GetValueOrDefault(), &amp;quot;greet&amp;quot;, new
            {
                Message = String.Format(&amp;quot;Hello {0}, from {1}&amp;quot;, to.DisplayName, from.DisplayName)
            });
        }
    };
}&lt;/pre&gt;
&lt;h3&gt;&lt;a id="Client_Side" name="Client_Side"&gt;&lt;/a&gt;Client Side&lt;/h3&gt;
&lt;p&gt;Create a new Studio Widget with content:&lt;/p&gt;
&lt;pre class="brush: javascript"&gt;## set up some unique ids for interface elements
#set($recipientInputId = $core_v2_widget.UniqueId(&amp;#39;recipient&amp;#39;))
#set($sendLinkId = $core_v2_widget.UniqueId(&amp;#39;greet&amp;#39;))

## basic interface
&amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;$recipientInputId&amp;quot; /&amp;gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;$sendLinkId&amp;quot;&amp;gt;Greet&amp;lt;/a&amp;gt;

&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
// Wait for socket to be connected
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {

    // when &amp;#39;Greet&amp;#39; is clicked, send a message to be delivered to the recipient
    jQuery(&amp;#39;#$sendLinkId&amp;#39;).on(&amp;#39;click&amp;#39;, function(e) {
        e.preventDefault();

        jQuery.telligent.evolution.sockets.greeter.send(&amp;#39;greet&amp;#39;, {
            Recipient: jQuery(&amp;#39;#$recipientInputId&amp;#39;).val()
        });
    });

    // when a &amp;#39;greet&amp;#39; message is received from the socket, display it as an alert
    jQuery.telligent.evolution.sockets.greeter.on(&amp;#39;greet&amp;#39;, function(data){
        alert(data.Message);
    });
});
&amp;lt;/script&amp;gt;&lt;/pre&gt;
&lt;p&gt;Note use of the &lt;a href="/developers/w/developer90/50006.socket-connected-client-message"&gt;socket.connected&lt;/a&gt; &lt;a href="/developers/w/developer90/50024.messaging-javascript-api-module"&gt;client-side message&lt;/a&gt; as well as the automatically-generated &lt;code&gt;jQuery.telligent.evolution.sockets.testSocket&lt;/code&gt; API.&lt;/p&gt;
&lt;p&gt;The result is a simple UI that enables sending a greeting to another user by their user name.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter.png"&gt;&lt;img style="border:1px solid #DDD;width:264px;" alt=" " src="/resized-image/__size/640x480/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter_2D00_greeted.png"&gt;&lt;img style="border:1px solid #DDD;width:485px;" alt=" " src="/resized-image/__size/640x480/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter_2D00_greeted.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a id="Download" name="Download"&gt;&lt;/a&gt;Download&lt;/h3&gt;
&lt;p&gt;The complete sample can be downloaded:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/1680_2E00_SocketSample_2E00_cs"&gt;community.telligent.com/.../1680_2E00_SocketSample_2E00_cs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/5314.GreeterUI_2D00_Widget.xml"&gt;community.telligent.com/.../5314.GreeterUI_2D00_Widget.xml&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a id="Scale-out" name="Scale-out"&gt;&lt;/a&gt;Scale-out&lt;/h2&gt;
&lt;h3&gt;&lt;a id="Overview" name="Overview"&gt;&lt;/a&gt;Overview&lt;/h3&gt;
&lt;p&gt;The socket message bus is used both internally by the Socket Framework to push messages to multiple application instances when sending messages as well as exposed as a generic message bus for &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; plugins to consume through the injected &lt;a href="/developers/w/developer90/50167.imessagebuscontroller-plugin-supplementary-type"&gt;IMessageBusController&lt;/a&gt; instance.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;When only a single application instance is needed, the Socket Message Bus uses an internal memory-only bus. When multiple application instances are needed, the in-memory bus cannot be used. Instead a [[Plugins|Plugins]] which implements &lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus&lt;/a&gt; must be enabled.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a id="Socket_Message_Bus_Server" name="Socket_Message_Bus_Server"&gt;&lt;/a&gt;Socket Message Bus Server&lt;/h3&gt;
&lt;p&gt;Verint&amp;nbsp;Community 7.5 comes with the optionally-installed Socket Message Bus Windows Service and its corresponding &lt;code&gt;ISocketMessageBus&lt;/code&gt; plugin-based connector, &lt;em&gt;Socket Message Bus Service Connector&lt;/em&gt;. This is simply a Windows Service which echoes messages it receives to all connected Verint&amp;nbsp;Community instances.&lt;/p&gt;
&lt;h3&gt;&lt;a id="Custom_Message_Bus" name="Custom_Message_Bus"&gt;&lt;/a&gt;Custom Message Bus&lt;/h3&gt;
&lt;p&gt;In cases where a community would prefer to use an existing third party message bus solution, custom &lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus plugins&lt;/a&gt; can be written against it and deployed. An example could be a message bus service which supports multiple Verint&amp;nbsp;Community communities on a single bus server by potentially adding an identifier to the string messages sent and received by the plugin for routing the message on the bus server.&lt;/p&gt;
&lt;h3&gt;&lt;a id="Generic_Messages" name="Generic_Messages"&gt;&lt;/a&gt;Generic Messages&lt;/h3&gt;
&lt;p&gt;Custom logic in &lt;code&gt;ISocket&lt;/code&gt; plugins can also make use of the message bus. Generic messages can be useful for keeping realtime state synchronized across application instances. For example, chat presence may be persisted in a database, but cached locally in multiple instances. Since it is important that these caches remain synchronized, presence change messages can be sent and received across the message bus for other app instances&amp;#39; plugins to handle and process.&lt;/p&gt;
&lt;p&gt;The &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt; injected into &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; plugins contains an instance of an &lt;a href="/developers/w/developer90/50167.imessagebuscontroller-plugin-supplementary-type"&gt;IMessageBusController&lt;/a&gt;. The &lt;a href="/developers/w/developer90/50167.imessagebuscontroller-plugin-supplementary-type"&gt;IMessageBusController&lt;/a&gt; exposes events for when generic messages are received from instances of the application along with a method for sending them.&lt;/p&gt;
&lt;p&gt;A useful pattern for state change is to send a generic message to the bus, and only handle it once it is re-received. This allows all instances to know about the state. Additionally, the instance that sends it receives the message immediately without having to wait for the round-trip, and is made aware of the local origin of the message. In this manner, the sender can also be exclusively responsible for potentially persisting the state change elsewhere.&lt;/p&gt;
&lt;pre class="brush: javascript"&gt;controller.MessageBus.Publish(&amp;quot;something.happened&amp;quot;,&amp;quot;&amp;quot;);
controller.MessageBus.Received += (sender, e) =&amp;gt;
{
    if (e.MessageName == &amp;quot;something.happened&amp;quot;)
    {
        // update some local caches
        // ...
        if (e.Source == BusMessageSource.Local)
        {
            // update DB
            // ...
        }
    }
};&lt;/pre&gt;
&lt;h2&gt;&lt;a id="Presence_Services" name="Presence_Services"&gt;&lt;/a&gt;Presence Services&lt;/h2&gt;
&lt;h3&gt;&lt;a id="User_Presence" name="User_Presence"&gt;&lt;/a&gt;User Presence&lt;/h3&gt;
&lt;p&gt;The User Presence service tracks which users are online. &amp;nbsp;The service is responsible for the presence indicator often&amp;nbsp;displayed along side the user&amp;#39;s name. &amp;nbsp;In conjunction with the Content Presence service (discussed below), the service sends socket messages as users go offline and online to update the presence indicators in near real-time for users who are currently viewing&amp;nbsp;the user whose online status has changed.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence.png"&gt;&lt;img alt=" " src="/resized-image/__size/320x240/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The platform has the options for&amp;nbsp;&lt;strong&gt;Enable Presence Tracking&lt;/strong&gt;,&amp;nbsp;&lt;strong&gt;Allow Members To Toggle Presence Tracking Enablement &lt;/strong&gt;and&lt;strong&gt; Default Presence Tracking Enablement Value &amp;nbsp;&lt;/strong&gt;available under Membership in the Membership Options panel in Administration. &amp;nbsp;&lt;strong&gt;Enable Presence Tracking&amp;nbsp;&lt;/strong&gt;controls whether user presence tracking is available for the community. &amp;nbsp;If tracking is enabled, &amp;nbsp;&lt;strong&gt;Allow Members To Toggle Presence Tracking Enablement&lt;/strong&gt; controls whether or not each user should have the option to disable tracking of their online status. If that option is enabled the&amp;nbsp;&lt;strong&gt;Default Presence Tracking Enablement Value&amp;nbsp;&lt;/strong&gt;is also available. &amp;nbsp;If users are giving the option to control their presence tracking, the&amp;nbsp;&lt;strong&gt;Enable presence tracking&lt;/strong&gt; option will be available in the membership settings.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence-admin.png"&gt;&lt;img alt=" " src="/resized-image/__size/550x539/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence-admin.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a id="Content_Presence" name="Content_Presence"&gt;&lt;/a&gt;Content Presence&lt;/h3&gt;
&lt;p&gt;The Content Presence service tracks which content users are currently viewing. &amp;nbsp;This enables the platform to update users in real time to changes in content they are currently viewing. &amp;nbsp;The API provides a quantity of users who are currently viewing each content item.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;How is content presence determined?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Page Context: The service uses the page content to track what content the using is currently viewing. &amp;nbsp;For instance if a user is currently viewing a blog post, the content service would be aware that user is currently viewing that blog post, its author, the blog the post belonged to and the group the blog belonged to. &amp;nbsp;&lt;/li&gt;
&lt;li&gt;Html attributes: Html attributes can be added to through the &lt;code&gt;core_v2_contentPresence.RenderAttributes&lt;/code&gt; method. &amp;nbsp;This method will render the proper attributes to automatically track a user&amp;#39;s content presence, when the decorated element is currently visible on the page they are viewing. &amp;nbsp;The comment stream and activity stream are two examples where this method is in use.&lt;/li&gt;
&lt;li&gt;APIs: &amp;nbsp;In Process, Rest and Widget APIs are available to directly add and remove which content a user is present for. &amp;nbsp;Additionally, a summary of the quantity of users viewing each content item is available.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a id="Service_Presence" name="Service_Presence"&gt;&lt;/a&gt;Service Presence&lt;/h3&gt;
&lt;p&gt;The Service Presence service tracks what services a user is currently viewing. &amp;nbsp;When a user is present for a service, messages about changes in that service can be sent to the user&amp;#39;s browser so that browser can be updated to show the latest changes. &amp;nbsp;The activity story service is an example of how this service is used. &amp;nbsp;When an activity story is created, deleted or updated any user that is present to the activity story service will&amp;nbsp;be see that updated of that change and their activity story stream can be updated as needed.&lt;/p&gt;
&lt;p&gt;How do you define a Service Presence service?&lt;/p&gt;
&lt;p&gt;Widgets can define themselves as services, using the&lt;code&gt;&amp;nbsp;core_v2_servicePresence.RenderAttributes&lt;/code&gt; method and passing a unique service identifier. &amp;nbsp;For instance, the activity stream widget can define itself as a service, doing allows users who are currently viewing an activity stream to receive socket messages for new activity stories. &amp;nbsp;Using the Content Presence service alone, would only allow users to receive socket messages to for content that already exists in the activity stream.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;How is service presence determined?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Html attributes: Html attributes can be added to through the &lt;code&gt;core_v2_servicePresence.RenderAttributes&lt;/code&gt; method. &amp;nbsp;This method will render the proper attributes to automatically track a user&amp;#39;s presence to a service, when the decorated element is currently visible on the page they are viewing.&lt;/li&gt;
&lt;li&gt;APIs: &amp;nbsp;In Process, Rest and Widget APIs are available to directly add and remove which service a user is present for. &amp;nbsp;Additionally listing which users are currently present to a service&amp;nbsp;is available in the same APIs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Combining the Content and Service Presence Services with Sockets creates new opportunities to&amp;nbsp;enhance community functionality. &amp;nbsp;The new Live Comment and Thread Forums are two features that make use of the Socket Bus and the Presence Services.&lt;/p&gt;
&lt;h2&gt;&lt;a id="Example_Socket_using_Content_Presence_Service" name="Example_Socket_using_Content_Presence_Service"&gt;&lt;/a&gt;Example Socket using Content Presence Service&lt;/h2&gt;
&lt;p&gt;This example will&amp;nbsp;create an &lt;code&gt;ISocket&lt;/code&gt; implementation that will send socket messages to users when a vote is received or changed on an idea. &amp;nbsp;By combining the socket implementation with the content presence service, the socket messages can be sent only to those users who are currently viewing the idea that received the vote.&lt;/p&gt;
&lt;h3&gt;&lt;a id="Server_Side" name="Server_Side"&gt;&lt;/a&gt;Server Side&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;ISocket&lt;/code&gt; implementation will use the &lt;em&gt;ideavotes&lt;/em&gt; for the &lt;code&gt;SocketName &lt;/code&gt;and maintain a reference to the &lt;code&gt;SocketController&lt;/code&gt; for later use in our example.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;ISocketController _sockets;
public string SocketName =&amp;gt; &amp;quot;ideavotes&amp;quot;;

public void SetController(ISocketController controller)
{
    _sockets = controller;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The example class will need to send a message whenever an idea is&amp;nbsp;voted on, this can be accomplished by attaching to the Idea Vote Events for these actions in our plugin&amp;#39;s &lt;code&gt;Initialize&lt;/code&gt; method. &amp;nbsp;In each event handler, we will call the same method SendVoteCounts passing the idea id for the vote.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public void Initialize()
{
    _ideas = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IIdeas&amp;gt;();

    _ideaVotes = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IVotes&amp;gt;();
    _ideaVotes.Events.AfterCreate += VoteCreated;
    _ideaVotes.Events.AfterDelete += VoteDeleted;
    _ideaVotes.Events.AfterUpdate += VoteUpdated;
}

private void VoteCreated(VoteAfterCreateEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}

private void VoteUpdated(VoteAfterUpdateEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}

private void VoteDeleted(VoteAfterDeleteEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;In the SendVoteCounts method, the number of up and down votes will be retrieved and the&amp;nbsp;&lt;code&gt;_sockets.Clients.SendToUsersPresentToContent &lt;/code&gt;method will be used to send a message to all users who are currently present to that idea.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;void SendVoteCounts(Guid ideaId)
{
    var idea = _ideas.Get(ideaId);
    if (idea != null &amp;amp;&amp;amp; !idea.HasErrors())
    {
        var upVotes =
            _ideaVotes.List(new VotesListOptions() {IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = true });

        var downVotes =
            _ideaVotes.List(new VotesListOptions() { IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = false });

        // send socket message with updated totals
        _sockets.Clients.SendToUsersPresentToContent(idea.ContentId, &amp;quot;ideavoted&amp;quot;, new
        {
            contentId = idea.ContentId,
            contentTypeId = _ideas.ContentTypeId,
            yesVotes = upVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;,
            noVotes = downVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;
        });
    }
}&lt;/pre&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a id="Client_Side" name="Client_Side"&gt;&lt;/a&gt;Client Side&lt;/h3&gt;
&lt;p&gt;Once this plugin is compiled and enabled on the community site, each time an idea is voted on any user who is viewing that idea will receive an &lt;em&gt;ideavoted&amp;nbsp;&lt;/em&gt;socket message. &amp;nbsp;For this example, we can use a widget to see these messages. &amp;nbsp;The example will&amp;nbsp;make use of the&amp;nbsp;&lt;code&gt;$.telligent.evolution.sockets.ideavotes&lt;/code&gt; API that is automatically generated for our &lt;code&gt;ISocket&lt;/code&gt; implementation. &amp;nbsp;That API will enable the widget to listen for messages from the custom socket. &amp;nbsp;In this case, the message&amp;#39;s data will output to the browser&amp;#39;s console window.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="javascript"&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
	jQuery.telligent.evolution.sockets.ideavotes.on(&amp;#39;ideavoted&amp;#39;, function(data) {
		console.log(data);
	});
});
&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The widget can be placed on the Idea page or Idea List page,&amp;nbsp;you will be able to see the messages for the ideas you are currently viewing when any vote is received on the idea(s) you are currently viewing.&lt;/p&gt;
&lt;h3&gt;&lt;a id="Completed_Sample" name="Completed_Sample"&gt;&lt;/a&gt;Completed Sample&lt;/h3&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;using System;
using Telligent.Evolution.Extensibility.Ideation.Api;
using Telligent.Evolution.Extensibility.Sockets.Version1;
using Telligent.Evolution.Extensibility.Version1;

namespace Telligent.Evolution.Examples
{
    public class VoteSocket : IPlugin, ISocket
    {
        ISocketController _sockets;
        IIdeas _ideas;
        IVotes _ideaVotes;

        public string Name =&amp;gt; &amp;quot;Idea Vote Sockets&amp;quot;;
        public string Description =&amp;gt; &amp;quot;Enables live updates to idea votes.&amp;quot;;
        public string SocketName =&amp;gt; &amp;quot;ideavotes&amp;quot;;

        public void Initialize()
        {
            _ideas = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IIdeas&amp;gt;();

            _ideaVotes = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IVotes&amp;gt;();
            _ideaVotes.Events.AfterCreate += VoteCreated;
            _ideaVotes.Events.AfterDelete += VoteDeleted;
            _ideaVotes.Events.AfterUpdate += VoteUpdated;
        }

        public void SetController(ISocketController controller)
        {
            _sockets = controller;
        }

        private void VoteCreated(VoteAfterCreateEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        private void VoteUpdated(VoteAfterUpdateEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        private void VoteDeleted(VoteAfterDeleteEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        void SendVoteCounts(Guid ideaId)
        {
            var idea = _ideas.Get(ideaId);
            if (idea != null &amp;amp;&amp;amp; !idea.HasErrors())
            {
                var upVotes =
                    _ideaVotes.List(new VotesListOptions() {IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = true });

                var downVotes =
                    _ideaVotes.List(new VotesListOptions() { IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = false });

                // send socket message with updated totals
                _sockets.Clients.SendToUsersPresentToContent(idea.ContentId, &amp;quot;ideavoted&amp;quot;, new
                {
                    contentId = idea.ContentId,
                    contentTypeId = _ideas.ContentTypeId,
                    yesVotes = upVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;,
                    noVotes = downVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;
                });
            }
        }
    }
}
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="xml"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;
&amp;lt;scriptedContentFragments&amp;gt;
  &amp;lt;scriptedContentFragment name=&amp;quot;Idea Socket Presence Test&amp;quot; version=&amp;quot;10.0.0.0&amp;quot; description=&amp;quot;&amp;quot; instanceIdentifier=&amp;quot;c7e0a2c7d2b44ab08f22d8938ef03a06&amp;quot; theme=&amp;quot;&amp;quot; isCacheable=&amp;quot;false&amp;quot; varyCacheByUser=&amp;quot;false&amp;quot; showHeaderByDefault=&amp;quot;false&amp;quot; cssClass=&amp;quot;&amp;quot; provider=&amp;quot;7bb87a0cc5864a9392ae5b9e5f9747b7&amp;quot;&amp;gt;
    &amp;lt;contentScript&amp;gt;&amp;lt;![CDATA[

&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
			jQuery.telligent.evolution.sockets.ideavotes.on(&amp;#39;ideavoted&amp;#39;, function(data) {
				console.log(data);
			});
});
&amp;lt;/script&amp;gt;

]]&amp;gt;&amp;lt;/contentScript&amp;gt;
  &amp;lt;/scriptedContentFragment&amp;gt;
&amp;lt;/scriptedContentFragments&amp;gt;&lt;/pre&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a id="Tips_and_Tricks" name="Tips_and_Tricks"&gt;&lt;/a&gt;Tips and Tricks&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Sockets can only be used by authenticated, non-system users&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Sockets and Presence</title><link>https://community.telligent.com/community/11/w/developer-training/65063/sockets-and-presence/revision/3</link><pubDate>Tue, 20 Aug 2019 15:41:13 GMT</pubDate><guid isPermaLink="false">f141b2d7-5f01-47b0-ab4d-105e12603c36</guid><dc:creator>Michael Monteleone</dc:creator><comments>https://community.telligent.com/community/11/w/developer-training/65063/sockets-and-presence#comments</comments><description>Revision 3 posted to Developer Training by Michael Monteleone on 08/20/2019 15:41:13&lt;br /&gt;
&lt;p&gt;The Socket Framework provides support for &lt;strong&gt;real-time two-way communication between Verint Community and the browser&lt;/strong&gt;. This enables&amp;nbsp;receiving and sending messages directly to specific users or scoped&amp;nbsp;groups of users.&lt;/p&gt;
&lt;p&gt;[toc]&lt;/p&gt;
&lt;h2&gt;&lt;a id="When_would_I_want_to_use_sockets" name="When_would_I_want_to_use_sockets"&gt;&lt;/a&gt;When would I want to use sockets?&lt;/h2&gt;
&lt;p&gt;Sockets are useful when you need to push messages from the server to the browser. An easy example to consider is a notification popup that is pushed to a user in the event of an action occurring on the server. Sockets are the mechanism through which built-in platform features including notifications, chat, live activity streams, forum threads, comment threads,&amp;nbsp;theme previews, presence indicators, tracing, and more communicate with the browser.&lt;/p&gt;
&lt;h2&gt;&lt;a id="Overview" name="Overview"&gt;&lt;/a&gt;Overview&lt;/h2&gt;
&lt;p&gt;Built on top of &lt;a href="http://signalr.net/"&gt;SignalR&lt;/a&gt;, the Socket Framework inherits all of SignalR&amp;#39;s performance, stability, and diversity of browser support over underlying WebSocket, server-sent event, or&amp;nbsp;long polling transports. Because it is Verint&amp;nbsp;Community-specific, the Socket Framework can provide:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;[[Plugins|Plugin]] based extensibility&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Both built-in and third-party [[Plugins|plugin]] can implement their own &lt;em&gt;sockets&lt;/em&gt; which each define a pair of server and client methods and events for bi-directional communication, all multiplexed over a single&amp;nbsp;underlying connection to the server.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Presence&lt;/strong&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Users&amp;#39; site presence as well as their presence to individual pieces of content regardless of how and where that content is presented&amp;nbsp;is&amp;nbsp;tracked&amp;nbsp;to enable&amp;nbsp;delivery of messages scoped only to&amp;nbsp;users viewing&amp;nbsp;specific&amp;nbsp;content. Additionally, Service Presence supports a similar, but non-content-based scoping of messages.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scale-out and reliability&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;All sockets are multiplexed over a single connection between&amp;nbsp;the server and browser. And the browser shares the same, single, connection across all of its windows and&amp;nbsp;tabs, transparently identifying a single window or tab at a time to function as the connection&amp;#39;s host.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Socket connections are reliably maintained, and reconnect after disconnections with randomized, exponential, retry backoffs.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;To support scale-out to multiple application instances and&amp;nbsp;delivery&amp;nbsp;of socket messages from plugins&amp;nbsp;running outside of web contexts in the job server, Verint&amp;nbsp;Community bundles two&amp;nbsp;possible message bus servers: the Socket Message Bus Service as well as the lower-performing Database Message Bus. Alternatively, Verint&amp;nbsp;Community can use &lt;em&gt;any&lt;/em&gt; message bus service through plugin extensibility. The configuration of which message bus server to use, if any at all, is defined by [[Plugins|plugin]]-based connectors, which can be enabled or disabled through standard plugin management without restarting the application. Socket plugins also expose the underlying message bus for use as a way to keep real-time application state in synchronization across multiple instances.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The socket framework powers &lt;span&gt;notifications, chat, live activity streams, forum threads, comment threads,&amp;nbsp;theme previews, presence indicators, tracing, and more&lt;/span&gt; in Community. Socket plugins can&amp;nbsp;be developed to easily power other functionality like real-time whiteboards, analytics, or even games.&lt;/p&gt;
&lt;p&gt;[DIAGRAM: Sockets]&lt;/p&gt;
&lt;h2&gt;&lt;a id="API" name="API"&gt;&lt;/a&gt;API&lt;/h2&gt;
&lt;p&gt;The API exists as a set of interfaces implementable by [[Plugins|plugins]].&lt;/p&gt;
&lt;h3&gt;&lt;a id="ISocket_Plugin" name="ISocket_Plugin"&gt;&lt;/a&gt;&lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket Plugin&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A socket is defined by a [[Plugins|plugin]] which implements the &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; interface. A single socket plugin represents a single channel of communication between the server and browser. For example, a socket plugin may represent all functionality related to sending and receiving realtime chat messages. A single socket plugin can send and receive arbitrary messages and optional data with those messages, but can only send or receive messages sent by or to the same socket plugin.&lt;/p&gt;
&lt;p&gt;Socket plugins are injected with instances of &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt; exposes an instance of an &lt;a href="/developers/w/developer90/50149.iclientscontroller-plugin-supplementary-type"&gt;IClientsController&lt;/a&gt; which contains events for when a user connects, disconnects, or sends a message. The &lt;a href="/developers/w/developer90/50149.iclientscontroller-plugin-supplementary-type"&gt;IClientsController&lt;/a&gt; also supports sending messages to a user or broadcasting to all users.&lt;/p&gt;
&lt;p&gt;Each enabled socket plugin yields a corresponding client-side API.&lt;/p&gt;
&lt;p&gt;Socket plugins will often also implement the &lt;a href="/developers/w/developer90/50286.ihtmlheaderextension-plugin-type"&gt;IHtmlHeaderExtension&lt;/a&gt; interface to register JavaScript which handles or sends socket messages along with custom logic required by the plugin.&lt;/p&gt;
&lt;h3&gt;&lt;a id="ISocketMessageBus_Plugin" name="ISocketMessageBus_Plugin"&gt;&lt;/a&gt;&lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus Plugin&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Multiple-application instance scale-out is achieved through usage of plugins which implement the &lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus&lt;/a&gt; interface. Verint&amp;nbsp;Community bundles a default implementation, but supports integrating with other message busses as well. For details, see the discussion on Scale-Out.&lt;/p&gt;
&lt;h3&gt;&lt;a id="Client-Side" name="Client-Side"&gt;&lt;/a&gt;Client-Side&lt;/h3&gt;
&lt;h4&gt;&lt;a id="Socket_Endpoints" name="Socket_Endpoints"&gt;&lt;/a&gt;Socket Endpoints&lt;/h4&gt;
&lt;p&gt;Each &lt;code&gt;ISocket&lt;/code&gt; plugin implements a &lt;code&gt;SocketName&lt;/code&gt;. This one-word string becomes the name of the client-side API. For example, given the socket:&lt;/p&gt;
&lt;pre class="brush: csharp"&gt;public class MySocket : ISocket
{
    // ...

    string SocketName { get { return &amp;quot;mySocket&amp;quot;; } }

    // ...
}&lt;/pre&gt;
&lt;p&gt;Then the following JavaScript API will be automatically exposed:&lt;/p&gt;
&lt;pre class="brush: javascript"&gt;// receive and handle a message with optional data from the server
$.telligent.evolution.sockets.mySocket.on(messageName, function(data) {
   // handle
});

// send data to the server an optional object message
$.telligent.evolution.sockets.mySocket.send(messageName, data);&lt;/pre&gt;
&lt;h4&gt;&lt;a id="Initiation" name="Initiation"&gt;&lt;/a&gt;Initiation&lt;/h4&gt;
&lt;p&gt;Before attempting to send or receive messages from the client side, the Socket Framework must initiate itself. This happens automatically, and when complete, it publishes a &lt;a href="/developers/w/developer90/50006.socket-connected-client-message"&gt;socket.connected&lt;/a&gt; &lt;a href="/developers/w/developer90/50024.messaging-javascript-api-module"&gt;client-side message&lt;/a&gt;.&lt;/p&gt;
&lt;pre class="brush: javascript"&gt;$.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
    // set up message listeners or send messages
});&lt;/pre&gt;
&lt;h2&gt;&lt;a id="Example_Socket" name="Example_Socket"&gt;&lt;/a&gt;Example Socket&lt;/h2&gt;
&lt;p&gt;The following shows a basic example of a socket which routes greetings from one user to another. A user provides the user name of another community member, clicks &amp;#39;greet&amp;#39;, and an alert is displayed to the other user.&lt;/p&gt;
&lt;p&gt;Greetings are initiated from a user via a widget, sent via the client-side socket API to the &lt;code&gt;ISocket&lt;/code&gt; plugin, and then delivered to the recipient user where the same widget instance for the other user will display the message in a JavaScript &lt;code&gt;alert()&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;&lt;a id="Server_Side" name="Server_Side"&gt;&lt;/a&gt;Server Side&lt;/h3&gt;
&lt;p&gt;Create a new [[Plugins|plugin]] which implements the &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; interface. Its &lt;code&gt;Name&lt;/code&gt;, &lt;code&gt;Description&lt;/code&gt;, and &lt;code&gt;Initialize()&lt;/code&gt; are unimportant. For &lt;code&gt;SocketName&lt;/code&gt; and &lt;code&gt;SetController()&lt;/code&gt;, use the following:&lt;/p&gt;
&lt;pre class="brush: csharp"&gt;public string SocketName
{
    get { return &amp;quot;greeter&amp;quot;; }
}

public void SetController(ISocketController controller)
{
    controller.Clients.Received += (sender, e) =&amp;gt;
    {
        // if this was a greting message, let&amp;#39;s process it
        if (e.MessageName == &amp;quot;greet&amp;quot;)
        {
            // get the associated recipient user
            // data passed from the client side is available on the dynamic MessageData object
            var to = PublicApi.Users.Get(new UsersGetOptions { Username = (string)e.MessageData.Recipient });

            // get the sender user
            var from = PublicApi.Users.Get(new UsersGetOptions { Id = e.UserId });

            // send a new message to the recipient
            controller.Clients.Send(to.Id.GetValueOrDefault(), &amp;quot;greet&amp;quot;, new
            {
                Message = String.Format(&amp;quot;Hello {0}, from {1}&amp;quot;, to.DisplayName, from.DisplayName)
            });
        }
    };
}&lt;/pre&gt;
&lt;h3&gt;&lt;a id="Client_Side" name="Client_Side"&gt;&lt;/a&gt;Client Side&lt;/h3&gt;
&lt;p&gt;Create a new Studio Widget with content:&lt;/p&gt;
&lt;pre class="brush: javascript"&gt;## set up some unique ids for interface elements
#set($recipientInputId = $core_v2_widget.UniqueId(&amp;#39;recipient&amp;#39;))
#set($sendLinkId = $core_v2_widget.UniqueId(&amp;#39;greet&amp;#39;))

## basic interface
&amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;$recipientInputId&amp;quot; /&amp;gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;$sendLinkId&amp;quot;&amp;gt;Greet&amp;lt;/a&amp;gt;

&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
// Wait for socket to be connected
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {

    // when &amp;#39;Greet&amp;#39; is clicked, send a message to be delivered to the recipient
    jQuery(&amp;#39;#$sendLinkId&amp;#39;).on(&amp;#39;click&amp;#39;, function(e) {
        e.preventDefault();

        jQuery.telligent.evolution.sockets.greeter.send(&amp;#39;greet&amp;#39;, {
            Recipient: jQuery(&amp;#39;#$recipientInputId&amp;#39;).val()
        });
    });

    // when a &amp;#39;greet&amp;#39; message is received from the socket, display it as an alert
    jQuery.telligent.evolution.sockets.greeter.on(&amp;#39;greet&amp;#39;, function(data){
        alert(data.Message);
    });
});
&amp;lt;/script&amp;gt;&lt;/pre&gt;
&lt;p&gt;Note use of the &lt;a href="/developers/w/developer90/50006.socket-connected-client-message"&gt;socket.connected&lt;/a&gt; &lt;a href="/developers/w/developer90/50024.messaging-javascript-api-module"&gt;client-side message&lt;/a&gt; as well as the automatically-generated &lt;code&gt;jQuery.telligent.evolution.sockets.testSocket&lt;/code&gt; API.&lt;/p&gt;
&lt;p&gt;The result is a simple UI that enables sending a greeting to another user by their user name.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter.png"&gt;&lt;img style="border:1px solid #DDD;width:264px;" alt=" " src="/resized-image/__size/640x480/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter_2D00_greeted.png"&gt;&lt;img style="border:1px solid #DDD;width:485px;" alt=" " src="/resized-image/__size/640x480/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter_2D00_greeted.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a id="Download" name="Download"&gt;&lt;/a&gt;Download&lt;/h3&gt;
&lt;p&gt;The complete sample can be downloaded:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/1680_2E00_SocketSample_2E00_cs"&gt;community.telligent.com/.../1680_2E00_SocketSample_2E00_cs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/5314.GreeterUI_2D00_Widget.xml"&gt;community.telligent.com/.../5314.GreeterUI_2D00_Widget.xml&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a id="Scale-out" name="Scale-out"&gt;&lt;/a&gt;Scale-out&lt;/h2&gt;
&lt;h3&gt;&lt;a id="Overview" name="Overview"&gt;&lt;/a&gt;Overview&lt;/h3&gt;
&lt;p&gt;The socket message bus is used both internally by the Socket Framework to push messages to multiple application instances when sending messages as well as exposed as a generic message bus for &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; plugins to consume through the injected &lt;a href="/developers/w/developer90/50167.imessagebuscontroller-plugin-supplementary-type"&gt;IMessageBusController&lt;/a&gt; instance.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;When only a single application instance is needed, the Socket Message Bus uses an internal memory-only bus. When multiple application instances are needed, the in-memory bus cannot be used. Instead a [[Plugins|Plugins]] which implements &lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus&lt;/a&gt; must be enabled.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a id="Socket_Message_Bus_Server" name="Socket_Message_Bus_Server"&gt;&lt;/a&gt;Socket Message Bus Server&lt;/h3&gt;
&lt;p&gt;Verint&amp;nbsp;Community 7.5 comes with the optionally-installed Socket Message Bus Windows Service and its corresponding &lt;code&gt;ISocketMessageBus&lt;/code&gt; plugin-based connector, &lt;em&gt;Socket Message Bus Service Connector&lt;/em&gt;. This is simply a Windows Service which echoes messages it receives to all connected Verint&amp;nbsp;Community instances.&lt;/p&gt;
&lt;h3&gt;&lt;a id="Custom_Message_Bus" name="Custom_Message_Bus"&gt;&lt;/a&gt;Custom Message Bus&lt;/h3&gt;
&lt;p&gt;In cases where a community would prefer to use an existing third party message bus solution, custom &lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus plugins&lt;/a&gt; can be written against it and deployed. An example could be a message bus service which supports multiple Verint&amp;nbsp;Community communities on a single bus server by potentially adding an identifier to the string messages sent and received by the plugin for routing the message on the bus server.&lt;/p&gt;
&lt;h3&gt;&lt;a id="Generic_Messages" name="Generic_Messages"&gt;&lt;/a&gt;Generic Messages&lt;/h3&gt;
&lt;p&gt;Custom logic in &lt;code&gt;ISocket&lt;/code&gt; plugins can also make use of the message bus. Generic messages can be useful for keeping realtime state synchronized across application instances. For example, chat presence may be persisted in a database, but cached locally in multiple instances. Since it is important that these caches remain synchronized, presence change messages can be sent and received across the message bus for other app instances&amp;#39; plugins to handle and process.&lt;/p&gt;
&lt;p&gt;The &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt; injected into &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; plugins contains an instance of an &lt;a href="/developers/w/developer90/50167.imessagebuscontroller-plugin-supplementary-type"&gt;IMessageBusController&lt;/a&gt;. The &lt;a href="/developers/w/developer90/50167.imessagebuscontroller-plugin-supplementary-type"&gt;IMessageBusController&lt;/a&gt; exposes events for when generic messages are received from instances of the application along with a method for sending them.&lt;/p&gt;
&lt;p&gt;A useful pattern for state change is to send a generic message to the bus, and only handle it once it is re-received. This allows all instances to know about the state. Additionally, the instance that sends it receives the message immediately without having to wait for the round-trip, and is made aware of the local origin of the message. In this manner, the sender can also be exclusively responsible for potentially persisting the state change elsewhere.&lt;/p&gt;
&lt;pre class="brush: javascript"&gt;controller.MessageBus.Publish(&amp;quot;something.happened&amp;quot;,&amp;quot;&amp;quot;);
controller.MessageBus.Received += (sender, e) =&amp;gt;
{
    if (e.MessageName == &amp;quot;something.happened&amp;quot;)
    {
        // update some local caches
        // ...
        if (e.Source == BusMessageSource.Local)
        {
            // update DB
            // ...
        }
    }
};&lt;/pre&gt;
&lt;h2&gt;&lt;a id="Presence_Services" name="Presence_Services"&gt;&lt;/a&gt;Presence Services&lt;/h2&gt;
&lt;h3&gt;&lt;a id="User_Presence" name="User_Presence"&gt;&lt;/a&gt;User Presence&lt;/h3&gt;
&lt;p&gt;The User Presence service tracks which users are online. &amp;nbsp;The service is responsible for the presence indicator often&amp;nbsp;displayed along side the user&amp;#39;s name. &amp;nbsp;In conjunction with the Content Presence service (discussed below), the service sends socket messages as users go offline and online to update the presence indicators in near real-time for users who are currently viewing&amp;nbsp;the user whose online status has changed.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence.png"&gt;&lt;img alt=" " src="/resized-image/__size/320x240/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The platform has the options for&amp;nbsp;&lt;strong&gt;Enable Presence Tracking&lt;/strong&gt;,&amp;nbsp;&lt;strong&gt;Allow Members To Toggle Presence Tracking Enablement &lt;/strong&gt;and&lt;strong&gt; Default Presence Tracking Enablement Value &amp;nbsp;&lt;/strong&gt;available under Membership in the Membership Options panel in Administration. &amp;nbsp;&lt;strong&gt;Enable Presence Tracking&amp;nbsp;&lt;/strong&gt;controls whether user presence tracking is available for the community. &amp;nbsp;If tracking is enabled, &amp;nbsp;&lt;strong&gt;Allow Members To Toggle Presence Tracking Enablement&lt;/strong&gt; controls whether or not each user should have the option to disable tracking of their online status. If that option is enabled the&amp;nbsp;&lt;strong&gt;Default Presence Tracking Enablement Value&amp;nbsp;&lt;/strong&gt;is also available. &amp;nbsp;If users are giving the option to control their presence tracking, the&amp;nbsp;&lt;strong&gt;Enable presence tracking&lt;/strong&gt; option will be available in the membership settings.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence-admin.png"&gt;&lt;img alt=" " src="/resized-image/__size/550x539/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence-admin.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a id="Content_Presence" name="Content_Presence"&gt;&lt;/a&gt;Content Presence&lt;/h3&gt;
&lt;p&gt;The Content Presence service tracks which content users are currently viewing. &amp;nbsp;This enables the platform to update users in real time to changes in content they are currently viewing. &amp;nbsp;The API provides a quantity of users who are currently viewing each content item.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;How is content presence determined?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Page Context: The service uses the page content to track what content the using is currently viewing. &amp;nbsp;For instance if a user is currently viewing a blog post, the content service would be aware that user is currently viewing that blog post, its author, the blog the post belonged to and the group the blog belonged to. &amp;nbsp;&lt;/li&gt;
&lt;li&gt;Html attributes: Html attributes can be added to through the &lt;code&gt;core_v2_contentPresence.RenderAttributes&lt;/code&gt; method. &amp;nbsp;This method will render the proper attributes to automatically track a user&amp;#39;s content presence, when the decorated element is currently visible on the page they are viewing. &amp;nbsp;The comment stream and activity stream are two examples where this method is in use.&lt;/li&gt;
&lt;li&gt;APIs: &amp;nbsp;In Process, Rest and Widget APIs are available to directly add and remove which content a user is present for. &amp;nbsp;Additionally, a summary of the quantity of users viewing each content item is available.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a id="Service_Presence" name="Service_Presence"&gt;&lt;/a&gt;Service Presence&lt;/h3&gt;
&lt;p&gt;The Service Presence service tracks what services a user is currently viewing. &amp;nbsp;When a user is present for a service, messages about changes in that service can be sent to the user&amp;#39;s browser so that browser can be updated to show the latest changes. &amp;nbsp;The activity story service is an example of how this service is used. &amp;nbsp;When an activity story is created, deleted or updated any user that is present to the activity story service will&amp;nbsp;be see that updated of that change and their activity story stream can be updated as needed.&lt;/p&gt;
&lt;p&gt;How do you define a Service Presence service?&lt;/p&gt;
&lt;p&gt;Widgets can define themselves as services, using the&lt;code&gt;&amp;nbsp;core_v2_servicePresence.RenderAttributes&lt;/code&gt; method and passing a unique service identifier. &amp;nbsp;For instance, the activity stream widget can define itself as a service, doing allows users who are currently viewing an activity stream to receive socket messages for new activity stories. &amp;nbsp;Using the Content Presence service alone, would only allow users to receive socket messages to for content that already exists in the activity stream.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;How is service presence determined?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Html attributes: Html attributes can be added to through the &lt;code&gt;core_v2_servicePresence.RenderAttributes&lt;/code&gt; method. &amp;nbsp;This method will render the proper attributes to automatically track a user&amp;#39;s presence to a service, when the decorated element is currently visible on the page they are viewing.&lt;/li&gt;
&lt;li&gt;APIs: &amp;nbsp;In Process, Rest and Widget APIs are available to directly add and remove which service a user is present for. &amp;nbsp;Additionally listing which users are currently present to a service&amp;nbsp;is available in the same APIs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Combining the Content and Service Presence Services with Sockets creates new opportunities to&amp;nbsp;enhance community functionality. &amp;nbsp;The new Live Comment and Thread Forums are two features that make use of the Socket Bus and the Presence Services.&lt;/p&gt;
&lt;h2&gt;&lt;a id="Example_Socket_using_Content_Presence_Service" name="Example_Socket_using_Content_Presence_Service"&gt;&lt;/a&gt;Example Socket using Content Presence Service&lt;/h2&gt;
&lt;p&gt;This example will&amp;nbsp;create an &lt;code&gt;ISocket&lt;/code&gt; implementation that will send socket messages to users when a vote is received or changed on an idea. &amp;nbsp;By combining the socket implementation with the content presence service, the socket messages can be sent only to those users who are currently viewing the idea that received the vote.&lt;/p&gt;
&lt;h3&gt;&lt;a id="Server_Side" name="Server_Side"&gt;&lt;/a&gt;Server Side&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;ISocket&lt;/code&gt; implementation will use the &lt;em&gt;ideavotes&lt;/em&gt; for the &lt;code&gt;SocketName &lt;/code&gt;and maintain a reference to the &lt;code&gt;SocketController&lt;/code&gt; for later use in our example.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;ISocketController _sockets;
public string SocketName =&amp;gt; &amp;quot;ideavotes&amp;quot;;

public void SetController(ISocketController controller)
{
    _sockets = controller;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The example class will need to send a message whenever an idea is&amp;nbsp;voted on, this can be accomplished by attaching to the Idea Vote Events for these actions in our plugin&amp;#39;s &lt;code&gt;Initialize&lt;/code&gt; method. &amp;nbsp;In each event handler, we will call the same method SendVoteCounts passing the idea id for the vote.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public void Initialize()
{
    _ideas = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IIdeas&amp;gt;();

    _ideaVotes = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IVotes&amp;gt;();
    _ideaVotes.Events.AfterCreate += VoteCreated;
    _ideaVotes.Events.AfterDelete += VoteDeleted;
    _ideaVotes.Events.AfterUpdate += VoteUpdated;
}

private void VoteCreated(VoteAfterCreateEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}

private void VoteUpdated(VoteAfterUpdateEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}

private void VoteDeleted(VoteAfterDeleteEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;In the SendVoteCounts method, the number of up and down votes will be retrieved and the&amp;nbsp;&lt;code&gt;_sockets.Clients.SendToUsersPresentToContent &lt;/code&gt;method will be used to send a message to all users who are currently present to that idea.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;void SendVoteCounts(Guid ideaId)
{
    var idea = _ideas.Get(ideaId);
    if (idea != null &amp;amp;&amp;amp; !idea.HasErrors())
    {
        var upVotes =
            _ideaVotes.List(new VotesListOptions() {IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = true });

        var downVotes =
            _ideaVotes.List(new VotesListOptions() { IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = false });

        // send socket message with updated totals
        _sockets.Clients.SendToUsersPresentToContent(idea.ContentId, &amp;quot;ideavoted&amp;quot;, new
        {
            contentId = idea.ContentId,
            contentTypeId = _ideas.ContentTypeId,
            yesVotes = upVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;,
            noVotes = downVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;
        });
    }
}&lt;/pre&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a id="Client_Side" name="Client_Side"&gt;&lt;/a&gt;Client Side&lt;/h3&gt;
&lt;p&gt;Once this plugin is compiled and enabled on the community site, each time an idea is voted on any user who is viewing that idea will receive an &lt;em&gt;ideavoted&amp;nbsp;&lt;/em&gt;socket message. &amp;nbsp;For this example, we can use a widget to see these messages. &amp;nbsp;The example will&amp;nbsp;make use of the&amp;nbsp;&lt;code&gt;$.telligent.evolution.sockets.ideavotes&lt;/code&gt; API that is automatically generated for our &lt;code&gt;ISocket&lt;/code&gt; implementation. &amp;nbsp;That API will enable the widget to listen for messages from the custom socket. &amp;nbsp;In this case, the message&amp;#39;s data will output to the browser&amp;#39;s console window.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="javascript"&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
	jQuery.telligent.evolution.sockets.ideavotes.on(&amp;#39;ideavoted&amp;#39;, function(data) {
		console.log(data);
	});
});
&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The widget can be placed on the Idea page or Idea List page,&amp;nbsp;you will be able to see the messages for the ideas you are currently viewing when any vote is received on the idea(s) you are currently viewing.&lt;/p&gt;
&lt;h3&gt;&lt;a id="Completed_Sample" name="Completed_Sample"&gt;&lt;/a&gt;Completed Sample&lt;/h3&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;using System;
using Telligent.Evolution.Extensibility.Ideation.Api;
using Telligent.Evolution.Extensibility.Sockets.Version1;
using Telligent.Evolution.Extensibility.Version1;

namespace Telligent.Evolution.Examples
{
    public class VoteSocket : IPlugin, ISocket
    {
        ISocketController _sockets;
        IIdeas _ideas;
        IVotes _ideaVotes;

        public string Name =&amp;gt; &amp;quot;Idea Vote Sockets&amp;quot;;
        public string Description =&amp;gt; &amp;quot;Enables live updates to idea votes.&amp;quot;;
        public string SocketName =&amp;gt; &amp;quot;ideavotes&amp;quot;;

        public void Initialize()
        {
            _ideas = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IIdeas&amp;gt;();

            _ideaVotes = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IVotes&amp;gt;();
            _ideaVotes.Events.AfterCreate += VoteCreated;
            _ideaVotes.Events.AfterDelete += VoteDeleted;
            _ideaVotes.Events.AfterUpdate += VoteUpdated;
        }

        public void SetController(ISocketController controller)
        {
            _sockets = controller;
        }

        private void VoteCreated(VoteAfterCreateEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        private void VoteUpdated(VoteAfterUpdateEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        private void VoteDeleted(VoteAfterDeleteEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        void SendVoteCounts(Guid ideaId)
        {
            var idea = _ideas.Get(ideaId);
            if (idea != null &amp;amp;&amp;amp; !idea.HasErrors())
            {
                var upVotes =
                    _ideaVotes.List(new VotesListOptions() {IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = true });

                var downVotes =
                    _ideaVotes.List(new VotesListOptions() { IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = false });

                // send socket message with updated totals
                _sockets.Clients.SendToUsersPresentToContent(idea.ContentId, &amp;quot;ideavoted&amp;quot;, new
                {
                    contentId = idea.ContentId,
                    contentTypeId = _ideas.ContentTypeId,
                    yesVotes = upVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;,
                    noVotes = downVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;
                });
            }
        }
    }
}
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="xml"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;
&amp;lt;scriptedContentFragments&amp;gt;
  &amp;lt;scriptedContentFragment name=&amp;quot;Idea Socket Presence Test&amp;quot; version=&amp;quot;10.0.0.0&amp;quot; description=&amp;quot;&amp;quot; instanceIdentifier=&amp;quot;c7e0a2c7d2b44ab08f22d8938ef03a06&amp;quot; theme=&amp;quot;&amp;quot; isCacheable=&amp;quot;false&amp;quot; varyCacheByUser=&amp;quot;false&amp;quot; showHeaderByDefault=&amp;quot;false&amp;quot; cssClass=&amp;quot;&amp;quot; provider=&amp;quot;7bb87a0cc5864a9392ae5b9e5f9747b7&amp;quot;&amp;gt;
    &amp;lt;contentScript&amp;gt;&amp;lt;![CDATA[

&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
			jQuery.telligent.evolution.sockets.ideavotes.on(&amp;#39;ideavoted&amp;#39;, function(data) {
				console.log(data);
			});
});
&amp;lt;/script&amp;gt;

]]&amp;gt;&amp;lt;/contentScript&amp;gt;
  &amp;lt;/scriptedContentFragment&amp;gt;
&amp;lt;/scriptedContentFragments&amp;gt;&lt;/pre&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a id="Tips_and_Tricks" name="Tips_and_Tricks"&gt;&lt;/a&gt;Tips and Tricks&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Sockets can only be used by authenticated, non-system users&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Sockets and Presence</title><link>https://community.telligent.com/community/11/w/developer-training/65063/sockets-and-presence/revision/2</link><pubDate>Tue, 20 Aug 2019 15:30:15 GMT</pubDate><guid isPermaLink="false">f141b2d7-5f01-47b0-ab4d-105e12603c36</guid><dc:creator>Michael Monteleone</dc:creator><comments>https://community.telligent.com/community/11/w/developer-training/65063/sockets-and-presence#comments</comments><description>Revision 2 posted to Developer Training by Michael Monteleone on 08/20/2019 15:30:15&lt;br /&gt;
&lt;p&gt;The Socket Framework provides support for &lt;strong&gt;real-time two-way communication between Verint&amp;nbsp;Community and the browser&lt;/strong&gt;. This allows for both receiving and sending messages directly to the user&amp;nbsp;or scoped&amp;nbsp;groups of users.&lt;/p&gt;
&lt;p&gt;[toc]&lt;/p&gt;
&lt;h2&gt;&lt;a id="When_would_I_want_to_use_sockets" name="When_would_I_want_to_use_sockets"&gt;&lt;/a&gt;When would I want to use sockets?&lt;/h2&gt;
&lt;p&gt;Sockets are useful when you need to push messages from the server to the browser. An easy example to consider is a notification popup that is pushed to a user in the event of an action occurring on the server. Sockets are the mechanism through which built-in platform features including notifications, chat, live activity streams, forum threads, comment threads,&amp;nbsp;theme previews, presence indicators, tracing, and more communicate with the browser.&lt;/p&gt;
&lt;h2&gt;&lt;a id="Overview" name="Overview"&gt;&lt;/a&gt;Overview&lt;/h2&gt;
&lt;p&gt;Built on top of &lt;a href="http://signalr.net/"&gt;SignalR&lt;/a&gt;, the Socket Framework inherits all of SignalR&amp;#39;s performance, stability, and diversity of browser support over underlying WebSocket, server-sent event, or&amp;nbsp;long polling transports. Because it is Verint&amp;nbsp;Community-specific, the Socket Framework also provides:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;[[Plugins|plugin]] based extensibility&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Both built-in and third-party [[Plugins|plugin]] can implement their own &lt;em&gt;sockets&lt;/em&gt; which each define a pair of server and client methods and events for bi-directional communication, all multiplexed over a single&amp;nbsp;underlying connection to the server.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Presence&lt;/strong&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Users&amp;#39; site presence as well as their presence to individual pieces of content regardless of how and where that content is presented&amp;nbsp;is&amp;nbsp;tracked&amp;nbsp;to enable&amp;nbsp;delivery of messages scoped only to&amp;nbsp;users viewing&amp;nbsp;specific&amp;nbsp;content. Additionally, Service Presence supports a similar, but non-content-based scoping of messages.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scale-out and reliability&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;All sockets are multiplexed to over a single connection to a browser. And the browser shares the same, single, connection across all windows or tabs.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Socket connections are reliably maintained, and reconnect after disconnections with randomized, exponential, retry backoffs.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;To support scale-out to multiple application instances as well as sending of socket messages from jobs running outside of web contexts in the job server, Verint&amp;nbsp;Community bundles two&amp;nbsp;possible message bus servers: the Socket Message Bus Service as well as the lower-performing Database Message Bus. Alternatively, Verint&amp;nbsp;Community can use &lt;em&gt;any&lt;/em&gt; message bus service through plugin extensibility. The configuration of which message bus server to use, if any at all, is defined by [[Plugins|plugin]]-based connectors, which can be enabled or disabled through standard plugin management without restarting the application. Socket plugins also expose the underlying message bus for use as a way to keep real-time application state in synchronization across multiple instances.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The socket framework powers &lt;span&gt;notifications, chat, live activity streams, forum threads, comment threads,&amp;nbsp;theme previews, presence indicators, tracing, and more&lt;/span&gt; in Verint Community. Socket plugins can&amp;nbsp;be developed to easily power other functionality like real-time whiteboards, analytics, or even games.&lt;/p&gt;
&lt;p&gt;[DIAGRAM: Sockets]&lt;/p&gt;
&lt;h2&gt;&lt;a id="API" name="API"&gt;&lt;/a&gt;API&lt;/h2&gt;
&lt;p&gt;The API exists solely as a set of interfaces implementable by [[Plugins|plugins]].&lt;/p&gt;
&lt;h3&gt;&lt;a id="ISocket_Plugin" name="ISocket_Plugin"&gt;&lt;/a&gt;&lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket Plugin&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A socket is defined by a [[Plugins|plugin]] which implements the &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; interface. A single socket plugin represents a single channel of communication between the server and browser. For example, a socket plugin may represent all functionality related to sending and receiving realtime chat messages. A single socket plugin can send and receive arbitrary messages and optional data with those messages, but can only send or receive messages sent by or to the same socket plugin.&lt;/p&gt;
&lt;p&gt;Socket plugins are injected with instances of &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt; exposes an instance of an &lt;a href="/developers/w/developer90/50149.iclientscontroller-plugin-supplementary-type"&gt;IClientsController&lt;/a&gt; which contains events for when a user connects, disconnects, or sends a message. The &lt;a href="/developers/w/developer90/50149.iclientscontroller-plugin-supplementary-type"&gt;IClientsController&lt;/a&gt; also supports sending messages to a user or broadcasting to all users.&lt;/p&gt;
&lt;p&gt;Each enabled socket plugin yields a corresponding client-side API.&lt;/p&gt;
&lt;p&gt;Socket plugins will often also implement the &lt;a href="/developers/w/developer90/50286.ihtmlheaderextension-plugin-type"&gt;IHtmlHeaderExtension&lt;/a&gt; interface to register JavaScript which handles or sends socket messages along with custom logic required by the plugin.&lt;/p&gt;
&lt;h3&gt;&lt;a id="ISocketMessageBus_Plugin" name="ISocketMessageBus_Plugin"&gt;&lt;/a&gt;&lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus Plugin&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Multiple-application instance scale-out is achieved through usage of plugins which implement the &lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus&lt;/a&gt; interface. Verint&amp;nbsp;Community bundles a default implementation, but supports integrating with other message busses as well. For details, see the discussion on Scale-Out.&lt;/p&gt;
&lt;h3&gt;&lt;a id="Client-Side" name="Client-Side"&gt;&lt;/a&gt;Client-Side&lt;/h3&gt;
&lt;h4&gt;&lt;a id="Socket_Endpoints" name="Socket_Endpoints"&gt;&lt;/a&gt;Socket Endpoints&lt;/h4&gt;
&lt;p&gt;Each &lt;code&gt;ISocket&lt;/code&gt; plugin implements a &lt;code&gt;SocketName&lt;/code&gt;. This one-word string becomes the name of the client-side API. For example, given the socket:&lt;/p&gt;
&lt;pre class="brush: csharp"&gt;public class MySocket : ISocket
{
    // ...

    string SocketName { get { return &amp;quot;mySocket&amp;quot;; } }

    // ...
}&lt;/pre&gt;
&lt;p&gt;Then the following JavaScript API will be automatically exposed:&lt;/p&gt;
&lt;pre class="brush: javascript"&gt;// receive and handle a message with optional data from the server
$.telligent.evolution.sockets.mySocket.on(messageName, function(data) {
   // handle
});

// send data to the server an optional object message
$.telligent.evolution.sockets.mySocket.send(messageName, data);&lt;/pre&gt;
&lt;h4&gt;&lt;a id="Initiation" name="Initiation"&gt;&lt;/a&gt;Initiation&lt;/h4&gt;
&lt;p&gt;Before attempting to send or receive messages from the client side, the Socket Framework must initiate itself. This happens automatically, and when complete, it publishes a &lt;a href="/developers/w/developer90/50006.socket-connected-client-message"&gt;socket.connected&lt;/a&gt; &lt;a href="/developers/w/developer90/50024.messaging-javascript-api-module"&gt;client-side message&lt;/a&gt;.&lt;/p&gt;
&lt;pre class="brush: javascript"&gt;$.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
    // set up message listeners or send messages
});&lt;/pre&gt;
&lt;h2&gt;&lt;a id="Example_Socket" name="Example_Socket"&gt;&lt;/a&gt;Example Socket&lt;/h2&gt;
&lt;p&gt;The following shows a basic example of a socket which routes greetings from one user to another. A user provides the user name of another community member, clicks &amp;#39;greet&amp;#39;, and an alert is displayed to the other user.&lt;/p&gt;
&lt;p&gt;Greetings are initiated from a user via a widget, sent via the client-side socket API to the &lt;code&gt;ISocket&lt;/code&gt; plugin, and then delivered to the recipient user where the same widget instance for the other user will display the message in a JavaScript &lt;code&gt;alert()&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;&lt;a id="Server_Side" name="Server_Side"&gt;&lt;/a&gt;Server Side&lt;/h3&gt;
&lt;p&gt;Create a new [[Plugins|plugin]] which implements the &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; interface. Its &lt;code&gt;Name&lt;/code&gt;, &lt;code&gt;Description&lt;/code&gt;, and &lt;code&gt;Initialize()&lt;/code&gt; are unimportant. For &lt;code&gt;SocketName&lt;/code&gt; and &lt;code&gt;SetController()&lt;/code&gt;, use the following:&lt;/p&gt;
&lt;pre class="brush: csharp"&gt;public string SocketName
{
    get { return &amp;quot;greeter&amp;quot;; }
}

public void SetController(ISocketController controller)
{
    controller.Clients.Received += (sender, e) =&amp;gt;
    {
        // if this was a greting message, let&amp;#39;s process it
        if (e.MessageName == &amp;quot;greet&amp;quot;)
        {
            // get the associated recipient user
            // data passed from the client side is available on the dynamic MessageData object
            var to = PublicApi.Users.Get(new UsersGetOptions { Username = (string)e.MessageData.Recipient });

            // get the sender user
            var from = PublicApi.Users.Get(new UsersGetOptions { Id = e.UserId });

            // send a new message to the recipient
            controller.Clients.Send(to.Id.GetValueOrDefault(), &amp;quot;greet&amp;quot;, new
            {
                Message = String.Format(&amp;quot;Hello {0}, from {1}&amp;quot;, to.DisplayName, from.DisplayName)
            });
        }
    };
}&lt;/pre&gt;
&lt;h3&gt;&lt;a id="Client_Side" name="Client_Side"&gt;&lt;/a&gt;Client Side&lt;/h3&gt;
&lt;p&gt;Create a new Studio Widget with content:&lt;/p&gt;
&lt;pre class="brush: javascript"&gt;## set up some unique ids for interface elements
#set($recipientInputId = $core_v2_widget.UniqueId(&amp;#39;recipient&amp;#39;))
#set($sendLinkId = $core_v2_widget.UniqueId(&amp;#39;greet&amp;#39;))

## basic interface
&amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;$recipientInputId&amp;quot; /&amp;gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;$sendLinkId&amp;quot;&amp;gt;Greet&amp;lt;/a&amp;gt;

&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
// Wait for socket to be connected
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {

    // when &amp;#39;Greet&amp;#39; is clicked, send a message to be delivered to the recipient
    jQuery(&amp;#39;#$sendLinkId&amp;#39;).on(&amp;#39;click&amp;#39;, function(e) {
        e.preventDefault();

        jQuery.telligent.evolution.sockets.greeter.send(&amp;#39;greet&amp;#39;, {
            Recipient: jQuery(&amp;#39;#$recipientInputId&amp;#39;).val()
        });
    });

    // when a &amp;#39;greet&amp;#39; message is received from the socket, display it as an alert
    jQuery.telligent.evolution.sockets.greeter.on(&amp;#39;greet&amp;#39;, function(data){
        alert(data.Message);
    });
});
&amp;lt;/script&amp;gt;&lt;/pre&gt;
&lt;p&gt;Note use of the &lt;a href="/developers/w/developer90/50006.socket-connected-client-message"&gt;socket.connected&lt;/a&gt; &lt;a href="/developers/w/developer90/50024.messaging-javascript-api-module"&gt;client-side message&lt;/a&gt; as well as the automatically-generated &lt;code&gt;jQuery.telligent.evolution.sockets.testSocket&lt;/code&gt; API.&lt;/p&gt;
&lt;p&gt;The result is a simple UI that enables sending a greeting to another user by their user name.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter.png"&gt;&lt;img style="border:1px solid #DDD;width:264px;" alt=" " src="/resized-image/__size/640x480/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter_2D00_greeted.png"&gt;&lt;img style="border:1px solid #DDD;width:485px;" alt=" " src="/resized-image/__size/640x480/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter_2D00_greeted.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a id="Download" name="Download"&gt;&lt;/a&gt;Download&lt;/h3&gt;
&lt;p&gt;The complete sample can be downloaded:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/1680_2E00_SocketSample_2E00_cs"&gt;community.telligent.com/.../1680_2E00_SocketSample_2E00_cs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/5314.GreeterUI_2D00_Widget.xml"&gt;community.telligent.com/.../5314.GreeterUI_2D00_Widget.xml&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a id="Scale-out" name="Scale-out"&gt;&lt;/a&gt;Scale-out&lt;/h2&gt;
&lt;h3&gt;&lt;a id="Overview" name="Overview"&gt;&lt;/a&gt;Overview&lt;/h3&gt;
&lt;p&gt;The socket message bus is used both internally by the Socket Framework to push messages to multiple application instances when sending messages as well as exposed as a generic message bus for &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; plugins to consume through the injected &lt;a href="/developers/w/developer90/50167.imessagebuscontroller-plugin-supplementary-type"&gt;IMessageBusController&lt;/a&gt; instance.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;When only a single application instance is needed, the Socket Message Bus uses an internal memory-only bus. When multiple application instances are needed, the in-memory bus cannot be used. Instead a [[Plugins|Plugins]] which implements &lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus&lt;/a&gt; must be enabled.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a id="Socket_Message_Bus_Server" name="Socket_Message_Bus_Server"&gt;&lt;/a&gt;Socket Message Bus Server&lt;/h3&gt;
&lt;p&gt;Verint&amp;nbsp;Community 7.5 comes with the optionally-installed Socket Message Bus Windows Service and its corresponding &lt;code&gt;ISocketMessageBus&lt;/code&gt; plugin-based connector, &lt;em&gt;Socket Message Bus Service Connector&lt;/em&gt;. This is simply a Windows Service which echoes messages it receives to all connected Verint&amp;nbsp;Community instances.&lt;/p&gt;
&lt;h3&gt;&lt;a id="Custom_Message_Bus" name="Custom_Message_Bus"&gt;&lt;/a&gt;Custom Message Bus&lt;/h3&gt;
&lt;p&gt;In cases where a community would prefer to use an existing third party message bus solution, custom &lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus plugins&lt;/a&gt; can be written against it and deployed. An example could be a message bus service which supports multiple Verint&amp;nbsp;Community communities on a single bus server by potentially adding an identifier to the string messages sent and received by the plugin for routing the message on the bus server.&lt;/p&gt;
&lt;h3&gt;&lt;a id="Generic_Messages" name="Generic_Messages"&gt;&lt;/a&gt;Generic Messages&lt;/h3&gt;
&lt;p&gt;Custom logic in &lt;code&gt;ISocket&lt;/code&gt; plugins can also make use of the message bus. Generic messages can be useful for keeping realtime state synchronized across application instances. For example, chat presence may be persisted in a database, but cached locally in multiple instances. Since it is important that these caches remain synchronized, presence change messages can be sent and received across the message bus for other app instances&amp;#39; plugins to handle and process.&lt;/p&gt;
&lt;p&gt;The &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt; injected into &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; plugins contains an instance of an &lt;a href="/developers/w/developer90/50167.imessagebuscontroller-plugin-supplementary-type"&gt;IMessageBusController&lt;/a&gt;. The &lt;a href="/developers/w/developer90/50167.imessagebuscontroller-plugin-supplementary-type"&gt;IMessageBusController&lt;/a&gt; exposes events for when generic messages are received from instances of the application along with a method for sending them.&lt;/p&gt;
&lt;p&gt;A useful pattern for state change is to send a generic message to the bus, and only handle it once it is re-received. This allows all instances to know about the state. Additionally, the instance that sends it receives the message immediately without having to wait for the round-trip, and is made aware of the local origin of the message. In this manner, the sender can also be exclusively responsible for potentially persisting the state change elsewhere.&lt;/p&gt;
&lt;pre class="brush: javascript"&gt;controller.MessageBus.Publish(&amp;quot;something.happened&amp;quot;,&amp;quot;&amp;quot;);
controller.MessageBus.Received += (sender, e) =&amp;gt;
{
    if (e.MessageName == &amp;quot;something.happened&amp;quot;)
    {
        // update some local caches
        // ...
        if (e.Source == BusMessageSource.Local)
        {
            // update DB
            // ...
        }
    }
};&lt;/pre&gt;
&lt;h2&gt;&lt;a id="Presence_Services" name="Presence_Services"&gt;&lt;/a&gt;Presence Services&lt;/h2&gt;
&lt;h3&gt;&lt;a id="User_Presence" name="User_Presence"&gt;&lt;/a&gt;User Presence&lt;/h3&gt;
&lt;p&gt;The User Presence service tracks which users are online. &amp;nbsp;The service is responsible for the presence indicator often&amp;nbsp;displayed along side the user&amp;#39;s name. &amp;nbsp;In conjunction with the Content Presence service (discussed below), the service sends socket messages as users go offline and online to update the presence indicators in near real-time for users who are currently viewing&amp;nbsp;the user whose online status has changed.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence.png"&gt;&lt;img alt=" " src="/resized-image/__size/320x240/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The platform has the options for&amp;nbsp;&lt;strong&gt;Enable Presence Tracking&lt;/strong&gt;,&amp;nbsp;&lt;strong&gt;Allow Members To Toggle Presence Tracking Enablement &lt;/strong&gt;and&lt;strong&gt; Default Presence Tracking Enablement Value &amp;nbsp;&lt;/strong&gt;available under Membership in the Membership Options panel in Administration. &amp;nbsp;&lt;strong&gt;Enable Presence Tracking&amp;nbsp;&lt;/strong&gt;controls whether user presence tracking is available for the community. &amp;nbsp;If tracking is enabled, &amp;nbsp;&lt;strong&gt;Allow Members To Toggle Presence Tracking Enablement&lt;/strong&gt; controls whether or not each user should have the option to disable tracking of their online status. If that option is enabled the&amp;nbsp;&lt;strong&gt;Default Presence Tracking Enablement Value&amp;nbsp;&lt;/strong&gt;is also available. &amp;nbsp;If users are giving the option to control their presence tracking, the&amp;nbsp;&lt;strong&gt;Enable presence tracking&lt;/strong&gt; option will be available in the membership settings.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence-admin.png"&gt;&lt;img alt=" " src="/resized-image/__size/550x539/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence-admin.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a id="Content_Presence" name="Content_Presence"&gt;&lt;/a&gt;Content Presence&lt;/h3&gt;
&lt;p&gt;The Content Presence service tracks which content users are currently viewing. &amp;nbsp;This enables the platform to update users in real time to changes in content they are currently viewing. &amp;nbsp;The API provides a quantity of users who are currently viewing each content item.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;How is content presence determined?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Page Context: The service uses the page content to track what content the using is currently viewing. &amp;nbsp;For instance if a user is currently viewing a blog post, the content service would be aware that user is currently viewing that blog post, its author, the blog the post belonged to and the group the blog belonged to. &amp;nbsp;&lt;/li&gt;
&lt;li&gt;Html attributes: Html attributes can be added to through the &lt;code&gt;core_v2_contentPresence.RenderAttributes&lt;/code&gt; method. &amp;nbsp;This method will render the proper attributes to automatically track a user&amp;#39;s content presence, when the decorated element is currently visible on the page they are viewing. &amp;nbsp;The comment stream and activity stream are two examples where this method is in use.&lt;/li&gt;
&lt;li&gt;APIs: &amp;nbsp;In Process, Rest and Widget APIs are available to directly add and remove which content a user is present for. &amp;nbsp;Additionally, a summary of the quantity of users viewing each content item is available.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a id="Service_Presence" name="Service_Presence"&gt;&lt;/a&gt;Service Presence&lt;/h3&gt;
&lt;p&gt;The Service Presence service tracks what services a user is currently viewing. &amp;nbsp;When a user is present for a service, messages about changes in that service can be sent to the user&amp;#39;s browser so that browser can be updated to show the latest changes. &amp;nbsp;The activity story service is an example of how this service is used. &amp;nbsp;When an activity story is created, deleted or updated any user that is present to the activity story service will&amp;nbsp;be see that updated of that change and their activity story stream can be updated as needed.&lt;/p&gt;
&lt;p&gt;How do you define a Service Presence service?&lt;/p&gt;
&lt;p&gt;Widgets can define themselves as services, using the&lt;code&gt;&amp;nbsp;core_v2_servicePresence.RenderAttributes&lt;/code&gt; method and passing a unique service identifier. &amp;nbsp;For instance, the activity stream widget can define itself as a service, doing allows users who are currently viewing an activity stream to receive socket messages for new activity stories. &amp;nbsp;Using the Content Presence service alone, would only allow users to receive socket messages to for content that already exists in the activity stream.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;How is service presence determined?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Html attributes: Html attributes can be added to through the &lt;code&gt;core_v2_servicePresence.RenderAttributes&lt;/code&gt; method. &amp;nbsp;This method will render the proper attributes to automatically track a user&amp;#39;s presence to a service, when the decorated element is currently visible on the page they are viewing.&lt;/li&gt;
&lt;li&gt;APIs: &amp;nbsp;In Process, Rest and Widget APIs are available to directly add and remove which service a user is present for. &amp;nbsp;Additionally listing which users are currently present to a service&amp;nbsp;is available in the same APIs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Combining the Content and Service Presence Services with Sockets creates new opportunities to&amp;nbsp;enhance community functionality. &amp;nbsp;The new Live Comment and Thread Forums are two features that make use of the Socket Bus and the Presence Services.&lt;/p&gt;
&lt;h2&gt;&lt;a id="Example_Socket_using_Content_Presence_Service" name="Example_Socket_using_Content_Presence_Service"&gt;&lt;/a&gt;Example Socket using Content Presence Service&lt;/h2&gt;
&lt;p&gt;This example will&amp;nbsp;create an &lt;code&gt;ISocket&lt;/code&gt; implementation that will send socket messages to users when a vote is received or changed on an idea. &amp;nbsp;By combining the socket implementation with the content presence service, the socket messages can be sent only to those users who are currently viewing the idea that received the vote.&lt;/p&gt;
&lt;h3&gt;&lt;a id="Server_Side" name="Server_Side"&gt;&lt;/a&gt;Server Side&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;ISocket&lt;/code&gt; implementation will use the &lt;em&gt;ideavotes&lt;/em&gt; for the &lt;code&gt;SocketName &lt;/code&gt;and maintain a reference to the &lt;code&gt;SocketController&lt;/code&gt; for later use in our example.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;ISocketController _sockets;
public string SocketName =&amp;gt; &amp;quot;ideavotes&amp;quot;;

public void SetController(ISocketController controller)
{
    _sockets = controller;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The example class will need to send a message whenever an idea is&amp;nbsp;voted on, this can be accomplished by attaching to the Idea Vote Events for these actions in our plugin&amp;#39;s &lt;code&gt;Initialize&lt;/code&gt; method. &amp;nbsp;In each event handler, we will call the same method SendVoteCounts passing the idea id for the vote.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public void Initialize()
{
    _ideas = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IIdeas&amp;gt;();

    _ideaVotes = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IVotes&amp;gt;();
    _ideaVotes.Events.AfterCreate += VoteCreated;
    _ideaVotes.Events.AfterDelete += VoteDeleted;
    _ideaVotes.Events.AfterUpdate += VoteUpdated;
}

private void VoteCreated(VoteAfterCreateEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}

private void VoteUpdated(VoteAfterUpdateEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}

private void VoteDeleted(VoteAfterDeleteEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;In the SendVoteCounts method, the number of up and down votes will be retrieved and the&amp;nbsp;&lt;code&gt;_sockets.Clients.SendToUsersPresentToContent &lt;/code&gt;method will be used to send a message to all users who are currently present to that idea.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;void SendVoteCounts(Guid ideaId)
{
    var idea = _ideas.Get(ideaId);
    if (idea != null &amp;amp;&amp;amp; !idea.HasErrors())
    {
        var upVotes =
            _ideaVotes.List(new VotesListOptions() {IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = true });

        var downVotes =
            _ideaVotes.List(new VotesListOptions() { IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = false });

        // send socket message with updated totals
        _sockets.Clients.SendToUsersPresentToContent(idea.ContentId, &amp;quot;ideavoted&amp;quot;, new
        {
            contentId = idea.ContentId,
            contentTypeId = _ideas.ContentTypeId,
            yesVotes = upVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;,
            noVotes = downVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;
        });
    }
}&lt;/pre&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a id="Client_Side" name="Client_Side"&gt;&lt;/a&gt;Client Side&lt;/h3&gt;
&lt;p&gt;Once this plugin is compiled and enabled on the community site, each time an idea is voted on any user who is viewing that idea will receive an &lt;em&gt;ideavoted&amp;nbsp;&lt;/em&gt;socket message. &amp;nbsp;For this example, we can use a widget to see these messages. &amp;nbsp;The example will&amp;nbsp;make use of the&amp;nbsp;&lt;code&gt;$.telligent.evolution.sockets.ideavotes&lt;/code&gt; API that is automatically generated for our &lt;code&gt;ISocket&lt;/code&gt; implementation. &amp;nbsp;That API will enable the widget to listen for messages from the custom socket. &amp;nbsp;In this case, the message&amp;#39;s data will output to the browser&amp;#39;s console window.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="javascript"&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
	jQuery.telligent.evolution.sockets.ideavotes.on(&amp;#39;ideavoted&amp;#39;, function(data) {
		console.log(data);
	});
});
&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The widget can be placed on the Idea page or Idea List page,&amp;nbsp;you will be able to see the messages for the ideas you are currently viewing when any vote is received on the idea(s) you are currently viewing.&lt;/p&gt;
&lt;h3&gt;&lt;a id="Completed_Sample" name="Completed_Sample"&gt;&lt;/a&gt;Completed Sample&lt;/h3&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;using System;
using Telligent.Evolution.Extensibility.Ideation.Api;
using Telligent.Evolution.Extensibility.Sockets.Version1;
using Telligent.Evolution.Extensibility.Version1;

namespace Telligent.Evolution.Examples
{
    public class VoteSocket : IPlugin, ISocket
    {
        ISocketController _sockets;
        IIdeas _ideas;
        IVotes _ideaVotes;

        public string Name =&amp;gt; &amp;quot;Idea Vote Sockets&amp;quot;;
        public string Description =&amp;gt; &amp;quot;Enables live updates to idea votes.&amp;quot;;
        public string SocketName =&amp;gt; &amp;quot;ideavotes&amp;quot;;

        public void Initialize()
        {
            _ideas = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IIdeas&amp;gt;();

            _ideaVotes = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IVotes&amp;gt;();
            _ideaVotes.Events.AfterCreate += VoteCreated;
            _ideaVotes.Events.AfterDelete += VoteDeleted;
            _ideaVotes.Events.AfterUpdate += VoteUpdated;
        }

        public void SetController(ISocketController controller)
        {
            _sockets = controller;
        }

        private void VoteCreated(VoteAfterCreateEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        private void VoteUpdated(VoteAfterUpdateEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        private void VoteDeleted(VoteAfterDeleteEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        void SendVoteCounts(Guid ideaId)
        {
            var idea = _ideas.Get(ideaId);
            if (idea != null &amp;amp;&amp;amp; !idea.HasErrors())
            {
                var upVotes =
                    _ideaVotes.List(new VotesListOptions() {IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = true });

                var downVotes =
                    _ideaVotes.List(new VotesListOptions() { IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = false });

                // send socket message with updated totals
                _sockets.Clients.SendToUsersPresentToContent(idea.ContentId, &amp;quot;ideavoted&amp;quot;, new
                {
                    contentId = idea.ContentId,
                    contentTypeId = _ideas.ContentTypeId,
                    yesVotes = upVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;,
                    noVotes = downVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;
                });
            }
        }
    }
}
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="xml"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;
&amp;lt;scriptedContentFragments&amp;gt;
  &amp;lt;scriptedContentFragment name=&amp;quot;Idea Socket Presence Test&amp;quot; version=&amp;quot;10.0.0.0&amp;quot; description=&amp;quot;&amp;quot; instanceIdentifier=&amp;quot;c7e0a2c7d2b44ab08f22d8938ef03a06&amp;quot; theme=&amp;quot;&amp;quot; isCacheable=&amp;quot;false&amp;quot; varyCacheByUser=&amp;quot;false&amp;quot; showHeaderByDefault=&amp;quot;false&amp;quot; cssClass=&amp;quot;&amp;quot; provider=&amp;quot;7bb87a0cc5864a9392ae5b9e5f9747b7&amp;quot;&amp;gt;
    &amp;lt;contentScript&amp;gt;&amp;lt;![CDATA[

&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
			jQuery.telligent.evolution.sockets.ideavotes.on(&amp;#39;ideavoted&amp;#39;, function(data) {
				console.log(data);
			});
});
&amp;lt;/script&amp;gt;

]]&amp;gt;&amp;lt;/contentScript&amp;gt;
  &amp;lt;/scriptedContentFragment&amp;gt;
&amp;lt;/scriptedContentFragments&amp;gt;&lt;/pre&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a id="Tips_and_Tricks" name="Tips_and_Tricks"&gt;&lt;/a&gt;Tips and Tricks&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Sockets can only be used by authenticated, non-system users&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Sockets</title><link>https://community.telligent.com/community/11/w/developer-training/65063/sockets-and-presence/revision/1</link><pubDate>Thu, 13 Jun 2019 19:24:02 GMT</pubDate><guid isPermaLink="false">f141b2d7-5f01-47b0-ab4d-105e12603c36</guid><dc:creator>Ben Tiedt</dc:creator><comments>https://community.telligent.com/community/11/w/developer-training/65063/sockets-and-presence#comments</comments><description>Revision 1 posted to Developer Training by Ben Tiedt on 06/13/2019 19:24:02&lt;br /&gt;
&lt;p&gt;The Socket Framework provides support for &lt;strong&gt;real-time two-way communication between Telligent Community and the browser&lt;/strong&gt;. This allows for both receiving and sending programmatic messages directly to the user.&lt;/p&gt;
&lt;p&gt;[toc]&lt;/p&gt;
&lt;h2&gt;&lt;a id="When_would_I_want_to_use_sockets" name="When_would_I_want_to_use_sockets"&gt;&lt;/a&gt;When would I want to use sockets?&lt;/h2&gt;
&lt;p&gt;Sockets are useful when you need to push messages from the server to the browser. An easy example to consider is a notification popup that is pushed to a user in the event of an action occurring on the server. Sockets are the mechanism through which built-in platform features including notifications, chat, live theme previewing, and tracing communicate with the browser.&lt;/p&gt;
&lt;h2&gt;&lt;a id="Overview" name="Overview"&gt;&lt;/a&gt;Overview&lt;/h2&gt;
&lt;p&gt;Built on top of &lt;a href="http://signalr.net/"&gt;SignalR&lt;/a&gt;, &lt;strong&gt;the Socket Framework inherits all of SignalR&amp;#39;s performance, stability, and diversity of browser support&lt;/strong&gt;. Because it is Telligent Community-specific, the Socket Framework also is able to provide:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;[[Plugins|plugin]] based extensibility&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Both built-in and third-party [[Plugins|plugin]] can implement their own &lt;em&gt;sockets&lt;/em&gt; which each define a pair of server and client methods and events for bi-directional communication, all multiplexed over a single underlying &lt;a href="https://github.com/SignalR/SignalR/wiki/PersistentConnection"&gt;PersistentConnection&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Built-in user mapping&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;User-to-connection mapping is maintained transparently by Telligent Community, allowing knowledge of which Telligent Community user has sent a message and enabling sending of a message directly to all active connections associated with a given Telligent Community user. User mapping persistence is maintained efficiently and shared immediately, both on single app instances as well as synchronized across multiple application instances.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Built-in, hot-swappable, scale-out&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;To support multiple application instances, Telligent Community bundles an optionally installable Message Bus Server. Alternatively, Telligent Community can use &lt;em&gt;any&lt;/em&gt; message bus service through plugin extensibility. The configuration of which message bus server to use, if any at all, is defined by [[Plugins|plugin]]-based connectors, which can be enabled or disabled through standard plugin management without restarting the application. Socket plugins also expose the underlying message bus for use as a way to keep real-time application state in synchronization across multiple instances.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Much more!&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The socket framework powers notifications, chat, live previewing, and tracing in Telligent Community. Socket plugins could be developed to easily power other functionality like real-time whiteboards, analytics, or even games.&lt;/p&gt;
&lt;p&gt;[DIAGRAM: Sockets]&lt;/p&gt;
&lt;h2&gt;&lt;a id="API" name="API"&gt;&lt;/a&gt;API&lt;/h2&gt;
&lt;p&gt;The API exists solely as a set of interfaces implementable by [[Plugins|plugins]].&lt;/p&gt;
&lt;h3&gt;&lt;a id="ISocket_Plugin" name="ISocket_Plugin"&gt;&lt;/a&gt;&lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket Plugin&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A socket is defined by a [[Plugins|plugin]] which implements the &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; interface. A single socket plugin represents a single channel of communication between the server and browser. For example, a socket plugin may represent all functionality related to sending and receiving realtime chat messages. A single socket plugin can send and receive arbitrary messages and optional data with those messages, but can only send or receive messages sent by or to the same socket plugin.&lt;/p&gt;
&lt;p&gt;Socket plugins are injected with instances of &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt; exposes an instance of an &lt;a href="/developers/w/developer90/50149.iclientscontroller-plugin-supplementary-type"&gt;IClientsController&lt;/a&gt; which contains events for when a user connects, disconnects, or sends a message. The &lt;a href="/developers/w/developer90/50149.iclientscontroller-plugin-supplementary-type"&gt;IClientsController&lt;/a&gt; also supports sending messages to a user or broadcasting to all users.&lt;/p&gt;
&lt;p&gt;Each enabled socket plugin yields a corresponding client-side API.&lt;/p&gt;
&lt;p&gt;Socket plugins will often also implement the &lt;a href="/developers/w/developer90/50286.ihtmlheaderextension-plugin-type"&gt;IHtmlHeaderExtension&lt;/a&gt; interface to register JavaScript which handles or sends socket messages along with custom logic required by the plugin.&lt;/p&gt;
&lt;h3&gt;&lt;a id="ISocketMessageBus_Plugin" name="ISocketMessageBus_Plugin"&gt;&lt;/a&gt;&lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus Plugin&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Multiple-application instance scale-out is achieved through usage of plugins which implement the &lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus&lt;/a&gt; interface. Telligent Community bundles a default implementation, but supports integrating with other message busses as well. For details, see the discussion on Scale-Out.&lt;/p&gt;
&lt;h3&gt;&lt;a id="Client-Side" name="Client-Side"&gt;&lt;/a&gt;Client-Side&lt;/h3&gt;
&lt;h4&gt;&lt;a id="Socket_Endpoints" name="Socket_Endpoints"&gt;&lt;/a&gt;Socket Endpoints&lt;/h4&gt;
&lt;p&gt;Each &lt;code&gt;ISocket&lt;/code&gt; plugin implements a &lt;code&gt;SocketName&lt;/code&gt;. This one-word string becomes the name of the client-side API. For example, given the socket:&lt;/p&gt;
&lt;pre class="brush: csharp"&gt;public class MySocket : ISocket
{
    // ...

    string SocketName { get { return &amp;quot;mySocket&amp;quot;; } }

    // ...
}&lt;/pre&gt;
&lt;p&gt;Then the following JavaScript API will be automatically exposed:&lt;/p&gt;
&lt;pre class="brush: javascript"&gt;// receive and handle a message with optional data from the server
$.telligent.evolution.sockets.mySocket.on(messageName, function(data) {
   // handle
});

// send data to the server an optional object message
$.telligent.evolution.sockets.mySocket.send(messageName, data);&lt;/pre&gt;
&lt;h4&gt;&lt;a id="Initiation" name="Initiation"&gt;&lt;/a&gt;Initiation&lt;/h4&gt;
&lt;p&gt;Before attempting to send or receive messages from the client side, the Socket Framework must initiate itself. This happens automatically, and when complete, it publishes a &lt;a href="/developers/w/developer90/50006.socket-connected-client-message"&gt;socket.connected&lt;/a&gt; &lt;a href="/developers/w/developer90/50024.messaging-javascript-api-module"&gt;client-side message&lt;/a&gt;.&lt;/p&gt;
&lt;pre class="brush: javascript"&gt;$.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
    // set up message listeners or send messages
});&lt;/pre&gt;
&lt;h2&gt;&lt;a id="Example_Socket" name="Example_Socket"&gt;&lt;/a&gt;Example Socket&lt;/h2&gt;
&lt;p&gt;The following shows a basic example of a socket which routes greetings from one user to another. A user provides the user name of another community member, clicks &amp;#39;greet&amp;#39;, and an alert is displayed to the other user.&lt;/p&gt;
&lt;p&gt;Greetings are initiated from a user via a widget, sent via the client-side socket API to the &lt;code&gt;ISocket&lt;/code&gt; plugin, and then delivered to the recipient user where the same widget instance for the other user will display the message in a JavaScript &lt;code&gt;alert()&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;&lt;a id="Server_Side" name="Server_Side"&gt;&lt;/a&gt;Server Side&lt;/h3&gt;
&lt;p&gt;Create a new [[Plugins|plugin]] which implements the &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; interface. Its &lt;code&gt;Name&lt;/code&gt;, &lt;code&gt;Description&lt;/code&gt;, and &lt;code&gt;Initialize()&lt;/code&gt; are unimportant. For &lt;code&gt;SocketName&lt;/code&gt; and &lt;code&gt;SetController()&lt;/code&gt;, use the following:&lt;/p&gt;
&lt;pre class="brush: csharp"&gt;public string SocketName
{
    get { return &amp;quot;greeter&amp;quot;; }
}

public void SetController(ISocketController controller)
{
    controller.Clients.Received += (sender, e) =&amp;gt;
    {
        // if this was a greting message, let&amp;#39;s process it
        if (e.MessageName == &amp;quot;greet&amp;quot;)
        {
            // get the associated recipient user
            // data passed from the client side is available on the dynamic MessageData object
            var to = PublicApi.Users.Get(new UsersGetOptions { Username = (string)e.MessageData.Recipient });

            // get the sender user
            var from = PublicApi.Users.Get(new UsersGetOptions { Id = e.UserId });

            // send a new message to the recipient
            controller.Clients.Send(to.Id.GetValueOrDefault(), &amp;quot;greet&amp;quot;, new
            {
                Message = String.Format(&amp;quot;Hello {0}, from {1}&amp;quot;, to.DisplayName, from.DisplayName)
            });
        }
    };
}&lt;/pre&gt;
&lt;h3&gt;&lt;a id="Client_Side" name="Client_Side"&gt;&lt;/a&gt;Client Side&lt;/h3&gt;
&lt;p&gt;Create a new Studio Widget with content:&lt;/p&gt;
&lt;pre class="brush: javascript"&gt;## set up some unique ids for interface elements
#set($recipientInputId = $core_v2_widget.UniqueId(&amp;#39;recipient&amp;#39;))
#set($sendLinkId = $core_v2_widget.UniqueId(&amp;#39;greet&amp;#39;))

## basic interface
&amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;$recipientInputId&amp;quot; /&amp;gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;$sendLinkId&amp;quot;&amp;gt;Greet&amp;lt;/a&amp;gt;

&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
// Wait for socket to be connected
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {

    // when &amp;#39;Greet&amp;#39; is clicked, send a message to be delivered to the recipient
    jQuery(&amp;#39;#$sendLinkId&amp;#39;).on(&amp;#39;click&amp;#39;, function(e) {
        e.preventDefault();

        jQuery.telligent.evolution.sockets.greeter.send(&amp;#39;greet&amp;#39;, {
            Recipient: jQuery(&amp;#39;#$recipientInputId&amp;#39;).val()
        });
    });

    // when a &amp;#39;greet&amp;#39; message is received from the socket, display it as an alert
    jQuery.telligent.evolution.sockets.greeter.on(&amp;#39;greet&amp;#39;, function(data){
        alert(data.Message);
    });
});
&amp;lt;/script&amp;gt;&lt;/pre&gt;
&lt;p&gt;Note use of the &lt;a href="/developers/w/developer90/50006.socket-connected-client-message"&gt;socket.connected&lt;/a&gt; &lt;a href="/developers/w/developer90/50024.messaging-javascript-api-module"&gt;client-side message&lt;/a&gt; as well as the automatically-generated &lt;code&gt;jQuery.telligent.evolution.sockets.testSocket&lt;/code&gt; API.&lt;/p&gt;
&lt;p&gt;The result is a simple UI that enables sending a greeting to another user by their user name.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter.png"&gt;&lt;img style="width:264px;border:1px solid #DDD;" src="/resized-image/__size/640x480/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter.png" alt=" " /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter_2D00_greeted.png"&gt;&lt;img style="width:485px;border:1px solid #DDD;" src="/resized-image/__size/640x480/__key/communityserver-wikis-components-files/00-00-00-12-83/greeter_2D00_greeted.png" alt=" " /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a id="Download" name="Download"&gt;&lt;/a&gt;Download&lt;/h3&gt;
&lt;p&gt;The complete sample can be downloaded:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/1680_2E00_SocketSample_2E00_cs"&gt;community.telligent.com/.../1680_2E00_SocketSample_2E00_cs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/5314.GreeterUI_2D00_Widget.xml"&gt;community.telligent.com/.../5314.GreeterUI_2D00_Widget.xml&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a id="Scale-out" name="Scale-out"&gt;&lt;/a&gt;Scale-out&lt;/h2&gt;
&lt;h3&gt;&lt;a id="Overview" name="Overview"&gt;&lt;/a&gt;Overview&lt;/h3&gt;
&lt;p&gt;The socket message bus is used both internally by the Socket Framework to push messages to multiple application instances when sending messages as well as exposed as a generic message bus for &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; plugins to consume through the injected &lt;a href="/developers/w/developer90/50167.imessagebuscontroller-plugin-supplementary-type"&gt;IMessageBusController&lt;/a&gt; instance.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;When only a single application instance is needed, the Socket Message Bus uses an internal memory-only bus. When multiple application instances are needed, the in-memory bus cannot be used. Instead a [[Plugins|Plugins]] which implements &lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus&lt;/a&gt; must be enabled.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a id="Socket_Message_Bus_Server" name="Socket_Message_Bus_Server"&gt;&lt;/a&gt;Socket Message Bus Server&lt;/h3&gt;
&lt;p&gt;Telligent Telligent Community 7.5 comes with the optionally-installed Socket Message Bus Windows Service and its corresponding &lt;code&gt;ISocketMessageBus&lt;/code&gt; plugin-based connector, &lt;em&gt;Socket Message Bus Service Connector&lt;/em&gt;. This is simply a Windows Service which echoes messages it receives to all connected Telligent Community instances.&lt;/p&gt;
&lt;h3&gt;&lt;a id="Custom_Message_Bus" name="Custom_Message_Bus"&gt;&lt;/a&gt;Custom Message Bus&lt;/h3&gt;
&lt;p&gt;In cases where a community would prefer to use an existing third party message bus solution, custom &lt;a href="/developers/w/developer90/50338.isocketmessagebus-plugin-type"&gt;ISocketMessageBus plugins&lt;/a&gt; can be written against it and deployed. An example could be a message bus service which supports multiple Telligent Community communities on a single bus server by potentially adding an identifier to the string messages sent and received by the plugin for routing the message on the bus server.&lt;/p&gt;
&lt;h3&gt;&lt;a id="Generic_Messages" name="Generic_Messages"&gt;&lt;/a&gt;Generic Messages&lt;/h3&gt;
&lt;p&gt;Custom logic in &lt;code&gt;ISocket&lt;/code&gt; plugins can also make use of the message bus. Generic messages can be useful for keeping realtime state synchronized across application instances. For example, chat presence may be persisted in a database, but cached locally in multiple instances. Since it is important that these caches remain synchronized, presence change messages can be sent and received across the message bus for other app instances&amp;#39; plugins to handle and process.&lt;/p&gt;
&lt;p&gt;The &lt;a href="/developers/w/developer90/50181.isocketcontroller-plugin-supplementary-type"&gt;ISocketController&lt;/a&gt; injected into &lt;a href="/developers/w/developer90/50337.isocket-plugin-type"&gt;ISocket&lt;/a&gt; plugins contains an instance of an &lt;a href="/developers/w/developer90/50167.imessagebuscontroller-plugin-supplementary-type"&gt;IMessageBusController&lt;/a&gt;. The &lt;a href="/developers/w/developer90/50167.imessagebuscontroller-plugin-supplementary-type"&gt;IMessageBusController&lt;/a&gt; exposes events for when generic messages are received from instances of the application along with a method for sending them.&lt;/p&gt;
&lt;p&gt;A useful pattern for state change is to send a generic message to the bus, and only handle it once it is re-received. This allows all instances to know about the state. Additionally, the instance that sends it receives the message immediately without having to wait for the round-trip, and is made aware of the local origin of the message. In this manner, the sender can also be exclusively responsible for potentially persisting the state change elsewhere.&lt;/p&gt;
&lt;pre class="brush: javascript"&gt;controller.MessageBus.Publish(&amp;quot;something.happened&amp;quot;,&amp;quot;&amp;quot;);
controller.MessageBus.Received += (sender, e) =&amp;gt;
{
    if (e.MessageName == &amp;quot;something.happened&amp;quot;)
    {
        // update some local caches
        // ...
        if (e.Source == BusMessageSource.Local)
        {
            // update DB
            // ...
        }
    }
};&lt;/pre&gt;
&lt;h2&gt;&lt;a id="Presence_Services" name="Presence_Services"&gt;&lt;/a&gt;Presence Services&lt;/h2&gt;
&lt;h3&gt;&lt;a id="User_Presence" name="User_Presence"&gt;&lt;/a&gt;User Presence&lt;/h3&gt;
&lt;p&gt;The User Presence service tracks which users are online. &amp;nbsp;The service is responsible for the presence indicator often&amp;nbsp;displayed along side the user&amp;#39;s name. &amp;nbsp;In conjunction with the Content Presence service (discussed below), the service sends socket messages as users go offline and online to update the presence indicators in near real-time for users who are currently viewing&amp;nbsp;the user whose online status has changed.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence.png"&gt;&lt;img src="/resized-image/__size/320x240/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence.png" alt=" " /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The platform has the options for&amp;nbsp;&lt;strong&gt;Enable Presence Tracking&lt;/strong&gt;,&amp;nbsp;&lt;strong&gt;Allow Members To Toggle Presence Tracking Enablement &lt;/strong&gt;and&lt;strong&gt; Default Presence Tracking Enablement Value &amp;nbsp;&lt;/strong&gt;available under Membership in the Membership Options panel in Administration. &amp;nbsp;&lt;strong&gt;Enable Presence Tracking&amp;nbsp;&lt;/strong&gt;controls whether user presence tracking is available for the community. &amp;nbsp;If tracking is enabled, &amp;nbsp;&lt;strong&gt;Allow Members To Toggle Presence Tracking Enablement&lt;/strong&gt; controls whether or not each user should have the option to disable tracking of their online status. If that option is enabled the&amp;nbsp;&lt;strong&gt;Default Presence Tracking Enablement Value&amp;nbsp;&lt;/strong&gt;is also available. &amp;nbsp;If users are giving the option to control their presence tracking, the&amp;nbsp;&lt;strong&gt;Enable presence tracking&lt;/strong&gt; option will be available in the membership settings.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence-admin.png"&gt;&lt;img src="/resized-image/__size/550x539/__key/communityserver-wikis-components-files/00-00-00-12-83/User-Presence-admin.png" alt=" " /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a id="Content_Presence" name="Content_Presence"&gt;&lt;/a&gt;Content Presence&lt;/h3&gt;
&lt;p&gt;The Content Presence service tracks which content users are currently viewing. &amp;nbsp;This enables the platform to update users in real time to changes in content they are currently viewing. &amp;nbsp;The API provides a quantity of users who are currently viewing each content item.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;How is content presence determined?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Page Context: The service uses the page content to track what content the using is currently viewing. &amp;nbsp;For instance if a user is currently viewing a blog post, the content service would be aware that user is currently viewing that blog post, its author, the blog the post belonged to and the group the blog belonged to. &amp;nbsp;&lt;/li&gt;
&lt;li&gt;Html attributes: Html attributes can be added to through the &lt;code&gt;core_v2_contentPresence.RenderAttributes&lt;/code&gt; method. &amp;nbsp;This method will render the proper attributes to automatically track a user&amp;#39;s content presence, when the decorated element is currently visible on the page they are viewing. &amp;nbsp;The comment stream and activity stream are two examples where this method is in use.&lt;/li&gt;
&lt;li&gt;APIs: &amp;nbsp;In Process, Rest and Widget APIs are available to directly add and remove which content a user is present for. &amp;nbsp;Additionally, a summary of the quantity of users viewing each content item is available.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a id="Service_Presence" name="Service_Presence"&gt;&lt;/a&gt;Service Presence&lt;/h3&gt;
&lt;p&gt;The Service Presence service tracks what services a user is currently viewing. &amp;nbsp;When a user is present for a service, messages about changes in that service can be sent to the user&amp;#39;s browser so that browser can be updated to show the latest changes. &amp;nbsp;The activity story service is an example of how this service is used. &amp;nbsp;When an activity story is created, deleted or updated any user that is present to the activity story service will&amp;nbsp;be see that updated of that change and their activity story stream can be updated as needed.&lt;/p&gt;
&lt;p&gt;How do you define a Service Presence service?&lt;/p&gt;
&lt;p&gt;Widgets can define themselves as services, using the&lt;code&gt;&amp;nbsp;core_v2_servicePresence.RenderAttributes&lt;/code&gt; method and passing a unique service identifier. &amp;nbsp;For instance, the activity stream widget can define itself as a service, doing allows users who are currently viewing an activity stream to receive socket messages for new activity stories. &amp;nbsp;Using the Content Presence service alone, would only allow users to receive socket messages to for content that already exists in the activity stream.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;How is service presence determined?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Html attributes: Html attributes can be added to through the &lt;code&gt;core_v2_servicePresence.RenderAttributes&lt;/code&gt; method. &amp;nbsp;This method will render the proper attributes to automatically track a user&amp;#39;s presence to a service, when the decorated element is currently visible on the page they are viewing.&lt;/li&gt;
&lt;li&gt;APIs: &amp;nbsp;In Process, Rest and Widget APIs are available to directly add and remove which service a user is present for. &amp;nbsp;Additionally listing which users are currently present to a service&amp;nbsp;is available in the same APIs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Combining the Content and Service Presence Services with Sockets creates new opportunities to&amp;nbsp;enhance community functionality. &amp;nbsp;The new Live Comment and Thread Forums are two features that make use of the Socket Bus and the Presence Services.&lt;/p&gt;
&lt;h2&gt;&lt;a id="Example_Socket_using_Content_Presence_Service" name="Example_Socket_using_Content_Presence_Service"&gt;&lt;/a&gt;Example Socket using Content Presence Service&lt;/h2&gt;
&lt;p&gt;This example will&amp;nbsp;create an &lt;code&gt;ISocket&lt;/code&gt; implementation that will send socket messages to users when a vote is received or changed on an idea. &amp;nbsp;By combining the socket implementation with the content presence service, the socket messages can be sent only to those users who are currently viewing the idea that received the vote.&lt;/p&gt;
&lt;h3&gt;&lt;a id="Server_Side" name="Server_Side"&gt;&lt;/a&gt;Server Side&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;ISocket&lt;/code&gt; implementation will use the &lt;em&gt;ideavotes&lt;/em&gt; for the &lt;code&gt;SocketName &lt;/code&gt;and maintain a reference to the &lt;code&gt;SocketController&lt;/code&gt; for later use in our example.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;ISocketController _sockets;
public string SocketName =&amp;gt; &amp;quot;ideavotes&amp;quot;;

public void SetController(ISocketController controller)
{
    _sockets = controller;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The example class will need to send a message whenever an idea is&amp;nbsp;voted on, this can be accomplished by attaching to the Idea Vote Events for these actions in our plugin&amp;#39;s &lt;code&gt;Initialize&lt;/code&gt; method. &amp;nbsp;In each event handler, we will call the same method SendVoteCounts passing the idea id for the vote.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public void Initialize()
{
    _ideas = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IIdeas&amp;gt;();

    _ideaVotes = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IVotes&amp;gt;();
    _ideaVotes.Events.AfterCreate += VoteCreated;
    _ideaVotes.Events.AfterDelete += VoteDeleted;
    _ideaVotes.Events.AfterUpdate += VoteUpdated;
}

private void VoteCreated(VoteAfterCreateEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}

private void VoteUpdated(VoteAfterUpdateEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}

private void VoteDeleted(VoteAfterDeleteEventArgs e)
{
    SendVoteCounts(e.IdeaId);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;In the SendVoteCounts method, the number of up and down votes will be retrieved and the&amp;nbsp;&lt;code&gt;_sockets.Clients.SendToUsersPresentToContent &lt;/code&gt;method will be used to send a message to all users who are currently present to that idea.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;void SendVoteCounts(Guid ideaId)
{
    var idea = _ideas.Get(ideaId);
    if (idea != null &amp;amp;&amp;amp; !idea.HasErrors())
    {
        var upVotes =
            _ideaVotes.List(new VotesListOptions() {IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = true });

        var downVotes =
            _ideaVotes.List(new VotesListOptions() { IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = false });

        // send socket message with updated totals
        _sockets.Clients.SendToUsersPresentToContent(idea.ContentId, &amp;quot;ideavoted&amp;quot;, new
        {
            contentId = idea.ContentId,
            contentTypeId = _ideas.ContentTypeId,
            yesVotes = upVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;,
            noVotes = downVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;
        });
    }
}&lt;/pre&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a id="Client_Side" name="Client_Side"&gt;&lt;/a&gt;Client Side&lt;/h3&gt;
&lt;p&gt;Once this plugin is compiled and enabled on the community site, each time an idea is voted on any user who is viewing that idea will receive an &lt;em&gt;ideavoted&amp;nbsp;&lt;/em&gt;socket message. &amp;nbsp;For this example, we can use a widget to see these messages. &amp;nbsp;The example will&amp;nbsp;make use of the&amp;nbsp;&lt;code&gt;$.telligent.evolution.sockets.ideavotes&lt;/code&gt; API that is automatically generated for our &lt;code&gt;ISocket&lt;/code&gt; implementation. &amp;nbsp;That API will enable the widget to listen for messages from the custom socket. &amp;nbsp;In this case, the message&amp;#39;s data will output to the browser&amp;#39;s console window.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="javascript"&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
	jQuery.telligent.evolution.sockets.ideavotes.on(&amp;#39;ideavoted&amp;#39;, function(data) {
		console.log(data);
	});
});
&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The widget can be placed on the Idea page or Idea List page,&amp;nbsp;you will be able to see the messages for the ideas you are currently viewing when any vote is received on the idea(s) you are currently viewing.&lt;/p&gt;
&lt;h3&gt;&lt;a id="Completed_Sample" name="Completed_Sample"&gt;&lt;/a&gt;Completed Sample&lt;/h3&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;using System;
using Telligent.Evolution.Extensibility.Ideation.Api;
using Telligent.Evolution.Extensibility.Sockets.Version1;
using Telligent.Evolution.Extensibility.Version1;

namespace Telligent.Evolution.Examples
{
    public class VoteSocket : IPlugin, ISocket
    {
        ISocketController _sockets;
        IIdeas _ideas;
        IVotes _ideaVotes;

        public string Name =&amp;gt; &amp;quot;Idea Vote Sockets&amp;quot;;
        public string Description =&amp;gt; &amp;quot;Enables live updates to idea votes.&amp;quot;;
        public string SocketName =&amp;gt; &amp;quot;ideavotes&amp;quot;;

        public void Initialize()
        {
            _ideas = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IIdeas&amp;gt;();

            _ideaVotes = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IVotes&amp;gt;();
            _ideaVotes.Events.AfterCreate += VoteCreated;
            _ideaVotes.Events.AfterDelete += VoteDeleted;
            _ideaVotes.Events.AfterUpdate += VoteUpdated;
        }

        public void SetController(ISocketController controller)
        {
            _sockets = controller;
        }

        private void VoteCreated(VoteAfterCreateEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        private void VoteUpdated(VoteAfterUpdateEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        private void VoteDeleted(VoteAfterDeleteEventArgs e)
        {
            SendVoteCounts(e.IdeaId);
        }

        void SendVoteCounts(Guid ideaId)
        {
            var idea = _ideas.Get(ideaId);
            if (idea != null &amp;amp;&amp;amp; !idea.HasErrors())
            {
                var upVotes =
                    _ideaVotes.List(new VotesListOptions() {IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = true });

                var downVotes =
                    _ideaVotes.List(new VotesListOptions() { IdeaId = idea.ContentId, PageIndex = 0, PageSize = 1, Value = false });

                // send socket message with updated totals
                _sockets.Clients.SendToUsersPresentToContent(idea.ContentId, &amp;quot;ideavoted&amp;quot;, new
                {
                    contentId = idea.ContentId,
                    contentTypeId = _ideas.ContentTypeId,
                    yesVotes = upVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;,
                    noVotes = downVotes?.TotalCount.ToString() ?? &amp;quot;0&amp;quot;
                });
            }
        }
    }
}
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="xml"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;
&amp;lt;scriptedContentFragments&amp;gt;
  &amp;lt;scriptedContentFragment name=&amp;quot;Idea Socket Presence Test&amp;quot; version=&amp;quot;10.0.0.0&amp;quot; description=&amp;quot;&amp;quot; instanceIdentifier=&amp;quot;c7e0a2c7d2b44ab08f22d8938ef03a06&amp;quot; theme=&amp;quot;&amp;quot; isCacheable=&amp;quot;false&amp;quot; varyCacheByUser=&amp;quot;false&amp;quot; showHeaderByDefault=&amp;quot;false&amp;quot; cssClass=&amp;quot;&amp;quot; provider=&amp;quot;7bb87a0cc5864a9392ae5b9e5f9747b7&amp;quot;&amp;gt;
    &amp;lt;contentScript&amp;gt;&amp;lt;![CDATA[

&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
jQuery.telligent.evolution.messaging.subscribe(&amp;#39;socket.connected&amp;#39;, function() {
			jQuery.telligent.evolution.sockets.ideavotes.on(&amp;#39;ideavoted&amp;#39;, function(data) {
				console.log(data);
			});
});
&amp;lt;/script&amp;gt;

]]&amp;gt;&amp;lt;/contentScript&amp;gt;
  &amp;lt;/scriptedContentFragment&amp;gt;
&amp;lt;/scriptedContentFragments&amp;gt;&lt;/pre&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a id="Tips_and_Tricks" name="Tips_and_Tricks"&gt;&lt;/a&gt;Tips and Tricks&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Sockets can only be used by authenticated, non-system users&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item></channel></rss>