combine all the broker replacement pieces

* local redis for event processing
* postgres for message broker
* redis for websockets
This commit is contained in:
chris meyers
2020-01-08 15:44:04 -05:00
committed by Ryan Petrello
parent 558e92806b
commit 2a2c34f567
14 changed files with 188 additions and 343 deletions

View File

@@ -1,11 +1,14 @@
import logging
import socket
from django.conf import settings
import string
import random
import json
from awx.main.dispatch import get_local_queuename
from kombu import Queue, Exchange, Producer, Consumer, Connection
from . import pg_bus_conn
logger = logging.getLogger('awx.main.dispatch')
@@ -19,15 +22,10 @@ class Control(object):
raise RuntimeError('{} must be in {}'.format(service, self.services))
self.service = service
self.queuename = host or get_local_queuename()
self.queue = Queue(self.queuename, Exchange(self.queuename), routing_key=self.queuename)
def publish(self, msg, conn, **kwargs):
producer = Producer(
exchange=self.queue.exchange,
channel=conn,
routing_key=self.queuename
)
producer.publish(msg, expiration=5, **kwargs)
# TODO: delete this method??
raise RuntimeError("Publish called?!")
def status(self, *args, **kwargs):
return self.control_with_reply('status', *args, **kwargs)
@@ -35,24 +33,29 @@ class Control(object):
def running(self, *args, **kwargs):
return self.control_with_reply('running', *args, **kwargs)
@classmethod
def generate_reply_queue_name(cls):
letters = string.ascii_lowercase
return 'reply_to_{}'.format(''.join(random.choice(letters) for i in range(8)))
def control_with_reply(self, command, timeout=5):
logger.warn('checking {} {} for {}'.format(self.service, command, self.queuename))
reply_queue = Queue(name="amq.rabbitmq.reply-to")
reply_queue = Control.generate_reply_queue_name()
self.result = None
with Connection(settings.BROKER_URL, transport_options=settings.BROKER_TRANSPORT_OPTIONS) as conn:
with Consumer(conn, reply_queue, callbacks=[self.process_message], no_ack=True):
self.publish({'control': command}, conn, reply_to='amq.rabbitmq.reply-to')
try:
conn.drain_events(timeout=timeout)
except socket.timeout:
logger.error('{} did not reply within {}s'.format(self.service, timeout))
raise
return self.result
with pg_bus_conn() as conn:
conn.listen(reply_queue)
conn.notify(self.queuename,
json.dumps({'control': command, 'reply_to': reply_queue}))
for reply in conn.events(select_timeout=timeout, yield_timeouts=True):
if reply is None:
logger.error(f'{self.service} did not reply within {timeout}s')
raise RuntimeError("{self.service} did not reply within {timeout}s")
break
return json.loads(reply.payload)
def control(self, msg, **kwargs):
with Connection(settings.BROKER_URL, transport_options=settings.BROKER_TRANSPORT_OPTIONS) as conn:
self.publish(msg, conn)
def process_message(self, body, message):
self.result = body
message.ack()
with pg_bus_conn() as conn:
conn.notify(self.queuename, json.dumps(msg))