forked from ansible/awx
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
replace celery task decorators with a kombu-based publisher
this commit implements the bulk of `awx-manage run_dispatcher`, a new command that binds to RabbitMQ via kombu and balances messages across a pool of workers that are similar to celeryd workers in spirit. Specifically, this includes: - a new decorator, `awx.main.dispatch.task`, which can be used to decorate functions or classes so that they can be designated as "Tasks" - support for fanout/broadcast tasks (at this point in time, only `conf.Setting` memcached flushes use this functionality) - support for job reaping - support for success/failure hooks for job runs (i.e., `handle_work_success` and `handle_work_error`) - support for auto scaling worker pool that scale processes up and down on demand - minimal support for RPC, such as status checks and pool recycle/reload
- Loading branch information
1 parent
da74f1d
commit ff1e8cc
Showing
54 changed files
with
1,603 additions
and
1,144 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from django.conf import settings | ||
|
||
|
||
def get_local_queuename(): | ||
return settings.CLUSTER_HOST_ID.encode('utf-8') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import logging | ||
import socket | ||
|
||
from django.conf import settings | ||
|
||
from awx.main.dispatch import get_local_queuename | ||
from kombu import Connection, Queue, Exchange, Producer, Consumer | ||
|
||
logger = logging.getLogger('awx.main.dispatch') | ||
|
||
|
||
class Control(object): | ||
|
||
services = ('dispatcher', 'callback_receiver') | ||
result = None | ||
|
||
def __init__(self, service): | ||
if service not in self.services: | ||
raise RuntimeError('{} must be in {}'.format(service, self.services)) | ||
self.service = service | ||
queuename = get_local_queuename() | ||
self.queue = Queue(queuename, Exchange(queuename), routing_key=queuename) | ||
|
||
def publish(self, msg, conn, host, **kwargs): | ||
producer = Producer( | ||
exchange=self.queue.exchange, | ||
channel=conn, | ||
routing_key=get_local_queuename() | ||
) | ||
producer.publish(msg, expiration=5, **kwargs) | ||
|
||
def status(self, *args, **kwargs): | ||
return self.control_with_reply('status', *args, **kwargs) | ||
|
||
def running(self, *args, **kwargs): | ||
return self.control_with_reply('running', *args, **kwargs) | ||
|
||
def control_with_reply(self, command, host=None, timeout=5): | ||
host = host or settings.CLUSTER_HOST_ID | ||
logger.warn('checking {} {} for {}'.format(self.service, command, host)) | ||
reply_queue = Queue(name="amq.rabbitmq.reply-to") | ||
self.result = None | ||
with Connection(settings.BROKER_URL) as conn: | ||
with Consumer(conn, reply_queue, callbacks=[self.process_message], no_ack=True): | ||
self.publish({'control': command}, conn, host, 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 | ||
|
||
def control(self, msg, host=None, **kwargs): | ||
host = host or settings.CLUSTER_HOST_ID | ||
with Connection(settings.BROKER_URL) as conn: | ||
self.publish(msg, conn, host) | ||
|
||
def process_message(self, body, message): | ||
self.result = body | ||
message.ack() |
Oops, something went wrong.