'Cometd/bayeux client Issue
We have created .Net core windows service for consuming platform events from Salesforce(whenever a particular object created/updated in Salesforce want to fetch the information).We are using Cometd/bayeux client for subscribing Salesforce platforms events.
Initially everything working fine we are getting data whenever a change happened in Salesforce object,but after few idle hours(around 1-2 hrs) no data is getting.Check the bayeux client status and it shown as connected but the subscription is not happening.When we restart the service it's started working. Using below code for connection and subscription. Can any one please help on this.
public void CheckAndSubscribe()
{
if (!_bayeuxClient.IsConnected())
{
_logger.LogInformation("Bayeux client not connected. trying to connect...");
try
{
SalesforceSession salesforceSessionData = _sfSessionAdapter.GetSalesforceSession();
_bayeuxClient.Connect(salesforceSessionData.Url, salesforceSessionData.SessionId);
List<string> sfChannels = _syncSalesforceConfiguration.BayeuxClientConfiguration.ExternalChannels;
foreach (string channel in sfChannels)
{
_bayeuxClient.Subscribe(channel, _messageListener);
}
_logger.LogInformation("Bayeux client connected and channels subscribed...");
}
catch (Exception ex)
{
_logger.LogException(ex);
}
}
}
public class BayeuxClientAdapter : IBayeuxClientAdapter
{
BayeuxClient _bayeuxClient = null;
private readonly SyncSalesforceConfiguration _syncSalesforceConfiguration;
public BayeuxClientAdapter(IOptions<SyncSalesforceConfiguration> syncSalesforceConfiguration)
{
_syncSalesforceConfiguration = syncSalesforceConfiguration.Value;
}
public bool IsConnected()
{
return _bayeuxClient?.Connected ?? false;
}
public void Connect(string instanceUrl, string authToken)
{
int readTimeOut = 120 * 1000;
string streamingEndpointURI = _syncSalesforceConfiguration.BayeuxClientConfiguration.StreamingEndpointUri;
IDictionary<string, object> options = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase)
{
{ ClientTransport.TIMEOUT_OPTION, readTimeOut },
{ ClientTransport.MAX_NETWORK_DELAY_OPTION, 120000 }
};
var headers = new NameValueCollection { { HttpRequestHeader.Authorization.ToString(), $"OAuth {authToken}" } };
var clientTransport = new LongPollingTransport(options, headers);
var serverUri = new Uri(instanceUrl);
String endpoint = String.Format("{0}://{1}{2}", serverUri.Scheme, serverUri.Host, streamingEndpointURI);
_bayeuxClient = new BayeuxClient(endpoint, new[] { clientTransport });
}
public void DisConnect()
{
if (IsConnected())
{
_bayeuxClient?.ResetSubscriptions();
_bayeuxClient?.Disconnect();
_bayeuxClient?.WaitFor(1000, new[] { BayeuxClient.State.DISCONNECTED });
}
}
public void Subscribe(string channel, IMessageListener listener)
{
_bayeuxClient.Handshake();
_bayeuxClient.WaitFor(1000, new[] { BayeuxClient.State.CONNECTED });
var sfChannel = _bayeuxClient.GetChannel(channel);
sfChannel.Subscribe(listener);
}
}
Solution 1:[1]
Whenever there is no activity on the channel, the server closes the connection after a specific time.
In that time client receives a 403 (Unknown client) status code, and the client has to handshake again withing 110 seconds.
By default, CometD tries to reconnect without any user interaction and If the client doesn't reconnect within the expected time, the server removes the client's CometD session.
Once the connection gets reconnect, all the channel subscriptions will be removed by ComedD, and we have to subscribe to the channel again in order to receive events.
In order to do so, we have to make use of meta/Handshake callback to resubscribe to the channel again.
Solution 2:[2]
I found I had to subscribe the meta/unsuccessful event and re-establish the CometD connection and subscriptions. That allowed the client to recover fully from being disconnected by Salesforce's server.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Jasneet Dua |
Solution 2 | saille |