Skip to content

Commit 325d1d6

Browse files
authored
Merge pull request #18 from clowder-framework/no-rabbitmq-stop
No rabbitmq stop
2 parents 288c366 + cef0d75 commit 325d1d6

File tree

4 files changed

+75
-59
lines changed

4 files changed

+75
-59
lines changed

CHANGELOG.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,27 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](http://keepachangelog.com/)
55
and this project adheres to [Semantic Versioning](http://semver.org/).
66

7+
## 2.3.2 - 2020-09-24
8+
9+
### Fixed
10+
- When rabbitmq restarts the extractor would not stop and restart, resulting
11+
in the extractor no longer receiving any messages. #17
12+
13+
### Added
14+
- Can specify url to use for extractor downloads, this is helpful for instances
15+
that have access to the internal URL for clowder, for example in docker/kubernetes.
16+
17+
### Removed
18+
- Removed ability to run multiple connectors in the same python process. If
19+
parallelism is needed, use multiple processes (or containers).
20+
721
## 2.3.1 - 2020-09-18
822

923
With this version we no longer gurantee support for versions of python below 3.
1024

1125
### Fixed
12-
- There was an issue where status messages could cause an exception. This would prevent most extractors from running correctly.
26+
- There was an issue where status messages could cause an exception. This would
27+
prevent most extractors from running correctly.
1328

1429
## 2.3.0 - 2020-09-15
1530

pyclowder/connectors.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,9 @@ def listen(self):
731731
self.connection.close()
732732
except Exception:
733733
logging.getLogger(__name__).exception("Error while closing connection.")
734+
if self.announcer:
735+
self.announcer.stop_thread()
736+
734737
self.connection = None
735738

736739
def stop(self):
@@ -811,6 +814,9 @@ def start_thread(self):
811814
self.thread.setDaemon(True)
812815
self.thread.start()
813816

817+
def stop_thread(self):
818+
self.thread = None
819+
814820
def send_heartbeat(self):
815821
# create the message we will send
816822
message = {
@@ -872,6 +878,7 @@ def start_thread(self, json_body):
872878
"""
873879
self.thread = threading.Thread(target=self._process_message, args=(json_body,))
874880
self.thread.start()
881+
self.thread.setDaemon(True)
875882

876883
def is_finished(self):
877884
with self.lock:

pyclowder/extractors.py

Lines changed: 51 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,6 @@ def __init__(self):
8181
help='connector to use (default=RabbitMQ)')
8282
self.parser.add_argument('--logging', '-l', nargs='?', default=logging_config,
8383
help='file or url or logging coonfiguration (default=None)')
84-
self.parser.add_argument('--num', '-n', type=int, nargs='?', default=1,
85-
help='number of parallel instances (default=1)')
8684
self.parser.add_argument('--pickle', nargs='*', dest="hpc_picklefile",
8785
default=None, action='append',
8886
help='pickle file that needs to be processed (only needed for HPC)')
@@ -129,32 +127,32 @@ def setup(self):
129127
def start(self):
130128
"""Create the connector and start listening.
131129
132-
Based on the num command line argument this will start multiple instances of a connector and run each of them
133-
in their own thread. Once the connector(s) are created this function will go into a endless loop until either
130+
Start a single instance of a connector and run it in their own thread.
131+
Once the connector(s) are created this function will go into a endless loop until either
134132
all connectors have stopped or the user kills the program.
135133
"""
136134
logger = logging.getLogger(__name__)
137-
connectors = list()
138-
for connum in range(self.args.num):
139-
if self.args.connector == "RabbitMQ":
140-
if 'rabbitmq_uri' not in self.args:
141-
logger.error("Missing URI for RabbitMQ")
142-
else:
143-
rabbitmq_key = []
144-
if not self.args.nobind:
145-
for key, value in self.extractor_info['process'].items():
146-
for mt in value:
147-
# Replace trailing '*' with '#'
148-
mt = re.sub('(\*$)', '#', mt)
149-
if mt.find('*') > -1:
150-
logger.error("Invalid '*' found in rabbitmq_key: %s" % mt)
135+
connector = None
136+
137+
if self.args.connector == "RabbitMQ":
138+
if 'rabbitmq_uri' not in self.args:
139+
logger.error("Missing URI for RabbitMQ")
140+
else:
141+
rabbitmq_key = []
142+
if not self.args.nobind:
143+
for key, value in self.extractor_info['process'].items():
144+
for mt in value:
145+
# Replace trailing '*' with '#'
146+
mt = re.sub('(\*$)', '#', mt)
147+
if mt.find('*') > -1:
148+
logger.error("Invalid '*' found in rabbitmq_key: %s" % mt)
149+
else:
150+
if mt == "":
151+
rabbitmq_key.append("*.%s.#" % key)
151152
else:
152-
if mt == "":
153-
rabbitmq_key.append("*.%s.#" % key)
154-
else:
155-
rabbitmq_key.append("*.%s.%s" % (key, mt.replace("/", ".")))
153+
rabbitmq_key.append("*.%s.%s" % (key, mt.replace("/", ".")))
156154

157-
rconn = RabbitMQConnector(self.args.rabbitmq_queuename,
155+
connector = RabbitMQConnector(self.args.rabbitmq_queuename,
158156
self.extractor_info,
159157
check_message=self.check_message,
160158
process_message=self.process_message,
@@ -164,54 +162,50 @@ def start(self):
164162
rabbitmq_queue=self.args.rabbitmq_queuename,
165163
mounted_paths=json.loads(self.args.mounted_paths),
166164
clowder_url=self.args.clowder_url)
167-
rconn.connect()
168-
rconn.register_extractor(self.args.registration_endpoints)
169-
connectors.append(rconn)
170-
threading.Thread(target=rconn.listen, name="Connector-" + str(connum)).start()
171-
elif self.args.connector == "HPC":
172-
if 'hpc_picklefile' not in self.args:
173-
logger.error("Missing hpc_picklefile for HPCExtractor")
174-
else:
175-
hconn = HPCConnector(self.extractor_info['name'],
165+
connector.connect()
166+
connector.register_extractor(self.args.registration_endpoints)
167+
threading.Thread(target=connector.listen, name="RabbitMQConnector").start()
168+
169+
elif self.args.connector == "HPC":
170+
if 'hpc_picklefile' not in self.args:
171+
logger.error("Missing hpc_picklefile for HPCExtractor")
172+
else:
173+
connector = HPCConnector(self.extractor_info['name'],
176174
self.extractor_info,
177175
check_message=self.check_message,
178176
process_message=self.process_message,
179177
picklefile=self.args.hpc_picklefile,
180178
mounted_paths=json.loads(self.args.mounted_paths))
181-
hconn.register_extractor(self.args.registration_endpoints)
182-
connectors.append(hconn)
183-
threading.Thread(target=hconn.listen, name="Connector-" + str(connum)).start()
184-
elif self.args.connector == "Local":
185-
186-
if self.args.input_file_path is None:
187-
logger.error("Environment variable INPUT_FILE_PATH or parameter --input-file-path is not set. "
188-
"Please try again after setting one of these")
189-
elif not os.path.isfile(self.args.input_file_path):
190-
logger.error("Local input file is not a regular file. Please check the path.")
191-
else:
192-
local_connector = LocalConnector(self.extractor_info['name'],
193-
self.extractor_info,
194-
self.args.input_file_path,
195-
process_message=self.process_message,
196-
output_file_path=self.args.output_file_path)
197-
connectors.append(local_connector)
198-
threading.Thread(target=local_connector.listen, name="Connector-" + str(connum)).start()
179+
connector.register_extractor(self.args.registration_endpoints)
180+
threading.Thread(target=connector.listen, name="HPCConnector").start()
181+
182+
elif self.args.connector == "Local":
183+
if self.args.input_file_path is None:
184+
logger.error("Environment variable INPUT_FILE_PATH or parameter "
185+
"--input-file-path is not set. Please try again after "
186+
"setting one of these")
187+
elif not os.path.isfile(self.args.input_file_path):
188+
logger.error("Local input file is not a regular file. Please check the path.")
199189
else:
200-
logger.error("Could not create instance of %s connector.", self.args.connector)
201-
sys.exit(-1)
190+
connector = LocalConnector(self.extractor_info['name'],
191+
self.extractor_info,
192+
self.args.input_file_path,
193+
process_message=self.process_message,
194+
output_file_path=self.args.output_file_path)
195+
threading.Thread(target=connector.listen, name="LocalConnector").start()
196+
else:
197+
logger.error("Could not create instance of %s connector.", self.args.connector)
198+
sys.exit(-1)
202199

203200
logger.info("Waiting for messages. To exit press CTRL+C")
204201
try:
205-
while connectors:
202+
while connector.alive():
206203
time.sleep(1)
207-
connectors = filter(lambda x: x.alive(), connectors)
208204
except KeyboardInterrupt:
209205
pass
210206
except BaseException:
211207
logger.exception("Error while consuming messages.")
212-
213-
for c in connectors:
214-
c.stop()
208+
connector.stop()
215209

216210
def get_metadata(self, content, resource_type, resource_id, server=None):
217211
"""Generate a metadata field.

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ def description():
99

1010

1111
setup(name='pyclowder',
12-
version='2.3.1',
12+
version='2.3.2',
1313
packages=find_packages(),
1414
description='Python SDK for the Clowder Data Management System',
1515
long_description=description(),

0 commit comments

Comments
 (0)