Search in sources :

Example 1 with SalesforceConsumer

use of org.apache.camel.component.salesforce.SalesforceConsumer in project camel by apache.

the class SubscriptionHelper method doStart.

@Override
protected void doStart() throws Exception {
    // create CometD client
    this.client = createClient(component);
    // reset all error conditions
    handshakeError = null;
    handshakeException = null;
    connectError = null;
    connectException = null;
    // listener for handshake error or exception
    if (handshakeListener == null) {
        // first start
        handshakeListener = new ClientSessionChannel.MessageListener() {

            public void onMessage(ClientSessionChannel channel, Message message) {
                LOG.debug("[CHANNEL:META_HANDSHAKE]: {}", message);
                if (!message.isSuccessful()) {
                    LOG.warn("Handshake failure: {}", message);
                    handshakeError = (String) message.get(ERROR_FIELD);
                    handshakeException = getFailure(message);
                    if (handshakeError != null) {
                        // refresh oauth token, if it's a 401 error
                        if (handshakeError.startsWith("401::")) {
                            try {
                                LOG.info("Refreshing OAuth token...");
                                session.login(session.getAccessToken());
                                LOG.info("Refreshed OAuth token for re-handshake");
                            } catch (SalesforceException e) {
                                LOG.error("Error renewing OAuth token on 401 error: " + e.getMessage(), e);
                            }
                        }
                    }
                    // restart if handshake fails for any reason
                    restartClient();
                } else if (!listenerMap.isEmpty()) {
                    reconnecting = true;
                }
            }
        };
    }
    client.getChannel(META_HANDSHAKE).addListener(handshakeListener);
    // listener for connect error
    if (connectListener == null) {
        connectListener = new ClientSessionChannel.MessageListener() {

            public void onMessage(ClientSessionChannel channel, Message message) {
                LOG.debug("[CHANNEL:META_CONNECT]: {}", message);
                if (!message.isSuccessful()) {
                    LOG.warn("Connect failure: {}", message);
                    connectError = (String) message.get(ERROR_FIELD);
                    connectException = getFailure(message);
                } else if (reconnecting) {
                    reconnecting = false;
                    LOG.debug("Refreshing subscriptions to {} channels on reconnect", listenerMap.size());
                    // reconnected to Salesforce, subscribe to existing channels
                    final Map<SalesforceConsumer, ClientSessionChannel.MessageListener> map = new HashMap<SalesforceConsumer, ClientSessionChannel.MessageListener>();
                    map.putAll(listenerMap);
                    listenerMap.clear();
                    for (Map.Entry<SalesforceConsumer, ClientSessionChannel.MessageListener> entry : map.entrySet()) {
                        final SalesforceConsumer consumer = entry.getKey();
                        final String topicName = consumer.getTopicName();
                        subscribe(topicName, consumer);
                    }
                }
            }
        };
    }
    client.getChannel(META_CONNECT).addListener(connectListener);
    // handle fatal disconnects by reconnecting asynchronously
    if (disconnectListener == null) {
        disconnectListener = new ClientSessionChannel.MessageListener() {

            @Override
            public void onMessage(ClientSessionChannel clientSessionChannel, Message message) {
                restartClient();
            }
        };
    }
    client.getChannel(META_DISCONNECT).addListener(disconnectListener);
    // connect to Salesforce cometd endpoint
    client.handshake();
    final long waitMs = MILLISECONDS.convert(CONNECT_TIMEOUT, SECONDS);
    if (!client.waitFor(waitMs, BayeuxClient.State.CONNECTED)) {
        if (handshakeException != null) {
            throw new CamelException(String.format("Exception during HANDSHAKE: %s", handshakeException.getMessage()), handshakeException);
        } else if (handshakeError != null) {
            throw new CamelException(String.format("Error during HANDSHAKE: %s", handshakeError));
        } else if (connectException != null) {
            throw new CamelException(String.format("Exception during CONNECT: %s", connectException.getMessage()), connectException);
        } else if (connectError != null) {
            throw new CamelException(String.format("Error during CONNECT: %s", connectError));
        } else {
            throw new CamelException(String.format("Handshake request timeout after %s seconds", CONNECT_TIMEOUT));
        }
    }
}
Also used : Message(org.cometd.bayeux.Message) HashMap(java.util.HashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) SalesforceException(org.apache.camel.component.salesforce.api.SalesforceException) SalesforceConsumer(org.apache.camel.component.salesforce.SalesforceConsumer) CamelException(org.apache.camel.CamelException) ClientSessionChannel(org.cometd.bayeux.client.ClientSessionChannel) HashMap(java.util.HashMap) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap)

Example 2 with SalesforceConsumer

use of org.apache.camel.component.salesforce.SalesforceConsumer in project camel by apache.

the class SubscriptionHelper method restartClient.

// launch an async task to restart
private void restartClient() {
    // launch a new restart command
    final SalesforceHttpClient httpClient = component.getConfig().getHttpClient();
    httpClient.getExecutor().execute(new Runnable() {

        @Override
        public void run() {
            LOG.info("Restarting on unexpected disconnect from Salesforce...");
            boolean abort = false;
            // wait for disconnect
            LOG.debug("Waiting to disconnect...");
            while (!client.isDisconnected()) {
                try {
                    Thread.sleep(DISCONNECT_INTERVAL);
                } catch (InterruptedException e) {
                    LOG.error("Aborting restart on interrupt!");
                    abort = true;
                }
            }
            if (!abort) {
                // update restart attempt backoff
                final long backoff = restartBackoff.getAndAdd(backoffIncrement);
                if (backoff > maxBackoff) {
                    LOG.error("Restart aborted after exceeding {} msecs backoff", maxBackoff);
                    abort = true;
                } else {
                    // pause before restart attempt
                    LOG.debug("Pausing for {} msecs before restart attempt", backoff);
                    try {
                        Thread.sleep(backoff);
                    } catch (InterruptedException e) {
                        LOG.error("Aborting restart on interrupt!");
                        abort = true;
                    }
                }
                if (!abort) {
                    Exception lastError = new SalesforceException("Unknown error", null);
                    try {
                        // reset client
                        doStop();
                        // register listeners and restart
                        doStart();
                    } catch (Exception e) {
                        LOG.error("Error restarting: " + e.getMessage(), e);
                        lastError = e;
                    }
                    if (client.isHandshook()) {
                        LOG.info("Successfully restarted!");
                        // reset backoff interval
                        restartBackoff.set(client.getBackoffIncrement());
                    } else {
                        LOG.error("Failed to restart after pausing for {} msecs", backoff);
                        if ((backoff + backoffIncrement) > maxBackoff) {
                            // notify all consumers
                            String abortMsg = "Aborting restart attempt due to: " + lastError.getMessage();
                            SalesforceException ex = new SalesforceException(abortMsg, lastError);
                            for (SalesforceConsumer consumer : listenerMap.keySet()) {
                                consumer.handleException(abortMsg, ex);
                            }
                        }
                    }
                }
            }
        }
    });
}
Also used : SalesforceException(org.apache.camel.component.salesforce.api.SalesforceException) SalesforceConsumer(org.apache.camel.component.salesforce.SalesforceConsumer) SalesforceHttpClient(org.apache.camel.component.salesforce.SalesforceHttpClient) CamelException(org.apache.camel.CamelException) SalesforceException(org.apache.camel.component.salesforce.api.SalesforceException)

Aggregations

CamelException (org.apache.camel.CamelException)2 SalesforceConsumer (org.apache.camel.component.salesforce.SalesforceConsumer)2 SalesforceException (org.apache.camel.component.salesforce.api.SalesforceException)2 HashMap (java.util.HashMap)1 Map (java.util.Map)1 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)1 SalesforceHttpClient (org.apache.camel.component.salesforce.SalesforceHttpClient)1 Message (org.cometd.bayeux.Message)1 ClientSessionChannel (org.cometd.bayeux.client.ClientSessionChannel)1