-
Notifications
You must be signed in to change notification settings - Fork 6
fixed connection issues I found #174
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
309ebc0
d25f1ab
cad46b2
2b38039
6cb407d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -44,10 +44,10 @@ | |||||
| """ | ||||||
| import base64 | ||||||
| import inspect | ||||||
| #import json | ||||||
| import logging | ||||||
| import os | ||||||
| import random | ||||||
| import re | ||||||
| import threading | ||||||
| from collections import defaultdict | ||||||
| from datetime import datetime | ||||||
|
|
@@ -58,6 +58,10 @@ | |||||
| from stomp import Connection12 as Connection | ||||||
| from stomp.exception import NotConnectedException | ||||||
| from time import sleep | ||||||
| try: # python2.7 | ||||||
| from urlparse import urlparse | ||||||
| except ImportError: | ||||||
| from urllib.parse import urlparse | ||||||
|
|
||||||
| from gridappsd import json_extension as json | ||||||
|
|
||||||
|
|
@@ -119,6 +123,22 @@ def __init__(self, | |||||
|
|
||||||
| if not self.__user__ or not self.__pass__: | ||||||
| raise ValueError("Invalid username/password specified.") | ||||||
|
|
||||||
| if self.stomp_address is None or self.stomp_address == '': | ||||||
| raise ValueError("Invalid stomp address specified.") | ||||||
|
|
||||||
| if not self.stomp_address.startswith("tcp://"): | ||||||
| self.stomp_address = "tcp://" + self.stomp_address | ||||||
|
|
||||||
| parsed_address = urlparse(self.stomp_address) | ||||||
|
|
||||||
| if self.stomp_port is None or self.stomp_port == '': | ||||||
| if parsed_address.port is not None: | ||||||
| self.stomp_port = parsed_address.port | ||||||
| else: | ||||||
| raise ValueError("Invalid stomp port specified.") | ||||||
|
|
||||||
| self._connection_tuple = [(parsed_address.hostname, int(self.stomp_port))] | ||||||
| self._conn = None | ||||||
| self._ids = set() | ||||||
| self._topic_set = set() | ||||||
|
|
@@ -306,7 +326,7 @@ def _make_connection(self): | |||||
| # send request to token topic | ||||||
| tokenTopic = "/topic/pnnl.goss.token.topic" | ||||||
|
|
||||||
| tmpConn = Connection([(self.stomp_address, self.stomp_port)]) | ||||||
| tmpConn = Connection([*self._connection_tuple]) | ||||||
| if self._override_thread_fc is not None: | ||||||
| tmpConn.transport.override_threading(self._override_thread_fc) | ||||||
| tmpConn.connect(self.__user__, self.__pass__, wait=True) | ||||||
|
|
@@ -349,7 +369,7 @@ def on_disconnect(self, header, message): | |||||
| sleep(1) | ||||||
| iter += 1 | ||||||
|
|
||||||
| self._conn = Connection([(self.stomp_address, self.stomp_port)]) | ||||||
| self._conn = Connection([*self._connection_tuple]) | ||||||
| if self._override_thread_fc is not None: | ||||||
| self._conn.transport.override_threading(self._override_thread_fc) | ||||||
| try: | ||||||
|
|
@@ -369,49 +389,62 @@ class CallbackRouter(object): | |||||
|
|
||||||
| def __init__(self): | ||||||
| self.callbacks = {} | ||||||
| self._topics_callback_map = defaultdict(list) | ||||||
| self._queue_callerback = Queue() | ||||||
| self._topic_callbacks = defaultdict(list) | ||||||
| self._queue_callback = Queue() | ||||||
| self._thread = threading.Thread(target=self.run_callbacks) | ||||||
| self._thread.daemon = True | ||||||
| self._thread.start() | ||||||
|
|
||||||
| def run_callbacks(self): | ||||||
| _log.debug("Starting thread queue") | ||||||
| while True: | ||||||
| cb, hdrs, msg = self._queue_callerback.get() | ||||||
| callbacks, headers, msg = self._queue_callback.get() | ||||||
| try: | ||||||
| msg = json.loads(msg) | ||||||
| except: | ||||||
| pass | ||||||
| # msg = message | ||||||
|
|
||||||
| for c in cb: | ||||||
| c(hdrs, msg) | ||||||
| for callback in callbacks: | ||||||
| callback(headers, msg) | ||||||
| except Exception as e: | ||||||
| _log.error(f"Error in callback execution: {e}") | ||||||
| sleep(0.01) | ||||||
|
|
||||||
| def add_callback(self, topic, callback): | ||||||
| if not topic.startswith('/topic/') and not topic.startswith('/temp-queue/'): | ||||||
| topic = "/queue/{topic}".format(topic=topic) | ||||||
| if callback in self._topics_callback_map[topic]: | ||||||
| raise ValueError("Callbacks can only be used one time per topic") | ||||||
| _log.debug("Added callbac using topic {topic}".format(topic=topic)) | ||||||
| self._topics_callback_map[topic].append(callback) | ||||||
|
|
||||||
| def remove_callback(self, topic, callback): | ||||||
| if topic in self._topics_callback_map: | ||||||
| callbacks = self._topics_callback_map[topic] | ||||||
| def add_callback(self, topic_pattern, callback): | ||||||
| """ Add a callback for a topic, supporting wildcards. | ||||||
|
|
||||||
| The topic can contain wildcards (based upon activmeq artemis | ||||||
| https://activemq.apache.org/components/classic/documentation/stomp-manual): | ||||||
|
|
||||||
| - '*' matches any level (e.g., `/topic/goss.gridappsd.field.heartbeat.*`) | ||||||
| - '**' matches multiple levels (e.g., `/topic/goss.gridappsd.**`) | ||||||
|
|
||||||
| :param topic_pattern: Topic string, allowing `*` or `**` as wildcards. | ||||||
| :param callback: Function to call when a matching message is received. | ||||||
| """ | ||||||
| regex_pattern = re.escape(topic_pattern).replace(r'\*', '[^/]+').replace(r'\*\*', '.*') | ||||||
|
||||||
| regex_pattern = re.escape(topic_pattern).replace(r'\*', '[^/]+').replace(r'\*\*', '.*') | |
| regex_pattern = re.escape(topic_pattern).replace(r'\*\*', '.*').replace(r'\*', '[^/]+') |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -69,16 +69,19 @@ class GridAPPSD(GOSS): | |||||
| # TODO Get the caller from the traceback/inspect module. | ||||||
| def __init__(self, simulation_id=None, address=None, **kwargs): | ||||||
|
|
||||||
| if address is None: | ||||||
| address = utils.get_gridappsd_address() | ||||||
|
|
||||||
| if 'stomp_address' in kwargs and 'stomp_port' in kwargs: | ||||||
| address = (kwargs.pop('stomp_address'), kwargs.pop('stomp_port')) | ||||||
| elif 'stomp_address' in kwargs and not 'stomp_port' in kwargs or \ | ||||||
| 'stomp_port' in kwargs and not 'stomp_address' in kwargs: | ||||||
| raise ValueError("If stomp_address is specified the so should stomp_port") | ||||||
|
|
||||||
| super(GridAPPSD, self).__init__(stomp_address=address[0], stomp_port=address[1], **kwargs) | ||||||
| if address is None: | ||||||
| super().__init__(**kwargs) | ||||||
| elif isinstance(address, tuple) or isinstance(address, list) and len(address) == 2: | ||||||
|
||||||
| elif isinstance(address, tuple) or isinstance(address, list) and len(address) == 2: | |
| elif isinstance(address, tuple) or (isinstance(address, list) and len(address) == 2): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic in the connect method is confusing: the else branch logs an error when gridappsd_obj is already set. Consider revising the condition to ensure that an existing, valid GridAPPSD object is used instead of logging an error.