![JAR search and dependency download from the Maven repository](/logo.png)
net.sf.jabb.dstream.eventhub.EventHubQpidStreamDataSupplier Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jabb-core-java8 Show documentation
Show all versions of jabb-core-java8 Show documentation
Additions to jabb-core that require Java 8
The newest version!
/**
*
*/
package net.sf.jabb.dstream.eventhub;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.function.Predicate;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.Queue;
import javax.jms.QueueBrowser;
import javax.jms.Session;
import net.sf.jabb.dstream.StreamDataSupplierWithId;
import net.sf.jabb.dstream.StreamDataSupplierWithIdAndEnqueuedTimeRange;
import net.sf.jabb.dstream.SimpleStreamDataSupplierWithId;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Throwables;
import com.google.common.util.concurrent.UncheckedTimeoutException;
import net.sf.jabb.azure.AzureEventHubUtility;
import net.sf.jabb.azure.EventHubAnnotations;
import net.sf.jabb.dstream.JmsConsumerStreamDataSupplier;
import net.sf.jabb.dstream.WrappedJmsConnection;
import net.sf.jabb.dstream.ex.DataStreamInfrastructureException;
import net.sf.jabb.util.jms.JmsUtility;
import net.sf.jabb.util.parallel.BackoffStrategies;
import net.sf.jabb.util.parallel.BackoffStrategy;
import net.sf.jabb.util.parallel.Sequencer;
import net.sf.jabb.util.parallel.WaitStrategies;
import net.sf.jabb.util.parallel.WaitStrategy;
import net.sf.jabb.util.text.DurationFormatter;
/**
* Stream data supplier for accessing messages in Azure Event Hub through Qpid JMS.
* It defines position range as (startPosition, endPosition].
* It is assumed that x-opt-offset is a Long number.
* @author James Hu
*
*/
public class EventHubQpidStreamDataSupplier extends JmsConsumerStreamDataSupplier {
private static final Logger logger = LoggerFactory.getLogger(EventHubQpidStreamDataSupplier.class);
protected static long RECEIVE_MUST_EXIST_MESSAGE_WAIT_MILLIS = 10_000L;
protected Function messageConverter;
protected WrappedJmsConnection wrappedConnection;
protected static final Sequencer idSequencer = new Sequencer();
protected String identifier;
protected WaitStrategy waitStrategy;
/**
* Constructor
* @param connectionFactory JMS connection factory
* @param destination JMS destination
* @param connectionValidator predicate for validating JMS connection
* @param connectBackoffStrategy backoff strategy for retrying connection establishment
* @param waitStrategy wait strategy for retrying connection establishment and other operations
* @param messageConverter converter for converting JMS messages
*/
public EventHubQpidStreamDataSupplier(ConnectionFactory connectionFactory, Queue destination, Predicate connectionValidator,
BackoffStrategy connectBackoffStrategy, WaitStrategy waitStrategy,
Function messageConverter){
Validate.notNull(connectionFactory, "connection factory cannot be null");
Validate.notNull(destination, "destination cannot be null");
Validate.notNull(connectionValidator, "connection validator cannot be null");
Validate.notNull(connectBackoffStrategy, "connect backoff strategy cannot be null");
Validate.notNull(waitStrategy, "wait strategy cannot be null");
Validate.notNull(messageConverter, "message converter cannot be null");
this.waitStrategy = waitStrategy;
this.messageConverter = messageConverter;
this.destination = destination;
try {
this.identifier = connectionFactory.toString() + "->" + destination.getQueueName();
} catch (JMSException e) {
this.identifier = connectionFactory.toString() + "->UNKNOWN";
}
this.wrappedConnection = new WrappedJmsConnection(connectionFactory, connectionValidator, connectBackoffStrategy, waitStrategy, false);
}
/**
* Constructor with default backoff strategy and wait strategy:
* BackoffStrategies.fibonacciBackoff(1000, 20, TimeUnit.SECONDS), WaitStrategies.threadSleepStrategy()
*
* @param host something like your_name_space.servicebus.windows.net
* @param eventHubName name of the Event Hub
* @param policyName something like ReceiveRule
* @param policyKey the key of the policy
* @param consumerGroup consumer gorup, or null for the default one '$Default'
* @param partition partition number
* @param messageConverter converter for converting JMS messages
*/
public EventHubQpidStreamDataSupplier(String host, String eventHubName, String policyName, String policyKey,
String consumerGroup, String partition, Function messageConverter){
this(host, eventHubName, policyName, policyKey, consumerGroup, partition,
BackoffStrategies.fibonacciBackoff(1000, 20, TimeUnit.SECONDS),
WaitStrategies.threadSleepStrategy(),
messageConverter);
}
/**
* Constructor with default backoff strategy and wait strategy:
* BackoffStrategies.fibonacciBackoff(1000, 20, TimeUnit.SECONDS), WaitStrategies.threadSleepStrategy()
*
* @param host something like your_name_space.servicebus.windows.net
* @param eventHubName name of the Event Hub
* @param policyName something like ReceiveRule
* @param policyKey the key of the policy
* @param consumerGroup consumer gorup, or null for the default one '$Default'
* @param partition partition number
* @param messageConverter converter for converting JMS messages
*/
public EventHubQpidStreamDataSupplier(String host, String eventHubName, String policyName, String policyKey,
String consumerGroup, int partition, Function messageConverter){
this(host, eventHubName, policyName, policyKey, consumerGroup, String.valueOf(partition),
BackoffStrategies.fibonacciBackoff(1000, 20, TimeUnit.SECONDS),
WaitStrategies.threadSleepStrategy(),
messageConverter);
}
/**
* Constructor
* @param server something like your_name_space.servicebus.windows.net
* @param eventHubName name of the Event Hub
* @param policyName something like ReceiveRule
* @param policyKey the key of the policy
* @param consumerGroup consumer gorup, or null for the default one '$Default'
* @param partition partition number
* @param connectBackoffStrategy backoff strategy for retrying connection establishment
* @param connectWaitStrategy wait strategy for retrying connection establishment
* @param messageConverter converter for converting JMS messages
*/
public EventHubQpidStreamDataSupplier(String server, String eventHubName, String policyName, String policyKey,
String consumerGroup, int partition,
BackoffStrategy connectBackoffStrategy, WaitStrategy connectWaitStrategy, Function messageConverter){
this(server, eventHubName, policyName, policyKey, consumerGroup, String.valueOf(partition),
connectBackoffStrategy, connectWaitStrategy, messageConverter);
}
/**
* Constructor
* @param server something like your_name_space.servicebus.windows.net
* @param eventHubName name of the Event Hub
* @param policyName something like ReceiveRule
* @param policyKey the key of the policy
* @param consumerGroup consumer gorup, or null for the default one '$Default'
* @param partition partition number
* @param connectBackoffStrategy backoff strategy for retrying connection establishment
* @param connectWaitStrategy wait strategy for retrying connection establishment
* @param messageConverter converter for converting JMS messages
*/
public EventHubQpidStreamDataSupplier(String server, String eventHubName, String policyName, String policyKey,
String consumerGroup, String partition,
BackoffStrategy connectBackoffStrategy, WaitStrategy connectWaitStrategy, Function messageConverter){
Validate.notBlank(server, "server cannot be blank");
Validate.notBlank(eventHubName, "Event Hub name cannot be blank");
Validate.notBlank(policyName, "access policy name cannot be blank");
Validate.notBlank(policyKey, "access policy key cannot be blank");
Validate.notNull(connectBackoffStrategy, "connect backoff strategy cannot be null");
Validate.notNull(connectWaitStrategy, "connect wait strategy cannot be null");
Validate.notNull(messageConverter, "message converter cannot be null");
String clientId = makeClientId();
this.messageConverter = messageConverter;
this.destination = createQueue(eventHubName, consumerGroup, partition);
this.identifier = clientId + "->" + policyName + ":" + server + "/" + eventHubName + "/" + consumerGroup + "/" + partition;
this.wrappedConnection = createConnectionForReceiving(server, policyName, policyKey, destination,
connectBackoffStrategy, connectWaitStrategy);
}
/**
* Create a list of {@link SimpleStreamDataSupplierWithId}s from an Event Hub.
* @param type of the message
* @param server the server name containing name space of the Event Hub
* @param policyName policy with read permission
* @param policyKey key of the policy
* @param eventHubName name of the Event Hub
* @param consumerGroup consumer group name
* @param messageConverter JMS message converter
* @return a list of {@link SimpleStreamDataSupplierWithId}s, one per partition
* @throws JMSException If list of partitions cannot be fetched
*/
public static List> create(String server, String policyName, String policyKey,
String eventHubName, String consumerGroup, Function messageConverter) throws JMSException{
return create(server, policyName, policyKey, eventHubName, consumerGroup, messageConverter, null);
}
/**
* Create a list of {@link SimpleStreamDataSupplierWithId}s from an Event Hub, with fromEnqueuedTime specified.
* @param type of the message
* @param server the server name containing name space of the Event Hub
* @param policyName policy with read permission
* @param policyKey key of the policy
* @param eventHubName name of the Event Hub
* @param consumerGroup consumer group name
* @param messageConverter JMS message converter
* @param fromEnqueuedTime The time that data items provided by stream data supplier must not be enqueued earlier than.
* It can be null which means that the data items provided can be enqueued at any time.
* @return a list of {@link SimpleStreamDataSupplierWithId}s, one per partition
* @throws JMSException If list of partitions cannot be fetched
*/
public static List> create(String server, String policyName, String policyKey,
String eventHubName, String consumerGroup, Function messageConverter,
Instant fromEnqueuedTime) throws JMSException{
String[] partitions = AzureEventHubUtility.getPartitions(server, policyName, policyKey, eventHubName);
List> suppliers = new ArrayList<>(partitions.length);
for (String partition: partitions){
EventHubQpidStreamDataSupplier supplier = new EventHubQpidStreamDataSupplier<>(server, eventHubName, policyName, policyKey,
consumerGroup, partition, messageConverter);
suppliers.add(fromEnqueuedTime == null ?
new SimpleStreamDataSupplierWithId<>(partition, supplier) :
new StreamDataSupplierWithIdAndEnqueuedTimeRange<>(partition, supplier, fromEnqueuedTime, null));
}
return suppliers;
}
static protected String makeClientId(){
return EventHubQpidStreamDataSupplier.class.getSimpleName() + "-" + idSequencer.next() + "@" + getHostName();
}
static protected String getHostName(){
String hostname = "";
try {
hostname = InetAddress.getLocalHost().getHostName().toLowerCase();
} catch (UnknownHostException e) {
hostname = "";
}
return hostname;
}
static public ConnectionFactory createConnectionFactory(String server, String policyName, String policyKey){
return createConnectionFactory(server, policyName, policyKey, null);
}
/**
* Create a connection factory without setting the syncPublish property
* @param server server domain name or ip address
* @param policyName policy name
* @param policyKey policy key
* @param eventHubName name of the event hub, will only be used in log messages
* @return the connection factory
*/
static public ConnectionFactory createConnectionFactory(String server, String policyName, String policyKey, String eventHubName){
return createConnectionFactory(server, policyName, policyKey, eventHubName, null);
}
/**
* Create a connection factory
* @param server server domain name or ip address
* @param policyName policy name
* @param policyKey policy key
* @param eventHubName name of the event hub, will only be used in log messages
* @param syncPublish whether to wait for acknowledgement after publish
* @return the connection factory
*/
static public ConnectionFactory createConnectionFactory(String server, String policyName, String policyKey, String eventHubName, Boolean syncPublish){
EventHubQpidConnectionFactory connectionFactory = new EventHubQpidConnectionFactory(
"amqps", server, 5671, policyName, policyKey, makeClientId(),
server, true, 0, eventHubName, syncPublish);
return connectionFactory;
}
static public WrappedJmsConnection createConnection(String server, String policyName, String policyKey,
BackoffStrategy connectBackoffStrategy, WaitStrategy connectWaitStrategy,
Predicate connectionValidator, String eventHubName, Boolean syncPublish){
ConnectionFactory connectionFactory = createConnectionFactory(server, policyName, policyKey, eventHubName, syncPublish);
return new WrappedJmsConnection(connectionFactory,
connectionValidator,
connectBackoffStrategy,
connectWaitStrategy,
false);
}
static public WrappedJmsConnection createConnection(String server, String policyName, String policyKey,
BackoffStrategy connectBackoffStrategy, WaitStrategy connectWaitStrategy,
Predicate connectionValidator, String eventHubName){
return createConnection(server, policyName, policyKey, connectBackoffStrategy, connectWaitStrategy, connectionValidator, eventHubName, null);
}
static public WrappedJmsConnection createConnection(String server, String policyName, String policyKey,
BackoffStrategy connectBackoffStrategy, WaitStrategy connectWaitStrategy,
Predicate connectionValidator, Boolean syncPublish){
return createConnection(server, policyName, policyKey, connectBackoffStrategy, connectWaitStrategy, connectionValidator, null, syncPublish);
}
static public WrappedJmsConnection createConnection(String server, String policyName, String policyKey,
BackoffStrategy connectBackoffStrategy, WaitStrategy connectWaitStrategy,
Predicate connectionValidator){
return createConnection(server, policyName, policyKey, connectBackoffStrategy, connectWaitStrategy, connectionValidator, null, null);
}
static public WrappedJmsConnection createConnectionForReceiving(String server, String policyName, String policyKey,
Destination eventHub,
BackoffStrategy connectBackoffStrategy, WaitStrategy connectWaitStrategy){
return createConnection(server, policyName, policyKey, connectBackoffStrategy, connectWaitStrategy,
conn -> WrappedJmsConnection.validateConnectionByCreatingConsumer(conn, eventHub), getQueueName(eventHub));
}
static public WrappedJmsConnection createConnectionForReceiving(String server, String policyName, String policyKey,
Destination eventHub,
BackoffStrategy connectBackoffStrategy, WaitStrategy connectWaitStrategy,
Boolean syncPublish){
return createConnection(server, policyName, policyKey, connectBackoffStrategy, connectWaitStrategy,
conn -> WrappedJmsConnection.validateConnectionByCreatingConsumer(conn, eventHub), getQueueName(eventHub), syncPublish);
}
static public WrappedJmsConnection createConnectionForSending(String server, String policyName, String policyKey,
Destination eventHub,
BackoffStrategy connectBackoffStrategy, WaitStrategy connectWaitStrategy,
String clientId){
return createConnection(server, policyName, policyKey, connectBackoffStrategy, connectWaitStrategy,
conn -> WrappedJmsConnection.validateConnectionByCreatingProducer(conn, eventHub), getQueueName(eventHub));
}
static public WrappedJmsConnection createConnectionForSending(String server, String policyName, String policyKey,
Destination eventHub,
BackoffStrategy connectBackoffStrategy, WaitStrategy connectWaitStrategy,
String clientId, Boolean syncPublish){
return createConnection(server, policyName, policyKey, connectBackoffStrategy, connectWaitStrategy,
conn -> WrappedJmsConnection.validateConnectionByCreatingProducer(conn, eventHub), getQueueName(eventHub), syncPublish);
}
static public String getQueueName(Destination d){
if (d instanceof Queue){
try {
return ((Queue)d).getQueueName();
} catch (JMSException e) {
throw Throwables.propagate(e);
}
}else{
return d.toString();
}
}
static public Queue createQueue(String eventHubName, String consumerGroup, String partition){
org.apache.qpid.amqp_1_0.jms.impl.QueueImpl eventHub = org.apache.qpid.amqp_1_0.jms.impl.QueueImpl.valueOf(
eventHubName + "/ConsumerGroups/" + (consumerGroup == null ? "$Default" : consumerGroup) + "/Partitions/" + partition);
return eventHub;
}
static public Queue createQueue(String eventHubName, String consumerGroup, int partition){
return createQueue(eventHubName, consumerGroup, String.valueOf(partition));
}
static public Queue createQueue(String eventHubName){
org.apache.qpid.amqp_1_0.jms.impl.QueueImpl eventHub = org.apache.qpid.amqp_1_0.jms.impl.QueueImpl.valueOf(
eventHubName);
return eventHub;
}
/**
* {@inheritDoc}
* This method always returns -1.
*/
@Override
public String firstPosition() {
return String.valueOf(-1);
}
@Override
public Instant enqueuedTime(String position) throws DataStreamInfrastructureException{
String selector = "amqp.annotation.x-opt-offset >= '" + position + "'";
Message msg = null;
try {
msg = firstMessageByReceive(selector, RECEIVE_MUST_EXIST_MESSAGE_WAIT_MILLIS); // the message must have existed, but it may not exist now because the server may purge old messages
if (msg == null){
logger.warn("Null message received for position {}, perhaps the message had been purged?", position);
return null;
}
EventHubAnnotations annotations = AzureEventHubUtility.getEventHubAnnotations(msg);
return annotations.getEnqueuedTime();
} catch (JMSException | InterruptedException e) {
throw new DataStreamInfrastructureException(e);
}
}
/**
* {@inheritDoc}
* This method returns (offset of the first message after (exclusive) enqueuedAfter
) - 1 if there is at least a message after enquedTimeNoEarlyThan
.
* Null is returned if there is no message enqueued after enqueuedAfter
* @throws InterruptedException if got interrupted
* @throws DataStreamInfrastructureException if any JMS level error happened
*/
@Override
public String firstPosition(Instant enqueuedAfter, Duration waitForArrival) throws DataStreamInfrastructureException, InterruptedException{
long opStartTime = System.currentTimeMillis();
long enqueuedAfterEpochMillis = enqueuedAfter.toEpochMilli();
long waitForArrivalMillis = waitForArrival.toMillis();
String selector = "amqp.annotation.x-opt-enqueued-time > '" + enqueuedAfterEpochMillis + "'";
Message msg;
try {
msg = firstMessageByReceive(selector, waitForArrivalMillis);
} catch (JMSException e) {
throw new DataStreamInfrastructureException(e);
}
//msg = firstMessageByListener(selector, waitForArrivalMillis);
//msg = firstMessageByBrowser(selector, waitForArrivalMillis);
EventHubAnnotations annotations = null;
String firstPosition = null;
if (msg != null){
annotations = AzureEventHubUtility.getEventHubAnnotations(msg);
firstPosition = String.valueOf(annotations.getOffset() - 1);
}
logger.debug("First position in {} after {} identified within {}: {}", identifier, enqueuedAfter, DurationFormatter.formatSince(opStartTime), annotations);
return firstPosition;
}
protected Message firstMessageByListener(String selector, long waitForArrivalMillis) throws JMSException, InterruptedException{
AtomicReference result = new AtomicReference<>(null);
AtomicBoolean gotIt = new AtomicBoolean(false);
CountDownLatch stillWaiting = new CountDownLatch(1);
Session session = null;
MessageConsumer consumer = null;
try{
Connection conn = getConnection();
session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
conn.stop();
try{
consumer = session.createConsumer(destination, selector);
consumer.setMessageListener(msg->{
if (gotIt.compareAndSet(false, true)){
result.set(msg);
stillWaiting.countDown();
}
});
}finally{
conn.start();
}
boolean received = stillWaiting.await(waitForArrivalMillis, TimeUnit.MILLISECONDS);
if (!received){ // nothing received
// ignore
}
}finally{
JmsUtility.closeSilently(consumer, session);
}
return result.get();
}
protected Message firstMessageByReceive(String selector, long waitForArrivalMillis) throws JMSException, InterruptedException{
Session session = null;
MessageConsumer consumer = null;
try{
Connection conn = getConnection();
session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
consumer = session.createConsumer(destination, selector);
Message msg = null;
long waitTime = waitForArrivalMillis > 0 ? waitForArrivalMillis : Long.MAX_VALUE;
long startTime = System.currentTimeMillis();
while(msg == null && waitTime > 0){ // sometimes the consumer is not fully ready immediatly
msg = consumer.receive(waitTime);
waitTime -= System.currentTimeMillis() - startTime;
}
return msg;
}finally{
JmsUtility.closeSilently(consumer, session);
}
}
protected Message firstMessageByBrowser(String selector, long waitForArrivalMillis) throws JMSException, InterruptedException{
Session session = null;
QueueBrowser browser = null;
try{
Connection conn = getConnection();
session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
browser = session.createBrowser(destination, selector);
@SuppressWarnings("rawtypes")
Enumeration enumeration = browser.getEnumeration();
Message msg = null;
try{
msg = timeLimiter.callWithTimeout(()->{
if(enumeration.hasMoreElements()){
return (Message) enumeration.nextElement();
}else{
return null;
}
},waitForArrivalMillis, TimeUnit.MILLISECONDS, true);
}catch(UncheckedTimeoutException e){
// ignore
}catch(JMSException e){
throw e;
}catch(Exception e){
throw Throwables.propagate(e);
}
return msg;
}finally{
JmsUtility.closeSilently(browser, session);
}
}
/* (non-Javadoc)
* @see net.sf.jabb.stream.DataStreamProvider#lastPosition()
*/
@Override
public String lastPosition() throws DataStreamInfrastructureException {
long opStartTime = System.currentTimeMillis();
Long lastPosition;
try {
lastPosition = lastPositionByTryError();
} catch (JMSException e) {
throw new DataStreamInfrastructureException(e);
}
//lastPosition = lastPositionThroughManagementQueue();
logger.debug("Last position in {} identified within {}: {}", identifier, DurationFormatter.formatSince(opStartTime), lastPosition);
return lastPosition == null ? null : lastPosition.toString();
}
protected Long lastPositionByTryError() throws JMSException {
Long lastPosition = null;
Session session = null;
MessageConsumer consumer = null;
try{
session = getConnection().createSession(false, Session.AUTO_ACKNOWLEDGE);
try{
consumer = session.createConsumer(destination, "amqp.annotation.x-opt-offset >= '" + (Long.MAX_VALUE/2 - 1) + "'");
}catch(JMSException e){
Throwable cause = e.getCause();
if (cause != null && cause.getMessage() != null){
String msg = cause.getMessage();
String LEADING_TEXT = "The last offset in the system is ";
int i = msg.indexOf(LEADING_TEXT);
if (i >= 0){
i += LEADING_TEXT.length();
int start = i;
i = msg.indexOf(' ', start + 1);
if (i >= 0){
lastPosition = Long.valueOf(
StringUtils.removeEnd(StringUtils.removeStart(StringUtils.trimToNull(msg.substring(start, i)), "'"), "'"));
}
}
}
if (lastPosition == null){ // if we cannot find it, that's an exception
throw e;
}
}
}finally{
JmsUtility.closeSilently(consumer, session);
}
return lastPosition;
}
@Override
public String nextStartPosition(String position) {
return position;
}
/* (non-Javadoc)
* @see net.sf.jabb.stream.AbstractJmsDataStreamProvider#getConnection()
*/
@Override
protected Connection getConnection() {
return wrappedConnection;
}
@Override
protected String messageSelector(String startPosition) {
return "amqp.annotation.x-opt-offset > '" + startPosition + "'";
}
@Override
protected String messageSelector(Instant startEnqueuedTime) {
return "amqp.annotation.x-opt-enqueued-time > '" + startEnqueuedTime.toEpochMilli() + "'";
}
/* (non-Javadoc)
* @see net.sf.jabb.stream.AbstractJmsDataStreamProvider#convert(javax.jms.Message)
*/
@Override
protected M convert(Message message) {
return messageConverter.apply(message);
}
/* (non-Javadoc)
* @see net.sf.jabb.stream.AbstractJmsDataStreamProvider#position(javax.jms.Message)
*/
@Override
protected String position(Message message) {
return String.valueOf(AzureEventHubUtility.getEventHubAnnotations(message).getOffset());
}
@Override
protected Instant enqueuedTime(Message message) {
return AzureEventHubUtility.getEventHubAnnotations(message).getEnqueuedTime();
}
@Override
public void start() throws Exception {
long opStartTime = System.currentTimeMillis();
wrappedConnection.establishConnection();
while(System.currentTimeMillis() < opStartTime + 60*1000L){
if (!wrappedConnection.isConnecting()){
return;
}
try{
waitStrategy.await(100);
}catch(InterruptedException e){
waitStrategy.handleInterruptedException(e);
break;
}
}
logger.warn("Connection is still not established after start: {}", DurationFormatter.formatSince(opStartTime));
return;
}
@Override
public void stop() throws Exception {
// TODO: more work needed to define the behaviour of start/stop/restart
// for now, there is no support for restart
wrappedConnection.close();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy