def test_6_integration_stomp_1_1_encoding_and_escaping_headers(self): if BROKER == 'rabbitmq': print('Broker does not support unicode characters. Skipping this test case.') return version = StompSpec.VERSION_1_1 client = Stomp(self.getConfig(version)) try: client.connect(host=VIRTUALHOST, versions=[version]) except StompProtocolError as e: print('Broker does not support STOMP protocol %s. Skipping this test case. [%s]' % (e, version)) return key = b'fen\xc3\xaatre'.decode('utf-8') value = b'\xc2\xbfqu\xc3\xa9 tal?'.decode('utf-8') headers = {key: value} client.send(self.DESTINATION, body=b'test message 1', headers=headers) self.assertFalse(client.canRead(self.TIMEOUT)) token = client.subscribe(self.DESTINATION, {StompSpec.ID_HEADER: 4711, StompSpec.ACK_HEADER: StompSpec.ACK_CLIENT_INDIVIDUAL}) self.assertTrue(client.canRead(self.TIMEOUT)) frame = client.receiveFrame() client.ack(frame) self.assertEqual(frame.version, version) self.assertEqual(frame.headers[key], headers[key]) self.assertFalse(client.canRead(self.TIMEOUT)) client.unsubscribe(token) client.disconnect(receipt='4712')
def test_6_integration_stomp_1_1_encoding_and_escaping_headers(self): if BROKER == 'rabbitmq': print 'Broker does not support unicode characters. Skipping this test case.' return version = StompSpec.VERSION_1_1 client = Stomp(self.getConfig(version)) try: client.connect(host=VIRTUALHOST, versions=[version]) except StompProtocolError as e: print 'Broker does not support STOMP protocol %s. Skipping this test case. [%s]' % ( e, version) return specialCharactersHeader = u'fen\xeatre:\r\n' headers = {specialCharactersHeader: u'\xbfqu\xe9 tal?, s\xfc\xdf'} client.send(self.DESTINATION, body='test message 1', headers=headers) self.assertFalse(client.canRead(self.TIMEOUT)) token = client.subscribe( self.DESTINATION, { StompSpec.ID_HEADER: 4711, StompSpec.ACK_HEADER: StompSpec.ACK_CLIENT_INDIVIDUAL }) self.assertTrue(client.canRead(self.TIMEOUT)) frame = client.receiveFrame() client.ack(frame) self.assertEquals(frame.version, version) self.assertEquals(frame.headers[specialCharactersHeader], headers[specialCharactersHeader]) self.assertFalse(client.canRead(self.TIMEOUT)) client.unsubscribe(token) client.disconnect(receipt='4712')
def test_6_integration_stomp_1_1_encoding_and_escaping_headers(self): if BROKER == 'rabbitmq': print 'Broker does not support unicode characters. Skipping this test case.' return version = StompSpec.VERSION_1_1 client = Stomp(self.getConfig(version)) try: client.connect(host=VIRTUALHOST, versions=[version]) except StompProtocolError as e: print 'Broker does not support STOMP protocol %s. Skipping this test case. [%s]' % (e, version) return specialCharactersHeader = u'fen\xeatre:\r\n' headers = {specialCharactersHeader: u'\xbfqu\xe9 tal?, s\xfc\xdf'} client.send(self.DESTINATION, body='test message 1', headers=headers) self.assertFalse(client.canRead(self.TIMEOUT)) token = client.subscribe(self.DESTINATION, {StompSpec.ID_HEADER: 4711, StompSpec.ACK_HEADER: StompSpec.ACK_CLIENT_INDIVIDUAL}) self.assertTrue(client.canRead(self.TIMEOUT)) frame = client.receiveFrame() client.ack(frame) self.assertEquals(frame.version, version) self.assertEquals(frame.headers[specialCharactersHeader], headers[specialCharactersHeader]) self.assertFalse(client.canRead(self.TIMEOUT)) client.unsubscribe(token) client.disconnect(receipt='4712')
def _test_4_integration_stomp(self, version): client = Stomp(self.getConfig(version)) try: client.connect(host=VIRTUALHOST, versions=[version]) except StompProtocolError as e: print('Broker does not support STOMP protocol %s. Skipping this test case. [%s]' % (e, version)) return client.send(self.DESTINATION, b'test message 1') client.send(self.DESTINATION, b'test message 2') self.assertFalse(client.canRead(self.TIMEOUT)) token = client.subscribe(self.DESTINATION, {StompSpec.ID_HEADER: 4711, StompSpec.ACK_HEADER: StompSpec.ACK_CLIENT_INDIVIDUAL}) self.assertTrue(client.canRead(self.TIMEOUT)) client.ack(client.receiveFrame()) self.assertTrue(client.canRead(self.TIMEOUT)) client.ack(client.receiveFrame()) self.assertFalse(client.canRead(self.TIMEOUT)) client.unsubscribe(token) client.send(self.DESTINATION, b'test message 3', receipt='4711') self.assertTrue(client.canRead(self.TIMEOUT)) self.assertEqual(client.receiveFrame(), StompFrame(StompSpec.RECEIPT, {StompSpec.RECEIPT_ID_HEADER: '4711'})) self.assertFalse(client.canRead(self.TIMEOUT)) client.subscribe(self.DESTINATION, {StompSpec.ID_HEADER: 4711, StompSpec.ACK_HEADER: StompSpec.ACK_CLIENT_INDIVIDUAL}) self.assertTrue(client.canRead(self.TIMEOUT)) client.ack(client.receiveFrame()) self.assertFalse(client.canRead(self.TIMEOUT)) client.disconnect(receipt='4712') self.assertEqual(client.receiveFrame(), StompFrame(StompSpec.RECEIPT, {StompSpec.RECEIPT_ID_HEADER: '4712'})) self.assertRaises(StompConnectionError, client.receiveFrame) client.connect(host=VIRTUALHOST) client.disconnect(receipt='4711') self.assertEqual(client.receiveFrame(), StompFrame(StompSpec.RECEIPT, {StompSpec.RECEIPT_ID_HEADER: '4711'})) client.close() self.assertRaises(StompConnectionError, client.canRead, 0)
def test_1_integration(self): config = self.getConfig(StompSpec.VERSION_1_0) client = Stomp(config) client.connect(host=VIRTUALHOST) client.send(self.DESTINATION, b'test message 1') client.send(self.DESTINATION, b'test message 2') self.assertFalse(client.canRead(self.TIMEOUT)) client.subscribe(self.DESTINATION, {StompSpec.ACK_HEADER: StompSpec.ACK_CLIENT_INDIVIDUAL}) self.assertTrue(client.canRead(self.TIMEOUT)) client.ack(client.receiveFrame()) self.assertTrue(client.canRead(self.TIMEOUT)) client.ack(client.receiveFrame()) self.assertFalse(client.canRead(self.TIMEOUT))
def test_4_integration_stomp_1_1(self): if StompSpec.VERSION_1_1 not in commands.versions(VERSION): print 'This broker does not support STOMP protocol version 1.1' return client = Stomp(self.getConfig(StompSpec.VERSION_1_1)) client.connect(host=VIRTUALHOST) client.send(self.DESTINATION, 'test message 1') client.send(self.DESTINATION, 'test message 2') self.assertFalse(client.canRead(self.TIMEOUT)) token = client.subscribe(self.DESTINATION, {StompSpec.ID_HEADER: 4711, StompSpec.ACK_HEADER: 'client-individual'}) self.assertTrue(client.canRead(self.TIMEOUT)) client.ack(client.receiveFrame()) self.assertTrue(client.canRead(self.TIMEOUT)) client.ack(client.receiveFrame()) self.assertFalse(client.canRead(self.TIMEOUT)) client.unsubscribe(token) client.send(self.DESTINATION, 'test message 3', receipt='4711') self.assertTrue(client.canRead(self.TIMEOUT)) self.assertEquals(client.receiveFrame(), StompFrame(StompSpec.RECEIPT, {'receipt-id': '4711'})) self.assertFalse(client.canRead(self.TIMEOUT)) client.subscribe(self.DESTINATION, {StompSpec.ID_HEADER: 4711, StompSpec.ACK_HEADER: 'client-individual'}) self.assertTrue(client.canRead(self.TIMEOUT)) client.ack(client.receiveFrame()) self.assertFalse(client.canRead(self.TIMEOUT)) client.disconnect(receipt='4712') self.assertEquals(client.receiveFrame(), StompFrame(StompSpec.RECEIPT, {'receipt-id': '4712'})) self.assertRaises(StompConnectionError, client.receiveFrame) client.connect(host=VIRTUALHOST) client.disconnect(receipt='4711') self.assertEquals(client.receiveFrame(), StompFrame(StompSpec.RECEIPT, {'receipt-id': '4711'})) client.close() self.assertRaises(StompConnectionError, client.canRead, 0)
def test_5_integration_stomp_1_1_heartbeat(self): version = StompSpec.VERSION_1_1 if BROKER == 'apollo': print "Broker %s doesn't properly support heart-beating. Skipping test." % BROKER return port = 61612 if (BROKER == 'activemq') else PORT # stomp+nio on 61613 does not work properly, so use stomp on 61612 client = Stomp(self.getConfig(StompSpec.VERSION_1_1, port)) self.assertEquals(client.lastReceived, None) self.assertEquals(client.lastSent, None) heartBeatPeriod = 100 try: client.connect(host=VIRTUALHOST, heartBeats=(heartBeatPeriod, heartBeatPeriod), versions=[version]) except StompProtocolError as e: print 'Broker does not support STOMP protocol %s. Skipping this test case. [%s]' % (e, version) return self.assertTrue((time.time() - client.lastReceived) < 0.1) if not (client.serverHeartBeat and client.clientHeartBeat): print 'broker does not support heart-beating. disconnecting ...' client.disconnect() client.close() return serverHeartBeatInSeconds = client.serverHeartBeat / 1000.0 clientHeartBeatInSeconds = client.clientHeartBeat / 1000.0 start = time.time() while (time.time() - start) < (2.5 * max(serverHeartBeatInSeconds, clientHeartBeatInSeconds)): time.sleep(0.5 * min(serverHeartBeatInSeconds, clientHeartBeatInSeconds)) client.canRead(0) self.assertTrue((time.time() - client.lastReceived) < (2.0 * serverHeartBeatInSeconds)) if (time.time() - client.lastSent) > (0.5 * clientHeartBeatInSeconds): client.beat() self.assertTrue((time.time() - client.lastSent) < 0.1) start = time.time() try: while not client.canRead(0.5 * clientHeartBeatInSeconds): pass except StompConnectionError: self.assertTrue((time.time() - start) < (3.0 * clientHeartBeatInSeconds)) self.assertTrue((time.time() - client.lastReceived) < (2.0 * serverHeartBeatInSeconds)) self.assertTrue((time.time() - client.lastSent) > clientHeartBeatInSeconds) else: raise client.close()
def call_route(request_queue, response_queue, request): """ """ config = { "stomp": { "server": '192.168.0.3', "port": 61613, "timeout": 15, } } stomp_config = StompConfig("tcp://%s:%d" % (config['stomp']['server'], config['stomp']['port']), version=StompSpec.VERSION_1_0) stomp = Stomp(stomp_config) stomp.connect() jms_id = str(uuid4()) token = stomp.subscribe(response_queue, {'JMSCorrelationID': jms_id}) stomp.send(request_queue, json.dumps(request), {'JMSCorrelationID': jms_id}) response = None if stomp.canRead(config['stomp']['timeout']): response = stomp.receiveFrame() stomp.unsubscribe(token) return response
def main(): logging.basicConfig() logging.getLogger().setLevel(logging.WARN) client = Stomp(stomp_config) client.connect() client.send(stomp_queue, body=stomp_body) client.subscribe(stomp_queue, {StompSpec.ACK_HEADER: StompSpec.ACK_CLIENT, 'activemq.prefetchSize': 1}) if client.canRead(timeout=5): frame = client.receiveFrame() print 'Got %s' % frame.info() client.ack(frame) frame_body = str(frame.body) if frame_body == stomp_body: print "OK: Message received" status = 'ok' else: print "WARNING: Incorrect message body; is %s, should be %s" % (frame_body, stomp_body) status = 'warning' else: print "CRITICAL: Timed out while trying to collect the message" status = 'critical' client.disconnect() client.close(flush=True) return exit_codes[status]
def test_5_integration_stomp_1_1_heartbeat(self): version = StompSpec.VERSION_1_1 port = 61612 if (BROKER == 'activemq') else PORT # stomp+nio on 61613 does not work properly, so use stomp on 61612 client = Stomp(self.getConfig(StompSpec.VERSION_1_1, port)) self.assertEquals(client.lastReceived, None) self.assertEquals(client.lastSent, None) heartBeatPeriod = 100 try: client.connect(host=VIRTUALHOST, heartBeats=(heartBeatPeriod, heartBeatPeriod), versions=[version]) except StompProtocolError as e: print 'Broker does not support STOMP protocol %s. Skipping this test case. [%s]' % (e, version) return self.assertTrue((time.time() - client.lastReceived) < 0.1) if not (client.serverHeartBeat and client.clientHeartBeat): print 'broker does not support heart-beating. disconnecting ...' client.disconnect() client.close() return serverHeartBeatInSeconds = client.serverHeartBeat / 1000.0 clientHeartBeatInSeconds = client.clientHeartBeat / 1000.0 start = time.time() while (time.time() - start) < (2.5 * max(serverHeartBeatInSeconds, clientHeartBeatInSeconds)): time.sleep(0.5 * min(serverHeartBeatInSeconds, clientHeartBeatInSeconds)) client.canRead(0) self.assertTrue((time.time() - client.lastReceived) < (2.0 * serverHeartBeatInSeconds)) if (time.time() - client.lastSent) > (0.5 * clientHeartBeatInSeconds): client.beat() self.assertTrue((time.time() - client.lastSent) < 0.1) start = time.time() try: while not client.canRead(0.5 * clientHeartBeatInSeconds): pass if client.receiveFrame().command == StompSpec.ERROR: raise StompProtocolError() except (StompConnectionError, StompProtocolError): self.assertTrue((time.time() - start) < (3.0 * clientHeartBeatInSeconds)) self.assertTrue((time.time() - client.lastReceived) < (2.0 * serverHeartBeatInSeconds)) self.assertTrue((time.time() - client.lastSent) > clientHeartBeatInSeconds) else: raise client.close()
def test_5_integration_stomp_1_1_heartbeat(self): version = StompSpec.VERSION_1_1 client = Stomp(self.getConfig(StompSpec.VERSION_1_1)) self.assertEqual(client.lastReceived, None) self.assertEqual(client.lastSent, None) heartBeatPeriod = 100 try: client.connect(host=VIRTUALHOST, heartBeats=(heartBeatPeriod, heartBeatPeriod), versions=[version]) except StompProtocolError as e: print('Broker does not support STOMP protocol %s. Skipping this test case. [%s]' % (e, version)) return self.assertTrue((time.time() - client.lastReceived) < 0.1) if not (client.serverHeartBeat and client.clientHeartBeat): print('broker does not support heart-beating. disconnecting ...') client.disconnect() client.close() return serverHeartBeatInSeconds = client.serverHeartBeat / 1000.0 clientHeartBeatInSeconds = client.clientHeartBeat / 1000.0 start = time.time() while (time.time() - start) < (2.5 * max(serverHeartBeatInSeconds, clientHeartBeatInSeconds)): time.sleep(0.5 * min(serverHeartBeatInSeconds, clientHeartBeatInSeconds)) client.canRead(0) self.assertTrue((time.time() - client.lastReceived) < (2.0 * serverHeartBeatInSeconds)) if (time.time() - client.lastSent) > (0.5 * clientHeartBeatInSeconds): client.beat() self.assertTrue((time.time() - client.lastSent) < 0.1) start = time.time() try: while not client.canRead(0.5 * clientHeartBeatInSeconds): pass if client.receiveFrame().command == StompSpec.ERROR: raise StompProtocolError() except (StompConnectionError, StompProtocolError): self.assertTrue((time.time() - start) < (3.0 * clientHeartBeatInSeconds)) self.assertTrue((time.time() - client.lastReceived) < (2.0 * serverHeartBeatInSeconds)) self.assertTrue((time.time() - client.lastSent) > clientHeartBeatInSeconds) else: raise client.close()
def setUp(self): config = self.getConfig(StompSpec.VERSION_1_0) client = Stomp(config) client.connect(host=VIRTUALHOST) client.subscribe(self.DESTINATION, {StompSpec.ACK_HEADER: StompSpec.ACK_AUTO}) client.subscribe(self.DESTINATION, {StompSpec.ID_HEADER: 'bla', StompSpec.ACK_HEADER: StompSpec.ACK_AUTO}) while client.canRead(self.TIMEOUT): frame = client.receiveFrame() self.log.debug('Dequeued old %s' % frame.info()) client.disconnect()
def test_2_transaction(self): config = self.getConfig(StompSpec.VERSION_1_0) client = Stomp(config) client.connect(host=VIRTUALHOST) client.subscribe( self.DESTINATION, {StompSpec.ACK_HEADER: StompSpec.ACK_CLIENT_INDIVIDUAL}) self.assertFalse(client.canRead(self.TIMEOUT)) with client.transaction(4711) as transaction: self.assertEquals(transaction, '4711') client.send(self.DESTINATION, 'test message', {StompSpec.TRANSACTION_HEADER: transaction}) self.assertFalse(client.canRead(0)) self.assertTrue(client.canRead(self.TIMEOUT)) frame = client.receiveFrame() self.assertEquals(frame.body, 'test message') client.ack(frame) with client.transaction(4713, receipt='4712') as transaction: self.assertEquals(transaction, '4713') self.assertEquals( client.receiveFrame(), StompFrame(StompSpec.RECEIPT, {StompSpec.RECEIPT_ID_HEADER: '4712-begin'})) client.send(self.DESTINATION, 'test message', {StompSpec.TRANSACTION_HEADER: transaction}) client.send(self.DESTINATION, 'test message without transaction') self.assertTrue(client.canRead(self.TIMEOUT)) frame = client.receiveFrame() self.assertEquals(frame.body, 'test message without transaction') client.ack(frame) self.assertFalse(client.canRead(0)) frames = [client.receiveFrame() for _ in xrange(2)] frames = list(sorted(frames, key=lambda f: f.command)) frame = frames[0] client.ack(frame) self.assertEquals(frame.body, 'test message') frame = frames[1] self.assertEquals( frame, StompFrame(StompSpec.RECEIPT, {StompSpec.RECEIPT_ID_HEADER: '4712-commit'})) try: with client.transaction(4714) as transaction: self.assertEquals(transaction, '4714') client.send(self.DESTINATION, 'test message', {StompSpec.TRANSACTION_HEADER: transaction}) raise RuntimeError('poof') except RuntimeError as e: self.assertEquals(str(e), 'poof') else: raise self.assertFalse(client.canRead(self.TIMEOUT)) client.disconnect()
def CreateConnection(): try: Write2File(threading.currentThread().getName(), "INFO", "Connecting to ActiveMQ Server.") client = Stomp( StompConfig("tcp://" + server + ":" + port, login=login, passcode=passcode, version="1.2")) client.connect(versions=["1.2"], host=vhost, heartBeats=(0, 60000)) #CONNECT subscription = client.subscribe(destination, { "ack": "client", "id": "0", "headers": { "activemq.prefetchSize": 1 } }) #SUBSCRIB Write2File(threading.currentThread().getName(), "INFO", "Connection to ActiveMQ Server successfully established.") except: Write2File(threading.currentThread().getName(), "ERROR", str(sys.exc_info())) raise try: while (client.canRead(5)): Write2File(threading.currentThread().getName(), "DEBUG", "Setting LOCK.") container.acquire() ReceiveFrame(client) else: Write2File(threading.currentThread().getName(), "INFO", "Closing connection with ActiveMQ Server.") client.disconnect() if (container.acquire(blocking=False)): Write2File(threading.currentThread().getName(), "DEBUG", "Removing LOCK.") container.release() except: Write2File(threading.currentThread().getName(), "ERROR", str(sys.exc_info())) exit(1)
def test_2_transaction(self): config = self.getConfig(StompSpec.VERSION_1_0) client = Stomp(config) client.connect(host=VIRTUALHOST) client.subscribe(self.DESTINATION, {StompSpec.ACK_HEADER: StompSpec.ACK_CLIENT_INDIVIDUAL}) self.assertFalse(client.canRead(self.TIMEOUT)) with client.transaction(4711) as transaction: self.assertEqual(transaction, '4711') client.send(self.DESTINATION, b'test message', {StompSpec.TRANSACTION_HEADER: transaction}) self.assertFalse(client.canRead(0)) self.assertTrue(client.canRead(self.TIMEOUT)) frame = client.receiveFrame() self.assertEqual(frame.body, b'test message') client.ack(frame) with client.transaction(4713, receipt='4712') as transaction: self.assertEqual(transaction, '4713') self.assertEqual(client.receiveFrame(), StompFrame(StompSpec.RECEIPT, {StompSpec.RECEIPT_ID_HEADER: '4712-begin'})) client.send(self.DESTINATION, b'test message', {StompSpec.TRANSACTION_HEADER: transaction}) client.send(self.DESTINATION, b'test message without transaction') self.assertTrue(client.canRead(self.TIMEOUT)) frame = client.receiveFrame() self.assertEqual(frame.body, b'test message without transaction') client.ack(frame) self.assertFalse(client.canRead(0)) frames = [client.receiveFrame() for _ in range(2)] frames = list(sorted(frames, key=lambda f: f.command)) frame = frames[0] client.ack(frame) self.assertEqual(frame.body, b'test message') frame = frames[1] self.assertEqual(frame, StompFrame(StompSpec.RECEIPT, {StompSpec.RECEIPT_ID_HEADER: '4712-commit'})) try: with client.transaction(4714) as transaction: self.assertEqual(transaction, '4714') client.send(self.DESTINATION, b'test message', {StompSpec.TRANSACTION_HEADER: transaction}) raise RuntimeError('poof') except RuntimeError as e: self.assertEqual(str(e), 'poof') else: raise self.assertFalse(client.canRead(self.TIMEOUT)) client.disconnect()
import time from stompest.config import StompConfig from stompest.sync import Stomp user = os.getenv('APOLLO_USER') or 'admin' password = os.getenv('APOLLO_PASSWORD') or 'password' host = os.getenv('APOLLO_HOST') or 'localhost' port = int(os.getenv('APOLLO_PORT') or 61613) destination = sys.argv[1:2] or ['/topic/event'] destination = destination[0] config = StompConfig('tcp://%s:%d' % (host, port), login=user, passcode=password, version='1.1') client = Stomp(config) client.connect(host='mybroker') client.subscribe(destination=destination, headers={'id': 'required-for-STOMP-1.1'}) count = 0 start = time.time() while (not count) or client.canRead(0): client.receiveFrame() count += 1 diff = time.time() - start print 'Received %s frames in %f seconds' % (count, diff) client.disconnect(receipt='bye') client.receiveFrame() client.close()
class StompMQAdapter: """ Represents a Message Queueing adapter, an object capable of interacting with a MQ system via Stomp protocol. """ # The Stomp connection headers. headers = {StompSpec.ACK_HEADER: StompSpec.ACK_CLIENT_INDIVIDUAL} def __init__(self, host, port, version, headers={}): """ Creates an instance of the StompMQAdapter class. Args: host (str): Hostname or IP address for locating the MQ system. port (int): The port to connect to. stomp_version (str): The Stomp protocol version ot be used. headers (dict, optional): Defaults to {}. The headers to be used in the connection. """ self.client = Stomp( StompConfig('tcp://{}:{}'.format(host, port), version=version)) # Assign mandatory ID_HEADER if version above 1.1 if float(version) > 1.1: self.headers[StompSpec.ID_HEADER] = id(self.client) # Add all given headers to object headers for key in headers.keys(): self.headers[key] = headers[key] def connect(self): """ Connects to the MQ system via Stomp protocol. Raises: StompConnectTimeout: Could not connect to STOMP socket. """ self.client.connect() def subscribe(self, queue): """ Subscribes to a queue in the MQ system. Args: queue (str): The queue to subscribe to. """ self.client.subscribe(queue, self.headers) def queue(self, queue, message): """ Sends a message to the specified queue. Args: queue (str): The queue to where the message should be queued. message: The message to be queued. Raises: NotImplementedError: Implement this method on a child class. """ self.client.send(queue, message.encode()) def retrieve(self): """ Retrieves a message from the subscription (queue). Returns: object: The message to be consumed or None if the queue is empty. """ if self.client.canRead(timeout=2): return self.client.receiveFrame() return None def ack(self, message): """ Acknowledges the consumption of the given message. Args: message ([type]): The message to be acknowledged. """ self.client.ack(message) def nack(self, message): """ Not-acknowledges the consumption of the given message. Args: message ([type]): The message to be not-acknowledged. """ self.client.nack(message) def disconnect(self): """ Disconnects from the MQ system. """ self.client.disconnect()
class StompClient(BaseComponent): """ Send and Receive messages from a STOMP queue """ channel = "stomp" def init(self, host, port, username=None, password=None, connect_timeout=3, connected_timeout=3, version=StompSpec.VERSION_1_2, accept_versions=["1.0", "1.1", "1.2"], heartbeats=(0, 0), ssl_context=None, use_ssl=True, key_file=None, cert_file=None, ca_certs=None, ssl_version=ssl.PROTOCOL_SSLv23, key_file_password=None, proxy_host=None, proxy_port=None, proxy_user=None, proxy_password=None, channel=channel): """ Initialize StompClient. Called after __init__ """ self.channel = channel if proxy_host: LOG.info("Connect to %s:%s through proxy %s:%d", host, port, proxy_host, proxy_port) else: LOG.info("Connect to %s:%s", host, port) if use_ssl and not ssl_context: ssl_params = dict(key_file=key_file, cert_file=cert_file, ca_certs=ca_certs, ssl_version=ssl_version, password=key_file_password) LOG.info("Request to use old-style socket wrapper: %s", ssl_params) ssl_context = ssl_params if use_ssl: uri = "ssl://%s:%s" % (host, port) else: uri = "tcp://%s:%s" % (host, port) # Configure failover options so it only tries to connect once self._stomp_server = "failover:(%s)?maxReconnectAttempts=1,startupMaxReconnectAttempts=1" % uri self._stomp_config = StompConfig(uri=self._stomp_server, sslContext=ssl_context, version=version, login=username, passcode=password) self._heartbeats = heartbeats self._accept_versions = accept_versions self._connect_timeout = connect_timeout self._connected_timeout = connected_timeout Stomp._transportFactory = EnhancedStompFrameTransport Stomp._transportFactory.proxy_host = proxy_host Stomp._transportFactory.proxy_port = proxy_port Stomp._transportFactory.proxy_user = proxy_user Stomp._transportFactory.proxy_password = proxy_password self._client = Stomp(self._stomp_config) self._subscribed = {} self.server_heartbeat = None self.client_heartbeat = None self.ALLOWANCE = 2 # multiplier for heartbeat timeouts @property def connected(self): if self._client.session: return self._client.session.state == StompSession.CONNECTED else: return False @property def subscribed(self): return self._subscribed.keys() @property def stomp_logger(self): return LOG_CATEGORY @handler("disconnect") def _disconnect(self, receipt=None): if self.connected: self._client.disconnect(receipt=receipt) self._client.close(flush=True) self.fire(disconnected(reconnect=False)) self._subscribed = {} return "disconnected" def start_heartbeats(self): LOG.info("Client HB: %s Server HB: %s", self._client.clientHeartBeat, self._client.serverHeartBeat) if self._client.clientHeartBeat: if self.client_heartbeat: # Timer already exists, just reset it self.client_heartbeat.reset() else: LOG.info("Client will send heartbeats to server") # Send heartbeats at 80% of agreed rate self.client_heartbeat = Timer((self._client.clientHeartBeat / 1000.0) * 0.8, client_heartbeat(), persist=True) self.client_heartbeat.register(self) else: LOG.info("No Client heartbeats will be sent") if self._client.serverHeartBeat: if self.server_heartbeat: # Timer already exists, just reset it self.server_heartbeat.reset() else: LOG.info("Requested heartbeats from server.") # Allow a grace period on server heartbeats self.server_heartbeat = Timer((self._client.serverHeartBeat / 1000.0) * self.ALLOWANCE, server_heartbeat(), persist=True) self.server_heartbeat.register(self) else: LOG.info("Expecting no heartbeats from Server") @handler("connect") def connect(self, event, host=None, *args, **kwargs): """ connect to Stomp server """ LOG.info("Connect to Stomp...") try: self._client.connect(heartBeats=self._heartbeats, host=host, versions=self._accept_versions, connectTimeout=self._connect_timeout, connectedTimeout=self._connected_timeout) LOG.info("State after Connection Attempt: %s", self._client.session.state) if self.connected: LOG.info("Connected to %s", self._stomp_server) self.fire(connected()) self.start_heartbeats() return "success" except StompConnectionError: LOG.debug(traceback.format_exc()) self.fire(connection_failed(self._stomp_server)) event.success = False return "fail" @handler("server_heartbeat") def check_server_heartbeat(self, event): """ Confirm that heartbeat from server hasn't timed out """ now = time.time() last = self._client.lastReceived or 0 if last: elapsed = now - last else: elapsed = -1 LOG.debug("Last received data %d seconds ago", elapsed) if ((self._client.serverHeartBeat / 1000.0) * self.ALLOWANCE + last) < now: LOG.error("Server heartbeat timeout. %d seconds since last heartbeat. Disconnecting.", elapsed) event.success = False self.fire(heartbeat_timeout()) if self.connected: self._client.disconnect() # TODO: Try to auto-reconnect? @handler("client_heartbeat") def send_heartbeat(self, event): if self.connected: LOG.debug("Sending heartbeat") try: self._client.beat() except StompConnectionError: event.success = False self.fire(disconnected()) @handler("generate_events") def generate_events(self, event): if not self.connected: return try: if self._client.canRead(1): frame = self._client.receiveFrame() LOG.debug("Recieved frame %s", frame) self.fire(message(frame)) except StompConnectionError: self.fire(disconnected()) @handler("send") def send(self, event, destination, body, headers=None, receipt=None): LOG.debug("send()") if not self.connected: LOG.error("Can't send when Stomp is disconnected") self.fire(on_stomp_error(None, Exception("Message send attempted with stomp disconnected"))) event.success = False return try: self._client.send(destination, body=body.encode('utf-8'), headers=headers, receipt=receipt) LOG.debug("Message sent") except StompConnectionError as err: event.success = False self.fire(disconnected()) except StompError as err: LOG.error("Error sending ack") event.success = False self.fire(on_stomp_error(None, err)) @handler("subscribe") def _subscribe(self, event, destination, ack=ACK_CLIENT_INDIVIDUAL): if ack not in ACK_MODES: raise ValueError("Invalid client ack mode specified") LOG.info("Subscribe to message destination %s", destination) try: # Set ID to match destination name for easy reference later frame, token = self._client.subscribe(destination, headers={StompSpec.ACK_HEADER: ack, 'id': destination}) self._subscribed[destination] = token except StompConnectionError as err: event.success = False self.fire(disconnected()) except StompError as err: event.success = False LOG.debug(traceback.format_exc()) self.fire(on_stomp_error(None, err)) @handler("unsubscribe") def _unsubscribe(self, event, destination): if destination not in self._subscribed: LOG.error("Unsubscribe Request Ignored. Not subscribed to %s", destination) return try: token = self._subscribed.pop(destination) frame = self._client.unsubscribe(token) LOG.debug("Unsubscribed: %s", frame) except StompConnectionError as err: event.success = False self.fire(disconnected()) except StompError as err: LOG.error("Error sending ack") event.success = False self.fire(on_stomp_error(frame, err)) @handler("message") def on_message(self, event, headers, message): LOG.info("Stomp message received") @handler("ack") def ack_frame(self, event, frame): LOG.debug("ack_frame()") try: self._client.ack(frame) LOG.debug("Ack Sent") except StompConnectionError as err: LOG.error("Error sending ack") event.success = False self.fire(disconnected()) except StompError as err: LOG.error("Error sending ack") event.success = False self.fire(on_stomp_error(frame, err)) def get_subscription(self, frame): """ Get subscription from frame """ LOG.info(self._subscribed) _, token = self._client.message(frame) return self._subscribed[token]
def toTime(input): return time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(input)) if __name__ == '__main__': client = Stomp(CONFIG) client.connect(connectedTimeout=4, heartBeats=(0,5000)) print "--------------------------------------------------------------------" print "state : ", client.session.state print "client HB : ", client.session.clientHeartBeat print "server HB : ", client.session.serverHeartBeat print "server : ", client.session.server print "id : ", client.session.id print "lastSent : ", toTime(client.session.lastSent) print "lastReceived : ", toTime(client.session.lastReceived) start = time.time() elapsed = lambda t = None: (t or time.time()) - start times = lambda: 'elapsed: %.2f, last received: %.2f, last sent: %.2f' % ( elapsed(), elapsed(client.lastReceived), elapsed(client.lastSent) ) while True: client.canRead(0.8 * client.serverHeartBeat / 1000.0) # poll server heart-beats print times() time.sleep(1)
class p25_metadata_agent(): def __init__(self, host=None, port=None): self.log = logging.getLogger('overseer.p25_metadata_agent') self.log.info('Initializing p25_metadata_agent') self.demod_type = 'p25' self.redis_demod_manager = redis_demod_manager(self) if (host != None): self.host = host else: self.host = '127.0.0.1' #manually set here until there is a better place if (port != None): self.port = port else: self.port = 61613 #manually set here until there is a better place self.client = None self.connection_issue = True self.continue_running = True self.subscriptions = {} self.parameters = {} self.hang_time = 0.5 self.instance_metadata = {} self.system_metadata = {} connection_handler = threading.Thread(target=self.connection_handler) connection_handler.daemon = True connection_handler.start() #time.sleep(0.25) publish_loop = threading.Thread(target=self.publish_loop) publish_loop.daemon = True publish_loop.start() def init_connection(self): self.log.info('init_connection() (activemq) to tcp://%s/:%s' % (self.host, self.port)) if (self.client != None and self.client.session.state == 'connected'): try: self.client.disconnect() except: pass config = StompConfig('tcp://%s:%s' % (self.host, self.port), version=StompSpec.VERSION_1_1, check=True) self.client = Stomp(config) self.client.connect(heartBeats=(30000, 0), connectTimeout=1, connectedTimeout=1) def connection_handler(self): self.log.info('connection_handler() startup') #This func will just try to reconnect repeatedly in a thread if we're flagged as having an issue. while (True): if (self.connection_issue == True): try: self.init_connection() self.connection_issue = False for subscription in self.subscriptions: self.subscribe(subscription, resub=True) except: pass time.sleep(1) def subscribe(self, queue, resub=False): #This needs to exist so we can keep track of what subs we have and re-sub on reconnect if queue in self.subscriptions and not resub: return True #we're already subscribed this_uuid = '%s' % uuid.uuid4() if (self.connection_issue == True): self.subscriptions[queue] = this_uuid return None try: self.subscriptions[queue] = this_uuid self.client.subscribe( queue, { StompSpec.ID_HEADER: this_uuid, StompSpec.ACK_HEADER: StompSpec.ACK_CLIENT_INDIVIDUAL, }) except Exception as e: self.log.fatal('%s' % e) self.connection_issue = True def unsubscribe(self, queue): if queue not in self.subscriptions: return False #cant unsubscribe, we're not subscribed if (self.connection_issue == True): return None try: self.client.unsubscribe( self.subscriptions[queue], {StompSpec.ACK_HEADER: StompSpec.ACK_CLIENT_INDIVIDUAL}) del self.subscriptions[queue] except Exception as e: self.log.fatal('%s' % e) self.connection_issue = True def send_event_lazy(self, destination, body): #If it gets there, then great, if not, well we tried! if (self.connection_issue == True): return None try: self.client.send(destination, json.dumps(body)) except: self.connection_issue = True def notify_demod_new(self, demod_instance_uuid): self.log.info('Notified of new demod %s' % (demod_instance_uuid)) self.subscribe('/topic/raw_control/%s' % (demod_instance_uuid)) def notify_demod_expire(self, demod_instance_uuid): self.log.info('Notified of expired demod %s' % (demod_instance_uuid)) self.unsubscribe('/topic/raw_control/%s' % (demod_instance_uuid)) def get_channel_detail(self, instance, channel): chan_ident = (channel & 0xf000) >> 12 chan_number = channel & 0x0fff try: base_freq = self.instance_metadata[instance][ 'channel_identifier_table'][chan_ident]['Base Frequency'] chan_spacing = self.instance_metadata[instance][ 'channel_identifier_table'][chan_ident][ 'Channel Spacing'] / 1000 slots = self.instance_metadata[instance][ 'channel_identifier_table'][chan_ident]['Slots'] modulation = self.instance_metadata[instance][ 'channel_identifier_table'][chan_ident]['Type'] except KeyError: return False, False, False, False chan_freq = ((chan_number / slots) * chan_spacing) slot_number = (chan_number % slots) channel_frequency = math.floor((base_freq + chan_freq) * 1000000) channel_bandwidth = self.instance_metadata[instance][ 'channel_identifier_table'][chan_ident]['BW'] * 1000 return channel_frequency, channel_bandwidth, slot_number, modulation def get_system_from_instance(self, instance_uuid): try: return self.redis_demod_manager.demods[instance_uuid][ 'system_uuid'] except: return False def is_updated(self, instance, parameter, value): if instance not in self.parameters: self.parameters[instance] = {} if parameter not in self.parameters[instance]: self.parameters[instance][parameter] = value return True elif self.parameters[instance][parameter] != value: self.parameters[instance][parameter] = value return True else: return False def publish_loop(self): self.log.info('publish_loop() startup') while self.continue_running: if self.connection_issue == False: try: if not self.client.canRead(0.1): continue frame = self.client.receiveFrame() t = json.loads(frame.body) instance_uuid = frame.headers['destination'].replace( '/topic/raw_control/', '') try: instance = self.redis_demod_manager.demods[ instance_uuid] except: continue #system_uuid = self.get_system_from_instance(instance_uuid) if instance_uuid not in self.instance_metadata: self.instance_metadata[instance_uuid] = { 'channel_identifier_table': {} } if 'crc' not in t or t['crc'] != 0: continue #Don't bother trying to work with bad data to_check = [] if t['name'] == 'IDEN_UP_VU': to_check.append({ 'parameter': 'FIT-%s' % t['Identifier'], 'value': { 'BW': t['BW VU'], 'Base Frequency': t['Base Frequency'], 'Channel Spacing': t['Channel Spacing'], 'Transmit Offset': t['Transmit Offset VU'], 'Type': 'FDMA', 'Slots': 1, } }) self.instance_metadata[instance_uuid][ 'channel_identifier_table'][t['Identifier']] = { 'BW': t['BW VU'], 'Base Frequency': t['Base Frequency'], 'Channel Spacing': t['Channel Spacing'], 'Transmit Offset': t['Transmit Offset VU'], 'Type': 'FDMA', 'Slots': 1, } elif t['name'] == 'IDEN_UP': to_check.append({ 'parameter': 'FIT-%s' % t['Identifier'], 'value': { 'BW': t['BW'], 'Base Frequency': t['Base Frequency'], 'Channel Spacing': t['Channel Spacing'], 'Transmit Offset': t['Transmit Offset'], 'Type': 'FDMA', 'Slots': 1, } }) self.instance_metadata[instance_uuid][ 'channel_identifier_table'][t['Identifier']] = { 'BW': t['BW'], 'Base Frequency': t['Base Frequency'], 'Channel Spacing': t['Channel Spacing'], 'Transmit Offset': t['Transmit Offset'], 'Type': 'FDMA', 'Slots': 1, } elif t['name'] == 'IDEN_UP_TDMA': to_check.append({ 'parameter': 'FIT-%s' % t['Identifier'], 'value': { 'BW': t['BW'], 'Base Frequency': t['Base Frequency'], 'Channel Spacing': t['Channel Spacing'], 'Transmit Offset': t['Transmit Offset TDMA'], 'Type': t['Access Type'], 'Slots': t['Slots'], } }) self.instance_metadata[instance_uuid][ 'channel_identifier_table'][t['Identifier']] = { 'BW': t['BW'], 'Base Frequency': t['Base Frequency'], 'Channel Spacing': t['Channel Spacing'], 'Transmit Offset': t['Transmit Offset TDMA'], 'Type': t['Access Type'], 'Slots': t['Slots'], } elif t['name'] == 'NET_STS_BCST': to_check.append({ 'parameter': 'WACN ID', 'value': hex(int(t['WACN ID'])) }) to_check.append({ 'parameter': 'System ID', 'value': hex(int(t['System ID'])) }) to_check.append({ 'parameter': 'System Service Class', 'value': t['System Service Class'] }) frequency, bandwidth, slot_number, modulation = self.get_channel_detail( instance_uuid, t['Channel']) if frequency != False: to_check.append({ 'parameter': 'Control Channel', 'value': { 'frequency': frequency, 'bandwidth': bandwidth } }) elif t['name'] == 'RFSS_STS_BCST': to_check.append({ 'parameter': 'Site ID', 'value': t['Site ID'] }) to_check.append({ 'parameter': 'RF Sub-system ID', 'value': t['RF Sub-system ID'] }) to_check.append({ 'parameter': 'RFSS Network Connection', 'value': t['A'] }) elif t['name'] == 'ADJ_STS_BCST': print '%s' % t pass for d in to_check: if self.is_updated(instance_uuid, d['parameter'], d['value']): print 'Updated! %s %s %s' % ( instance_uuid, d['parameter'], d['value']) message = { 'transmit_site_uuid': self.redis_demod_manager.demods[instance_uuid] ['transmit_site_uuid'], 'receive_site_uuid': self.redis_demod_manager.demods[instance_uuid] ['site_uuid'], 'parameter': d['parameter'], 'value': d['value'], } self.send_event_lazy('/queue/metadata/site_update', message) self.client.ack(frame) except Exception as e: self.log.fatal('except: %s' % e) raise self.connection_issue = True
from stompest.config import StompConfig from stompest.sync import Stomp user = os.getenv('ACTIVEMQ_USER') or 'admin' password = os.getenv('ACTIVEMQ_PASSWORD') or 'ok0dikosmou123' host = os.getenv('ACTIVEMQ_HOST') or 'es.giorgos.io' port = int(os.getenv('ACTIVEMQ_PORT') or 61613) #61613 destination = sys.argv[1:2] or [''] destination = "Consumer.esb.VirtualTopic.es-data" config = StompConfig('tcp://%s:%d' % (host, port), login=user, passcode=password, version='1.1') client = Stomp(config) client.connect(host='mybroker') client.subscribe(destination=destination, headers={'id': 'required-for-STOMP-1.1'}) count = 0 start = time.time() while (not count) or client.canRead(0): client.receiveFrame() count += 1 diff = time.time() - start print('Received %s frames in %f seconds' % (count, diff)) client.disconnect(receipt='bye') client.receiveFrame() client.close()
class StompClient(BaseComponent): channel = "stomp" def init( self, host, port, username=None, password=None, connect_timeout=3, connected_timeout=3, version=StompSpec.VERSION_1_2, accept_versions=["1.0", "1.1", "1.2"], heartbeats=(0, 0), ssl_context=None, use_ssl=True, key_file=None, cert_file=None, ca_certs=None, ssl_version=ssl.PROTOCOL_SSLv23, # means 'latest available' key_file_password=None, proxy_host=None, proxy_port=None, proxy_user=None, proxy_password=None, channel=channel): """ Initialize StompClient. Called after __init__ """ self.channel = channel if proxy_host: LOG.info("Connect to %s:%s through proxy %s:%d", host, port, proxy_host, proxy_port) else: LOG.info("Connect to %s:%s", host, port) if use_ssl and not ssl_context: ssl_params = dict(key_file=key_file, cert_file=cert_file, ca_certs=ca_certs, ssl_version=ssl_version, password=key_file_password) LOG.info("Request to use old-style socket wrapper: %s", ssl_params) ssl_context = ssl_params if use_ssl: uri = "ssl://%s:%s" % (host, port) else: uri = "tcp://%s:%s" % (host, port) # Configure failover options so it only tries to connect once self._stomp_server = "failover:(%s)?maxReconnectAttempts=1,startupMaxReconnectAttempts=1" % uri self._stomp_config = StompConfig(uri=self._stomp_server, sslContext=ssl_context, version=version, login=username, passcode=password) self._heartbeats = heartbeats self._accept_versions = accept_versions self._connect_timeout = connect_timeout self._connected_timeout = connected_timeout Stomp._transportFactory = EnhancedStompFrameTransport Stomp._transportFactory.proxy_host = proxy_host Stomp._transportFactory.proxy_port = proxy_port Stomp._transportFactory.proxy_user = proxy_user Stomp._transportFactory.proxy_password = proxy_password self._client = Stomp(self._stomp_config) self._subscribed = {} self.server_heartbeat = None self.client_heartbeat = None self.last_heartbeat = 0 self.ALLOWANCE = 2 # multiplier for heartbeat timeouts @property def connected(self): if self._client.session: return self._client.session.state == StompSession.CONNECTED else: return False @property def socket_connected(self): try: if self._client._transport: return True except: pass return False @property def subscribed(self): return self._subscribed.keys() @property def stomp_logger(self): return LOG_CATEGORY @handler("Disconnect") def _disconnect(self, receipt=None, flush=True, reconnect=False): try: if flush: self._subscribed = {} if self.connected: self._client.disconnect(receipt=receipt) except Exception as e: LOG.error("Failed to disconnect client") try: self.fire(Disconnected(reconnect=reconnect)) self._client.close(flush=flush) except Exception as e: LOG.error("Failed to close client connection") return "disconnected" def start_heartbeats(self): LOG.info("Client HB: %s Server HB: %s", self._client.clientHeartBeat, self._client.serverHeartBeat) if self._client.clientHeartBeat: if self.client_heartbeat: # Timer already exists, just reset it self.client_heartbeat.reset() else: LOG.info("Client will send heartbeats to server") # Send heartbeats at 80% of agreed rate self.client_heartbeat = Timer( (self._client.clientHeartBeat / 1000.0) * 0.8, ClientHeartbeat(), persist=True) self.client_heartbeat.register(self) else: LOG.info("No Client heartbeats will be sent") if self._client.serverHeartBeat: if self.server_heartbeat: # Timer already exists, just reset it self.server_heartbeat.reset() else: LOG.info("Requested heartbeats from server.") # Allow a grace period on server heartbeats self.server_heartbeat = Timer( (self._client.serverHeartBeat / 1000.0) * self.ALLOWANCE, ServerHeartbeat(), persist=True) self.server_heartbeat.register(self) else: LOG.info("Expecting no heartbeats from Server") @handler("Connect") def connect(self, event, host=None, *args, **kwargs): """ connect to Stomp server """ LOG.info("Connect to Stomp...") try: self._client.connect(heartBeats=self._heartbeats, host=host, versions=self._accept_versions, connectTimeout=self._connect_timeout, connectedTimeout=self._connected_timeout) LOG.debug("State after Connection Attempt: %s", self._client.session.state) if self.connected: LOG.info("Connected to %s", self._stomp_server) self.fire(Connected()) self.start_heartbeats() return "success" except StompConnectionError as err: LOG.debug(traceback.format_exc()) self.fire(ConnectionFailed(self._stomp_server)) event.success = False return "fail" @handler("ServerHeartbeat") def check_server_heartbeat(self, event): """ Confirm that heartbeat from server hasn't timed out """ now = time.time() self.last_heartbeat = self._client.lastReceived or self.last_heartbeat if self.last_heartbeat: elapsed = now - self.last_heartbeat else: elapsed = -1 if ((self._client.serverHeartBeat / 1000.0) * self.ALLOWANCE + self.last_heartbeat) < now: LOG.error( "Server heartbeat timeout. %d seconds since last heartbeat.", elapsed) event.success = False self.fire(HeartbeatTimeout()) @handler("ClientHeartbeat") def send_heartbeat(self, event): if self.connected: LOG.debug("Sending heartbeat") try: self._client.beat() except (StompConnectionError, StompError) as err: event.success = False self.fire(OnStompError(None, err)) @handler("generate_events") def generate_events(self, event): event.reduce_time_left(0.1) if not self.connected: return try: if self._client.canRead(0): frame = self._client.receiveFrame() LOG.debug("Recieved frame %s", frame) if frame.command == StompSpec.ERROR: self.fire(OnStompError(frame, None)) else: self.fire(Message(frame)) except (StompConnectionError, StompError) as err: LOG.error("Failed attempt to generate events.") self.fire(OnStompError(None, err)) @handler("Send") def send(self, event, destination, body, headers=None, receipt=None): LOG.debug("send()") try: self._client.send(destination, body=body.encode('utf-8'), headers=headers, receipt=receipt) LOG.debug("Message sent") except (StompConnectionError, StompError) as err: LOG.error("Error sending frame") event.success = False self.fire(OnStompError(None, err)) raise # To fire Send_failure event @handler("Subscribe") def _subscribe(self, event, destination, additional_headers=None, ack=ACK_CLIENT_INDIVIDUAL): if ack not in ACK_MODES: raise ValueError("Invalid client ack mode specified") if destination in self._client.session._subscriptions: LOG.debug("Ignoring subscribe request to %s. Already subscribed.", destination) LOG.info("Subscribe to message destination %s", destination) try: headers = {StompSpec.ACK_HEADER: ack, 'id': destination} if additional_headers: headers.update(additional_headers) # Set ID to match destination name for easy reference later frame, token = self._client.subscribe(destination, headers) self._subscribed[destination] = token except (StompConnectionError, StompError) as err: LOG.error("Failed to subscribe to queue.") event.success = False LOG.debug(traceback.format_exc()) self.fire(OnStompError(None, err)) @handler("Unsubscribe") def _unsubscribe(self, event, destination): if destination not in self._subscribed: LOG.error("Unsubscribe Request Ignored. Not subscribed to %s", destination) return try: token = self._subscribed.pop(destination) frame = self._client.unsubscribe(token) LOG.debug("Unsubscribed: %s", frame) except (StompConnectionError, StompError) as err: event.success = False LOG.error("Unsubscribe Failed.") self.fire(OnStompError(frame, err)) @handler("Message") def on_message(self, event, headers, message): LOG.debug("Stomp message received") @handler("Ack") def ack_frame(self, event, frame): LOG.debug("ack_frame()") try: self._client.ack(frame) LOG.debug("Ack Sent") except (StompConnectionError, StompError) as err: LOG.error("Error sending ack") event.success = False self.fire(OnStompError(frame, err)) raise # To fire Ack_failure event def get_subscription(self, frame): """ Get subscription from frame """ _, token = self._client.message(frame) return self._subscribed[token]
tmout = int(options.tmout) config = StompConfig('tcp://{0}:{1}'.format(broker, port)) client = Stomp(config) try: client.connect() except stompest.error.StompConnectTimeout: print('Unable to connect to {0}:{1}'.format(broker, port)) client.disconnect() sys.exit(1) else: print('STOMP connection established to {0}:{1}'.format(broker, port)) client.subscribe(from_queue, {StompSpec.ACK_HEADER: StompSpec.ACK_CLIENT_INDIVIDUAL}) while client.canRead(timeout=tmout): frame = client.receiveFrame() try: payload = json.loads(frame.body) except json.JSONDecoder: print("Failed to decode message body: frame.body was {}".format(frame.body)) with open('/opt/apache-activemq/sendfail/malformed', 'a+') as mf: mf.write('{0}\n{1}'.format(frame.headers, frame.body)) mf.close() continue headers = frame.headers print('Sending the following message to {} : '.format(to_queue)) print('body: {}'.format(payload)) print('headers: {}'.format(frame.headers)) try: client.ack(frame)
class client_activemq(): def __init__(self, worker_threads=2): self.log = logging.getLogger('client_activemq') self.log.debug('Initializing client_activemq') self.host = '127.0.0.1' #manually set here until there is a better place self.port = 61613 #manually set here until there is a better place self.worker_threads = worker_threads self.client = None self.connection_issue = True self.continue_running = True self.subscriptions = {} self.outbound_msg_queue = [] self.outbound_msg_queue_lazy = [] self.threads = [] self.work_queue = Queue.Queue() connection_handler = threading.Thread(target=self.connection_handler) connection_handler.daemon = True connection_handler.start() send_event_hopeful_thread = threading.Thread( target=self.send_event_hopeful_thread) send_event_hopeful_thread.daemon = True send_event_hopeful_thread.start() send_event_lazy_thread = threading.Thread( target=self.send_event_lazy_thread) send_event_lazy_thread.daemon = True send_event_lazy_thread.start() publish_loop = threading.Thread(target=self.publish_loop) publish_loop.daemon = True publish_loop.start() def init_connection(self): if (self.client != None and self.client.session.state == 'connected'): self.log.error('Re-init connection') try: self.client.disconnect() except: pass config = StompConfig('tcp://%s:%s' % (self.host, self.port), version=StompSpec.VERSION_1_1, check=True) self.client = Stomp(config) self.client.connect(heartBeats=(30000, 0), connectTimeout=1, connectedTimeout=1) def build_worker_pool(self, capacity): for thread in self.threads: if thread.is_alive() == False: self.threads.remove(thread) while len(self.threads) < capacity: t = threading.Thread(target=self.worker, args=(self.work_queue, )) t.daemon = True t.start() self.threads.append(t) def connection_handler(self): #This func will just try to reconnect repeatedly in a thread if we're flagged as having an issue. while (True): if (self.connection_issue == True): try: self.init_connection() self.connection_issue = False time.sleep(0.1) for subscription in self.subscriptions: self.log.info('Re-subscribing upon reconnection: %s' % subscription) self.subscribe( subscription, self.subscriptions[subscription]['callback_class'], self.subscriptions[subscription]['callback'], True, self.subscriptions[subscription]['selector']) except Exception as e: self.log.critical('Except: %s' % e) else: try: self.client.beat() except: self.log.warning('Failed to heartbeat?') self.build_worker_pool(self.worker_threads) time.sleep(10) def subscribe(self, queue, callback_class, callback, resub=False, selector=None): #This needs to exist so we can keep track of what subs we have and re-sub on reconnect if queue in self.subscriptions and not resub: self.log.info('Ignoring existing subscription %s' % queue) return True #we're already subscribed this_uuid = '%s' % uuid.uuid4() if (self.connection_issue == True): self.log.info( 'Cannot process subscription request as were not properly connected' ) self.subscriptions[queue] = { 'uuid': this_uuid, 'callback': callback, 'callback_class': callback_class, 'selector': selector } return None self.log.info('subscribe(%s %s %s %s)' % (queue, callback_class, callback, resub)) try: self.subscriptions[queue] = { 'uuid': this_uuid, 'callback': callback, 'callback_class': callback_class, 'selector': selector } if selector != None: self.client.subscribe( queue, { StompSpec.ID_HEADER: this_uuid, StompSpec.ACK_HEADER: StompSpec.ACK_AUTO, 'selector': selector }) else: self.client.subscribe( queue, { StompSpec.ID_HEADER: this_uuid, StompSpec.ACK_HEADER: StompSpec.ACK_AUTO, }) except Exception as e: self.log.fatal('%s' % e) self.connection_issue = True def unsubscribe(self, queue): if queue not in self.subscriptions: return False #cant unsubscribe, we're not subscribed if (self.connection_issue == True): del self.subscriptions[queue] return None try: self.client.unsubscribe(self.subscriptions[queue]['uuid']) del self.subscriptions[queue] except Exception as e: self.log.error('%s' % e) self.log.error('%s' % traceback.format_exc()) sys.exc_clear() self.connection_issue = True def send_event_lazy(self, destination, body, headers={}, persistent=False): headers['time_queued'] = time.time() self.outbound_msg_queue_lazy.append({ 'destination': destination, 'body': body, 'headers': headers, 'persistent': persistent }) def send_event_lazy_thread(self): while self.continue_running: time.sleep(0.001) #If it gets there, then great, if not, well we tried! if (self.connection_issue == True): continue while len(self.outbound_msg_queue_lazy ) > 0 and self.connection_issue == False: try: item = self.outbound_msg_queue_lazy.pop(0) if item['persistent'] == True: item['headers']['persistent'] = 'true' else: item['headers']['persistent'] = 'false' item['headers']['time_sent'] = time.time() self.client.send(item['destination'], json.dumps(item['body']), item['headers']) except Exception as e: self.log.critical('Except: %s' % e) self.outbound_msg_queue_lazy.insert(0, item) self.connection_issue = True def send_event_hopeful(self, destination, body, persist): self.outbound_msg_queue.append({ 'destination': destination, 'body': body }) def send_event_hopeful_thread(self): while self.continue_running: time.sleep(0.001) if (self.connection_issue == True): continue while len(self.outbound_msg_queue ) > 0 and self.connection_issue == False: try: item = self.outbound_msg_queue.pop(0) self.client.send(item['destination'], json.dumps(item['body']), {'persistent': 'false'}) except Exception as e: self.log.critical('Except: %s' % e) self.outbound_msg_queue.insert(0, item) self.connection_issue = True def worker(self, queue): while self.continue_running: try: item = queue.get() for x in 1, 2, 3: try: item['callback'](item['callback_class'], item['data'], item['headers']) break except Exception as e: self.log.error('Exception in worker thread: %s' % e) traceback.print_exc() sys.exc_clear() time.sleep(0.01) queue.task_done() except: pass def publish_loop(self): self.log.debug('publish_loop() init') time.sleep(0.2) while self.continue_running: if self.connection_issue == False: try: if not self.client.canRead(0.01): continue try: frame = self.client.receiveFrame() data = json.loads(frame.body) queue = frame.headers['destination'] try: time_sent = float(frame.headers['time_sent']) time_queued = float(frame.headers['time_queued']) send_latency = (time.time() - time_sent) queue_latency = (time_sent - time_queued) if queue_latency > 0.1: print 'Queue Latency: %s' % (queue_latency) if send_latency > 0.1: print 'Send Latency: %s' % (send_latency) except: pass self.work_queue.put({ 'callback': self.subscriptions[queue]['callback'], 'callback_class': self.subscriptions[queue]['callback_class'], 'data': data, 'headers': frame.headers, }) #self.client.ack(frame) except Exception as e: raise self.log.critical('Except: %s' % e) #self.client.nack(frame) except Exception as e: self.log.fatal('except: %s' % e) self.connection_issue = True
config = StompConfig('tcp://{0}:{1}'.format(broker, port)) client = Stomp(config) try: client.connect() except stompest.error.StompConnectTimeout: print('Unable to connect to {0}:{1}'.format(broker, port)) client.disconnect() sys.exit(1) else: print('STOMP connection established to {0}:{1}'.format(broker, port)) client.subscribe(from_queue, {StompSpec.ACK_HEADER: StompSpec.ACK_CLIENT_INDIVIDUAL}) while client.canRead(timeout=tmout): frame = client.receiveFrame() try: payload = json.loads(frame.body) except json.JSONDecoder: print("Failed to decode message body: frame.body was {}".format( frame.body)) with open('/opt/apache-activemq/sendfail/malformed', 'a+') as mf: mf.write('{0}\n{1}'.format(frame.headers, frame.body)) mf.close() continue headers = frame.headers print('Sending the following message to {} : '.format(to_queue)) print('body: {}'.format(payload)) print('headers: {}'.format(frame.headers)) try:
class JMSClient(object): """Class JMSClient """ _mh = None _client = None _host = None _port = None _user = None _passw = None _verbose = None _is_connected = None def __init__(self, verbose=False): """Class constructor Called when the object is initialized Args: verbose (bool): verbose mode """ try: self._mh = MasterHead.get_head() self._verbose = verbose if (self._verbose): basicConfig() getLogger().setLevel(DEBUG) except StompError as ex: self._mh.demsg('htk_on_error', ex, self._mh.fromhere()) @property def client(self): """ STOMP client property getter """ return self._client @property def host(self): """ server host property getter """ return self._host @property def port(self): """ server port property getter """ return self._port @property def user(self): """ username property getter """ return self._user @property def passw(self): """ user password property getter """ return self._passw @property def verbose(self): """ verbose mode property getter """ return self._verbose @property def is_connected(self): """ is_connected property getter """ return self._is_connected def connect(self, host, port=61613, user=None, passw=None, timeout=10): """Method connects to server Args: host (str): hostname port (str): port user (str): username passw (str): password timeout (int): timeout Returns: bool: result Raises: event: jms_before_connect event: jms_after_connected """ try: msg = 'host:{0}, port:{1}, user:{2}, passw:{3}, timeout:{4}'.format( host, port, user, passw, timeout) self._mh.demsg('htk_on_debug_info', self._mh._trn.msg( 'htk_jms_connecting', msg), self._mh.fromhere()) ev = event.Event( 'jms_before_connect', host, port, user, passw, timeout) if (self._mh.fire_event(ev) > 0): host = ev.argv(0) port = ev.argv(1) user = ev.argv(2) passw = ev.argv(3) timeout = ev.argv(4) self._host = host self._port = port self._user = user self._passw = passw if (ev.will_run_default()): self._client = Stomp(StompConfig('tcp://{0}:{1}'.format(self._host, self._port), login=self._user, passcode=self._passw)) self._client.connect( connectTimeout=timeout, connectedTimeout=timeout) self._is_connected = True self._mh.demsg('htk_on_debug_info', self._mh._trn.msg( 'htk_jms_connected'), self._mh.fromhere()) ev = event.Event('jms_after_connect') self._mh.fire_event(ev) return True except StompError as ex: self._mh.demsg('htk_on_error', ex, self._mh.fromhere()) return False def disconnect(self): """Method disconnects from server Args: none Returns: bool: result """ try: self._mh.demsg('htk_on_debug_info', self._mh._trn.msg( 'htk_jms_disconnecting'), self._mh.fromhere()) if (not self._is_connected): self._mh.demsg('htk_on_warning', self._mh._trn.msg( 'htk_jms_not_connected'), self._mh.fromhere()) return False else: self._client.disconnect() self._client.close() self._is_connected = False self._mh.demsg('htk_on_debug_info', self._mh._trn.msg( 'htk_jms_disconnected'), self._mh.fromhere()) return True except StompError as ex: self._mh.demsg('htk_on_error', ex, self._mh.fromhere()) return False def send(self, destination_name, message, destination_type='queue', headers={}): """Method sends message JMS headers - JMSCorrelationID, JMSExpiration, JMSDeliveryMode, JMSPriority, JMSReplyTo, JMSType Args: destination_name (str): queue|topic name message (str): message destination_type (str): queue|topic headers (dict): JMS headers, key - title, value - string Returns: bool: result Raises: event: jms_before_send event: jms_after_send """ try: msg = 'destination_name:{0}, message:{1}, destination_type:{2}, headers:{3}'.format( destination_name, message, destination_type, headers) self._mh.demsg('htk_on_debug_info', self._mh._trn.msg( 'htk_jms_sending_msg', msg), self._mh.fromhere()) if (not self._is_connected): self._mh.demsg('htk_on_warning', self._mh._trn.msg( 'htk_jms_not_connected'), self._mh.fromhere()) return False ev = event.Event( 'jms_before_send', destination_name, message, destination_type, headers) if (self._mh.fire_event(ev) > 0): destination_name = ev.argv(0) message = ev.argv(1) destination_type = ev.argv(2) headers = ev.argv(3) if (ev.will_run_default()): headers_new = {} for key, value in headers.items(): if (key in mapping): headers_new[mapping[key]] = value self._client.send('/{0}/{1}'.format(destination_type, destination_name), message if ( version_info[0] == 2) else message.encode('utf-8'), headers_new) self._mh.demsg('htk_on_debug_info', self._mh._trn.msg( 'htk_jms_msg_sent'), self._mh.fromhere()) ev = event.Event('jms_after_send') self._mh.fire_event(ev) return True except StompError as ex: self._mh.demsg('htk_on_error', ex, self._mh.fromhere()) return False def receive(self, destination_name, cnt=1): """Method receives messages Args: destination_name (str): queue name cnt (int): count of messages Returns: list: messages as dictionary {'message', JMS headers} Raises: event: jms_before_receive event: jms_after_receive """ try: msg = 'destination_name:{0}, count:{1}'.format( destination_name, cnt) self._mh.demsg('htk_on_debug_info', self._mh._trn.msg( 'htk_jms_receiving_msg', msg), self._mh.fromhere()) if (not self._is_connected): self._mh.demsg('htk_on_warning', self._mh._trn.msg( 'htk_jms_not_connected'), self._mh.fromhere()) return None ev = event.Event('jms_before_receive', destination_name, cnt) if (self._mh.fire_event(ev) > 0): destination_name = ev.argv(0) cnt = ev.argv(1) if (ev.will_run_default()): token = self._client.subscribe('/queue/{0}'.format(destination_name), {StompSpec.ACK_HEADER: StompSpec.ACK_CLIENT_INDIVIDUAL}) msgs = [] i = 0 while (i < cnt and self._client.canRead(1)): frame = self._client.receiveFrame() if (frame.command != 'MESSAGE'): break self._client.ack(frame) msgs.append(frame) i = i + 1 self._client.unsubscribe(token) messages = [] for msg in msgs: message = {} message['message'] = msg.body.decode() for header in msg.rawHeaders: if (header[0] in mapping.values()): message[ list(mapping.keys())[list(mapping.values()).index(header[0])]] = header[1] messages.append(message) self._mh.demsg('htk_on_debug_info', self._mh._trn.msg( 'htk_jms_msg_received', len(messages)), self._mh.fromhere()) ev = event.Event('jms_after_receive') self._mh.fire_event(ev) return messages except StompError as ex: self._mh.demsg('htk_on_error', ex, self._mh.fromhere()) return None def browse(self, destination_name, cnt=100, jms_correlation_id=None, jms_type=None): """Method browses queue Args: destination_name (str): queue name cnt (int): count of messages jms_correlation_id (str): requested JMSCorrelationID jms_type (str): requested JMSType Returns: list: messages as dictionary {'message', JMS headers} Raises: event: jms_before_browse event: jms_after_browse """ try: msg = 'destination_name:{0}, count:{1}, jms_correlation_id:{2}, jms_type:{3}'.format( destination_name, cnt, jms_correlation_id, jms_type) self._mh.demsg('htk_on_debug_info', self._mh._trn.msg( 'htk_jms_browsing', msg), self._mh.fromhere()) if (not self._is_connected): self._mh.demsg('htk_on_warning', self._mh._trn.msg( 'htk_jms_not_connected'), self._mh.fromhere()) return None ev = event.Event( 'jms_before_browse', destination_name, cnt, jms_correlation_id, jms_type) if (self._mh.fire_event(ev) > 0): destination_name = ev.argv(0) cnt = ev.argv(1) jms_correlation_id = ev.argv(2) jms_type = ev.argv(3) if (ev.will_run_default()): token = self._client.subscribe('/queue/{0}'.format(destination_name), {StompSpec.ACK_HEADER: StompSpec.ACK_CLIENT_INDIVIDUAL}) msgs = [] i = 0 while (i < cnt and self._client.canRead(1)): frame = self._client.receiveFrame() correlation_id = None type = None for header in frame.rawHeaders: if (header[0] == 'correlation-id'): correlation_id = header[1] elif (header[0] == 'type'): type = header[1] if ((jms_correlation_id == None or jms_correlation_id == correlation_id) and (jms_type == None or jms_type == type)): msgs.append(frame) i = i + 1 self._client.unsubscribe(token) messages = [] for msg in msgs: message = {} message['message'] = msg.body.decode() for header in msg.rawHeaders: if (header[0] in mapping.values()): message[ list(mapping.keys())[list(mapping.values()).index(header[0])]] = header[1] messages.append(message) self._mh.demsg('htk_on_debug_info', self._mh._trn.msg( 'htk_jms_msg_received', len(messages)), self._mh.fromhere()) ev = event.Event('jms_after_browse') self._mh.fire_event(ev) return messages except StompError as ex: self._mh.demsg('htk_on_error', ex, self._mh.fromhere()) return None
def get_next_order(email): role = get_user(email).get('role') conn = get_connection() returnid = None if role == 'OrderAdmin': cursor = conn.cursor() cursor.execute("SELECT * FROM next_order where status= 'Ordered'") rows = cursor.fetchall() returnid = None if len(rows) < 1: amq_conf = None queue = '/queue/ordered' #if isOpen('activemq.default', 61612): amq_conf = StompConfig('tcp://activemq-service.default:61613') #else: # amq_conf = StompConfig('tcp://localhost:30012') try: client = Stomp(amq_conf) client.connect() client.subscribe( queue, {StompSpec.ACK_HEADER: StompSpec.ACK_CLIENT_INDIVIDUAL}) if client.canRead(timeout=2): frame = client.receiveFrame() cursor = conn.cursor() sql = "Insert into next_order (status, order_id) values (%s,%s)" values = ('Ordered', int(frame.body.decode())) row = cursor.execute(sql, values) conn.commit() client.ack(frame) returnid = int(frame.body.decode()) else: returnid = None client.disconnect() except: print("something went wrong") returnid = None else: returnid = rows[0][0] elif role == 'ShipmentAdmin': cursor = conn.cursor() cursor.execute("SELECT * FROM next_order where status= 'ReadyToShip'") rows = cursor.fetchall() returnid = None if len(rows) < 1: amq_conf = None queue = '/queue/readytoship' #if isOpen('activemq.default', 61612): amq_conf = StompConfig('tcp://activemq-service.default:61613') #else: # amq_conf = StompConfig('tcp://localhost:30012') try: client = Stomp(amq_conf) client.connect() client.subscribe( queue, {StompSpec.ACK_HEADER: StompSpec.ACK_CLIENT_INDIVIDUAL}) if client.canRead(timeout=2): frame = client.receiveFrame() cursor = conn.cursor() sql = "Insert into next_order (status, order_id) values (%s,%s)" values = ('ReadyToShip', int(frame.body.decode())) row = cursor.execute(sql, values) conn.commit() client.ack(frame) returnid = int(frame.body.decode()) else: returnid = None client.disconnect() except: print("something went wrong") returnid = None else: returnid = rows[0][0] elif role == 'DeliveryAdmin': cursor = conn.cursor() cursor.execute("SELECT * FROM next_order where status= 'Shipped'") rows = cursor.fetchall() returnid = None if len(rows) < 1: amq_conf = None queue = '/queue/shipped' #if isOpen('activemq.default', 61612): amq_conf = StompConfig('tcp://activemq-service.default:61613') #else: # amq_conf = StompConfig('tcp://localhost:30012') try: client = Stomp(amq_conf) client.connect() client.subscribe( queue, {StompSpec.ACK_HEADER: StompSpec.ACK_CLIENT_INDIVIDUAL}) if client.canRead(timeout=2): frame = client.receiveFrame() cursor = conn.cursor() sql = "Insert into next_order (status, order_id) values (%s,%s)" values = ('Shipped', int(frame.body.decode())) row = cursor.execute(sql, values) conn.commit() client.ack(frame) returnid = int(frame.body.decode()) else: returnid = None client.disconnect() except: print("something went wrong") returnid = None else: returnid = rows[0][0] if returnid: cursor = conn.cursor() cursor.execute( "SELECT * FROM orders join order_details on orders.order_id = order_details.order_id where orders.order_id = " + str(returnid) + "") rows = cursor.fetchall() print(rows) processed_orders = [] result = [] for row in rows: order_id = row[0] if order_id not in processed_orders: order = {'order_id': order_id} order['total_amount'] = row[1] order['created_on'] = str(row[2]) order['status'] = row[3] order['products'] = [] result.append(order) processed_orders.append(order_id) for row in rows: order_id = row[0] product = {} product['product_name'] = row[8] product['product_id'] = row[6] product['quantity'] = row[9] product['unit_cost'] = row[10] for i in range(len(result)): if result[i]['order_id'] == order_id: result[i]['products'].append(product) conn.close() return result else: conn.close() return []