/ salesforce

Streaming API goes silent ๐Ÿ™‰

Salesforce's Streaming API provides real-time, push-oriented data to external apps. As Salesforce delivers more and more event-oriented features, this API continues to evolve. Nowadays, people rely on the Streaming API to power enterprise message busses and data warehouse synchronizations. That's a lot of business value coming from the decade-old, Bayeux pub/sub over HTTP messaging protocol!

Salesforce's newest Spring '18 release notes contain this nugget:

Handle Invalid Connections in Streaming API

A Streaming API client is now notified with an error when the client authentication becomes invalid. After receiving the error, the client can reauthenticate and reconnect to receive new events. Otherwise, the client doesnโ€™t receive any events. This change applies to all API versionsโ€ฆ

Hold up ๐Ÿ˜ต๐Ÿ›‘ This means Streaming API subscribers that do not detect this new condition will eventually, silently fail to receive new data. Connections hang. Progress stalls. No error thrown. I've recently observed that streaming data stalls after 3-hours.

The release notes article continues to describe the criteria to detect this condition, but unfortunately it is not entirely accurate. I found another message indicating this invalid condition:

{
  "ext": {
    "sfdc": {
      "failureReason": "401::Authentication invalid"
    }
  },
  "advice": {
    "reconnect": "none"
  },
  "channel": "/meta/handshake",
  "error": "403::Handshake denied",
  "successful": false
}

In our JavaScript/Node Streaming API subscriber app, we detect this condition using a small Faye client extension:

var AuthFailureExtension = function() {
  this.incoming = function(message, callback) {
    if (
      (message.channel === '/meta/connect' ||
        message.channel === '/meta/handshake')
      && message.advice
      && message.advice.reconnect == 'none'
    ) {
      console.error(
        "Exiting because Salesforce authentication was lost: ",
        message.error
      );
      process.exit(1);
    }
    callback(message);
  }
};

โ€ฆand load it into the client, like this:

client.addExtension(new AuthFailureExtension());

Whenever this new error condition is detected, the process exits. Our process manager for the server immediately restarts the app โ™ป๏ธ which freshly authenticates and continues where it left off using Event Replay ๐Ÿ•บ

I have a feeling this new Streaming API requirement will take many people by surprise. While I am not associated with the Salesforce API, I'm definitely interested to hear about your experiences! Tweets welcome ๐Ÿ’™๐Ÿฆ

Article updated 2018-01-02 to clarify that there are multiple error conditions that require resetting the client.