So, imagine you’re building a modern web app (or page) and need to update some element on the page in near-real time, perhaps an open inventory quantity to prevent data conflicts upstream. The point being that the immediacy of update of the data plays a fundamental role in the business process. What are the options? Historically an interaction of this type would require a full page refresh, and as such would push the application toward a non-web delivery model. Then partial page updates became popular; we could then consider some form of client-initiated polling (JavaScript timer or otherwise). This client-initiated “Pull” model would satisfy the requirement, with a possible benefit of offloading the expensive polling activity to client agent, all the server needs to do is expose a lightweight (probably stateless) endpoint to return the calculated data. Excellent. However, as anyone implementing such an approach will know – there’s something slightly unedifying about the “Pull” model – you can never really tune the poll frequency to the right balance of data update frequency versus the feeling of wasting server resources. We should also strive to minimise how much trust we put in the client. In the Force.com context, unnecessary polling activity also comes with the cost of consumption of limited API calls – this is a key point. In an ideal world perhaps, the server could somehow just notify the client when the data has definitely changed with no redundant polling, wasted callouts or unnecessary server resource consumption. Enter the Force.com Streaming API.
The Force.com Streaming API provides a server-initiated “Push Model”, where notifications of changes to data of interest can be sent to internal pages (Visualforce), external app servers and external clients. The latter point being interesting in that the use cases for the API aren’t limited to simple UI updates, external system-type services can also be be subscribers in the model. The API is founded on the cometD stack and utilises the long polling technique where an almost persistent client-to-server connection used, i.e. the server holds the client request open until a response is available, once returned the client immediately re-requests the data thereby opening a new connection.
To use this API, a PushTopic is defined using a SOQL query construct and exposed via a Channel. Clients then subscribe to the channel and receive notifications when DML events occur that affect records covered by the SOQL query WHERE clause. PushTopics can notify on Insert and/or Update operations, this can be configured. Also, PushTopics can generate notifications for records matching the SOQL WHERE clause in response to any field change, or just changes to fields referenced in the SELECT clause or a WHERE clause predicate – or both. There is currently no UI for the creation of PushTopics, therefore Apex script must be used – executed perhaps via the Developer Console or Execute Anonymous tab in the Force.com IDE. Not ideal.
Supporting technology
Bayeux protocol – standard protocol for transportation of asynchronous messages – typically in an HTTP context.
CometD – implementation of the Bayeux protocol using the AJAX push technology pattern referred to as Comet. Reference: http://cometd.org.
JSON – notifications are formatted as JSON messages.
Key points
– Stateless model – no server persistence of client state – fire-and-forget from the server perspective.
– Bulk API operations do not initiate notifications – for obvious reasons.
– Server processing of new PushTopic notifications occurs every 3 seconds, therefore this becomes the maximum frequency of update from the client perspective.
– PushTopic construct – each PushTopic relates to one object (Custom or Standard). The SELECT clause must include the Id field, other fields are sent via the channel. Join and aggregation operations are not supported – also formula fields are not supported, which is a surprising limitation.
– Browser support is limited to IE8+ and FF4+.
– Client cookie support is required.
– A limit of 10 subscribing clients is enforced per PushTopic, with a maximum of 20 PushTopics in total. This again is surprising, as 10 clients per-topic is unrealistic for usage in a multi-user web-app. The documentation does suggest however that this soft-limit can be increased through contacting salesforce.com support. There may be a cost implication here.
– A number of JavaScript libraries must be added to each Visualforce page, via a static resource preferably. Use a page template, or page composition if possible to isolate the references.
– The API requires a reasonable level of JavaScript expertise.
Summary
The Force.com Streaming API adds native support for server-initiated “Push” models – helping to limit consumption of expensive API callouts in some circumstances. The key imitations to be aware of are that the API does not enable client-control over the scope of the data pushed from the server, and that the subscribers per PushTopic is limited to 10. With the former, it isn’t possible to limit the scope of notifications to a single Account as an example – therefore a web page would receive notifications for all Accounts. Careful consideration must be to the design and purpose of each topic, with a focus on maximising specificity.