Non puoi selezionare più di 25 argomenti
Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
152 righe
5.2 KiB
152 righe
5.2 KiB
import logging |
|
import time |
|
import json |
|
import pika |
|
import subprocess |
|
import sys |
|
import threading |
|
import os |
|
from distutils.util import strtobool |
|
|
|
class JixelBackgroundTaskHandler(): |
|
|
|
def __init__( |
|
self, rabbitmq_username, rabbitmq_password, |
|
rabbitmq_host, rabbitmq_port, rabbitmq_queue, |
|
rabbitmq_heartbeat, execution_path, logger, |
|
discarding_mode=False |
|
): |
|
self.rabbitmq_username = rabbitmq_username |
|
self.rabbitmq_password = rabbitmq_password |
|
self.rabbitmq_host = rabbitmq_host |
|
self.rabbitmq_port = rabbitmq_port |
|
self.rabbitmq_queue = rabbitmq_queue |
|
self.rabbitmq_heartbeat = int(rabbitmq_heartbeat) |
|
self.execution_path = execution_path |
|
self.logger = logger |
|
self.discarding_mode = strtobool(discarding_mode) |
|
self.logger.info("JixelBackgroundTaskHandler - Initialization...") |
|
self.credentials = pika.PlainCredentials( |
|
self.rabbitmq_username , |
|
self.rabbitmq_password |
|
) |
|
self.connection = pika.BlockingConnection( |
|
pika.ConnectionParameters( |
|
host=self.rabbitmq_host, |
|
port=int(self.rabbitmq_port), |
|
credentials=self.credentials,heartbeat=self.rabbitmq_heartbeat |
|
) |
|
) |
|
self.channel = self.connection.channel() |
|
self.logger.info("JixelBackgroundTaskHandler - Initialization completed successfully") |
|
self.channel.queue_declare(queue=self.rabbitmq_queue, durable=True) |
|
self.logger.info("JixelBackgroundTaskHandler - " + self.rabbitmq_queue + " queue declared") |
|
self.channel.queue_declare(queue=self.rabbitmq_queue+'_errors', durable=True) |
|
self.logger.info("JixelBackgroundTaskHandler - " + self.rabbitmq_queue + "_errors queue declared") |
|
self.channel.basic_qos(prefetch_count=1) |
|
self.logger.info("JixelBackgroundTaskHandler - Queue handler declared") |
|
self.channel.basic_consume( |
|
on_message_callback=self.__data_handler, |
|
queue=self.rabbitmq_queue |
|
) |
|
|
|
def consume(self): |
|
|
|
try: |
|
self.channel.start_consuming() |
|
except KeyboardInterrupt: |
|
self.channel.stop_consuming() |
|
|
|
self.channel.close() |
|
|
|
def __execute_command(self, mr): |
|
self.logger.info('JixelBackgroundTaskHandler - Processing thread is running:') |
|
command = [self.execution_path + 'cake'] |
|
command += mr['command'].split(' ') |
|
command += [mr['data']] |
|
self.logger.info('JixelBackgroundTaskHandler - Executing shell command:') |
|
self.logger.info(command) |
|
|
|
try: |
|
subprocess.check_call(command) |
|
self.result = True |
|
except subprocess.CalledProcessError as error: |
|
self.logger.error('JixelBackgroundTaskHandler - An error as occured during processing:') |
|
self.logger.error(error) |
|
self.result = False |
|
|
|
def __data_processing(self, channel, mr): |
|
self.logger.info(mr) |
|
self.logger.info('JixelBackgroundTaskHandler - Starting processing thread:') |
|
self.result = None |
|
thread = threading.Thread(target=self.__execute_command, args=(mr,)) |
|
thread.start() |
|
|
|
while thread.is_alive(): |
|
self.connection.process_data_events() |
|
|
|
self.logger.info("JixelBackgroundTaskHandler - Result received:") |
|
self.logger.info(self.result) |
|
if (self.result is not True): |
|
self.__send_error(json.dumps(mr)) |
|
return self.result |
|
|
|
def __send_ack_nack(self, ack, channel, method): |
|
if ack is True: |
|
self.logger.info("JixelBackgroundTaskHandler - Ack performed") |
|
channel.basic_ack(delivery_tag=method.delivery_tag) |
|
else: |
|
self.logger.info("JixelBackgroundTaskHandler - Nack performed BECAUSE ERRORS OCCURRED!") |
|
channel.basic_reject(delivery_tag=method.delivery_tag) |
|
|
|
def __data_handler(self, channel, method, properties, body): |
|
self.logger.info('JixelBackgroundTaskHandler - New message received:') |
|
error = False |
|
|
|
try: |
|
mr = json.loads(body.decode()) |
|
error = not self.__data_processing(channel, mr) |
|
except json.JSONDecodeError as error: |
|
self.logger.error("JixelBackgroundTaskHandler - Malformed message") |
|
self.logger.error(error) |
|
self.logger.error("JixelBackgroundTaskHandler - This message will be removed from the queue") |
|
self.__send_ack_nack(False, channel, method) |
|
time.sleep(60) |
|
return |
|
|
|
if self.result is True and error is False: |
|
self.__send_ack_nack(True, channel, method) |
|
else: |
|
self.logger.error("JixelBackgroundTaskHandler - An error has occured during processing") |
|
if self.discarding_mode is True: |
|
self.logger.error("JixelBackgroundTaskHandler - Discarding mode enabled.") |
|
self.__send_ack_nack(True, channel, method) |
|
else: |
|
self.__send_ack_nack(False, channel, method) |
|
|
|
time.sleep(5) |
|
|
|
self.logger.info("JixelBackgroundTaskHandler - Data handling complete. Waiting for new messages") |
|
|
|
def __send_error(self, message): |
|
self.channel.basic_publish(exchange='', routing_key=self.rabbitmq_queue+'_errors', body=message) |
|
|
|
if __name__ == '__main__': |
|
logger = logging.getLogger("JixelBackgroundTaskHandler") |
|
logger.setLevel(logging.INFO) |
|
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") |
|
terminal_log = logging.StreamHandler(sys.stdout) |
|
terminal_log.setFormatter(formatter) |
|
logger.addHandler(terminal_log) |
|
app = JixelBackgroundTaskHandler( |
|
os.environ['RABBITMQ_USERNAME'], |
|
os.environ['RABBITMQ_PASSWORD'], |
|
os.environ['rabbitmq_host'], |
|
os.environ['rabbitmq_port'], |
|
os.environ['rabbitmq_queue'], |
|
os.environ['rabbitmq_heartbeat'], |
|
os.environ['execution_path'], |
|
logger, |
|
os.environ['discarding_mode'] |
|
) |
|
app.consume()
|
|
|