From 07aea5e5c1d0b464089e4b90a324b042ccae5115 Mon Sep 17 00:00:00 2001 From: zhangliyong Date: Thu, 14 Aug 2014 15:11:43 +0800 Subject: [PATCH 01/27] Add CLI `rq` to empty queues and requeue failed jobs --- requirements.txt | 1 + rq/scripts/rq.py | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100755 rq/scripts/rq.py diff --git a/requirements.txt b/requirements.txt index 7800f0f..539b9a4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ redis +click diff --git a/rq/scripts/rq.py b/rq/scripts/rq.py new file mode 100755 index 0000000..882195c --- /dev/null +++ b/rq/scripts/rq.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +rq command line tool +""" +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import click +import redis +from rq import get_failed_queue, Queue, use_connection +from rq.exceptions import InvalidJobOperationError + + +@click.group() +@click.option('--url', '-u', envvar='URL', + help='URL describing Redis connection details.') +def rq(url): + if url is None: + url = "redis://localhost:6379/0" + redis_conn = redis.from_url(url) + use_connection(redis_conn) + + +@rq.command() +@click.argument('queues', nargs=-1) +def empty(queues): + """Empty queues, default: empty failed queue + + $ rq empty + 2 jobs removed from failed queue + + $ rq empty default high + 10 jobs removed from default queue + 2 jobs removed from high queue + """ + queues = list(map(Queue, queues)) + if not queues: + queues = (get_failed_queue(),) + for queue in queues: + num_jobs = queue.empty() + print('{} jobs removed from {} queue'.format(num_jobs, queue.name)) + + +@rq.command() +def requeue(): + """Requeue all failed jobs in failed queue""" + failed_queue = get_failed_queue() + job_ids = failed_queue.job_ids + print('Requeuing {} failed jobs......'.format(len(job_ids))) + requeue_failed_num = 0 + for job_id in job_ids: + try: + failed_queue.requeue(job_id) + except InvalidJobOperationError: + print('Requeue job({}) failed'.format(job_id)) + requeue_failed_num += 1 + + print('Requeue over with {} jobs requeuing failed'.format( + requeue_failed_num)) From e1d236ec02b2fd21ceb421b5a85a533a7eec84c6 Mon Sep 17 00:00:00 2001 From: zhangliyong Date: Thu, 14 Aug 2014 15:56:35 +0800 Subject: [PATCH 02/27] Use click.echo instead of print to output --- rq/scripts/rq.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rq/scripts/rq.py b/rq/scripts/rq.py index 882195c..668a58b 100755 --- a/rq/scripts/rq.py +++ b/rq/scripts/rq.py @@ -39,7 +39,7 @@ def empty(queues): queues = (get_failed_queue(),) for queue in queues: num_jobs = queue.empty() - print('{} jobs removed from {} queue'.format(num_jobs, queue.name)) + click.echo('{} jobs removed from {} queue'.format(num_jobs, queue.name)) @rq.command() @@ -47,14 +47,14 @@ def requeue(): """Requeue all failed jobs in failed queue""" failed_queue = get_failed_queue() job_ids = failed_queue.job_ids - print('Requeuing {} failed jobs......'.format(len(job_ids))) + click.echo('Requeuing {} failed jobs......'.format(len(job_ids))) requeue_failed_num = 0 for job_id in job_ids: try: failed_queue.requeue(job_id) except InvalidJobOperationError: - print('Requeue job({}) failed'.format(job_id)) + click.echo('Requeue job({}) failed'.format(job_id)) requeue_failed_num += 1 - print('Requeue over with {} jobs requeuing failed'.format( - requeue_failed_num)) + click.secho('Requeue over with {} jobs requeuing failed'.format( + requeue_failed_num), fg='red') From 36880db872b858f1613e71082dd1075c90f52ef1 Mon Sep 17 00:00:00 2001 From: zhangliyong Date: Fri, 15 Aug 2014 14:20:00 +0800 Subject: [PATCH 03/27] Show progressbar when requeuing --- rq/scripts/rq.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/rq/scripts/rq.py b/rq/scripts/rq.py index 668a58b..f15e543 100755 --- a/rq/scripts/rq.py +++ b/rq/scripts/rq.py @@ -47,14 +47,14 @@ def requeue(): """Requeue all failed jobs in failed queue""" failed_queue = get_failed_queue() job_ids = failed_queue.job_ids - click.echo('Requeuing {} failed jobs......'.format(len(job_ids))) + click.echo('Requeue failed jobs: {}'.format(len(job_ids))) requeue_failed_num = 0 - for job_id in job_ids: - try: - failed_queue.requeue(job_id) - except InvalidJobOperationError: - click.echo('Requeue job({}) failed'.format(job_id)) - requeue_failed_num += 1 - - click.secho('Requeue over with {} jobs requeuing failed'.format( + with click.progressbar(job_ids) as job_bar: + for job_id in job_bar: + try: + failed_queue.requeue(job_id) + except InvalidJobOperationError: + requeue_failed_num += 1 + + click.secho('Requeue failed: {}'.format( requeue_failed_num), fg='red') From f845ae25a230140f316dfbe92e86db612969d434 Mon Sep 17 00:00:00 2001 From: zhangliyong Date: Fri, 15 Aug 2014 15:06:55 +0800 Subject: [PATCH 04/27] Make command empty help message friendly --- rq/scripts/rq.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rq/scripts/rq.py b/rq/scripts/rq.py index f15e543..31d9d3f 100755 --- a/rq/scripts/rq.py +++ b/rq/scripts/rq.py @@ -27,9 +27,10 @@ def rq(url): def empty(queues): """Empty queues, default: empty failed queue + \b $ rq empty 2 jobs removed from failed queue - + \b $ rq empty default high 10 jobs removed from default queue 2 jobs removed from high queue From 81febc6dc5183399f2edd2bf95e19961962c5e60 Mon Sep 17 00:00:00 2001 From: zhangliyong Date: Fri, 15 Aug 2014 16:24:34 +0800 Subject: [PATCH 05/27] Format empty help message --- rq/scripts/rq.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rq/scripts/rq.py b/rq/scripts/rq.py index 31d9d3f..328ea91 100755 --- a/rq/scripts/rq.py +++ b/rq/scripts/rq.py @@ -25,7 +25,7 @@ def rq(url): @rq.command() @click.argument('queues', nargs=-1) def empty(queues): - """Empty queues, default: empty failed queue + """[QUEUES]: queues to empty, default: failed queue \b $ rq empty From e948bde5d77aed42d16533dfafa9e05d9bc64067 Mon Sep 17 00:00:00 2001 From: zhangliyong Date: Fri, 15 Aug 2014 16:25:14 +0800 Subject: [PATCH 06/27] Add rq command when installing --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index a49b126..5ac56b8 100644 --- a/setup.py +++ b/setup.py @@ -17,7 +17,7 @@ def get_version(): def get_dependencies(): - deps = ['redis >= 2.7.0'] + deps = ['redis >= 2.7.0', 'click > 3.0'] if sys.version_info < (2, 7) or \ (sys.version_info >= (3, 0) and sys.version_info < (3, 1)): deps += ['importlib'] @@ -43,6 +43,7 @@ setup( install_requires=get_dependencies(), entry_points='''\ [console_scripts] + rq = rq.scripts.rq:rq rqworker = rq.scripts.rqworker:main rqinfo = rq.scripts.rqinfo:main ''', From 551483b477345fb340ecec92e954f63687a97285 Mon Sep 17 00:00:00 2001 From: zhangliyong Date: Tue, 19 Aug 2014 10:29:39 +0800 Subject: [PATCH 07/27] Add rq info command --- rq/scripts/{rq.py => rq_cli.py} | 11 ++- rq/scripts/rqinfo.py | 138 ++++++++++++++------------------ setup.py | 2 +- 3 files changed, 68 insertions(+), 83 deletions(-) rename rq/scripts/{rq.py => rq_cli.py} (94%) diff --git a/rq/scripts/rq.py b/rq/scripts/rq_cli.py similarity index 94% rename from rq/scripts/rq.py rename to rq/scripts/rq_cli.py index 328ea91..a9470af 100755 --- a/rq/scripts/rq.py +++ b/rq/scripts/rq_cli.py @@ -11,18 +11,20 @@ import redis from rq import get_failed_queue, Queue, use_connection from rq.exceptions import InvalidJobOperationError +from rqinfo import info + @click.group() @click.option('--url', '-u', envvar='URL', help='URL describing Redis connection details.') -def rq(url): +def main(url): if url is None: url = "redis://localhost:6379/0" redis_conn = redis.from_url(url) use_connection(redis_conn) -@rq.command() +@main.command() @click.argument('queues', nargs=-1) def empty(queues): """[QUEUES]: queues to empty, default: failed queue @@ -43,7 +45,7 @@ def empty(queues): click.echo('{} jobs removed from {} queue'.format(num_jobs, queue.name)) -@rq.command() +@main.command() def requeue(): """Requeue all failed jobs in failed queue""" failed_queue = get_failed_queue() @@ -59,3 +61,6 @@ def requeue(): click.secho('Requeue failed: {}'.format( requeue_failed_num), fg='red') + + +main.add_command(info) diff --git a/rq/scripts/rqinfo.py b/rq/scripts/rqinfo.py index 48d318a..d9a51a2 100755 --- a/rq/scripts/rqinfo.py +++ b/rq/scripts/rqinfo.py @@ -3,20 +3,18 @@ from __future__ import (absolute_import, division, print_function, unicode_literals) -import argparse -import os import sys import time +import click +from functools import partial from redis.exceptions import ConnectionError -from rq import get_failed_queue, Queue, Worker -from rq.scripts import (add_standard_arguments, read_config_file, - setup_default_arguments, setup_redis) -from rq.utils import gettermsize, make_colorizer +from rq import Queue, Worker -red = make_colorizer('darkred') -green = make_colorizer('darkgreen') -yellow = make_colorizer('darkyellow') + +red = partial(click.style, fg='red') +green = partial(click.style, fg='green') +yellow = partial(click.style, fg='yellow') def pad(s, pad_to_length): @@ -44,14 +42,14 @@ def state_symbol(state): return state -def show_queues(args): - if len(args.queues): - qs = list(map(Queue, args.queues)) +def show_queues(queues, raw, by_queue): + if len(queues): + qs = list(map(Queue, queues)) else: qs = Queue.all() num_jobs = 0 - termwidth, _ = gettermsize() + termwidth, _ = click.get_terminal_size() chartwidth = min(20, termwidth - 20) max_count = 0 @@ -65,23 +63,23 @@ def show_queues(args): for q in qs: count = counts[q] - if not args.raw: + if not raw: chart = green('|' + '█' * int(ratio * count)) line = '%-12s %s %d' % (q.name, chart, count) else: line = 'queue %s %d' % (q.name, count) - print(line) + click.echo(line) num_jobs += count - # Print summary when not in raw mode - if not args.raw: - print('%d queues, %d jobs total' % (len(qs), num_jobs)) + # print summary when not in raw mode + if not raw: + click.echo('%d queues, %d jobs total' % (len(qs), num_jobs)) -def show_workers(args): - if len(args.queues): - qs = list(map(Queue, args.queues)) +def show_workers(queues, raw, by_queue): + if len(queues): + qs = list(map(Queue, queues)) def any_matching_queue(worker): def queue_matches(q): @@ -99,13 +97,13 @@ def show_workers(args): ws = Worker.all() filter_queues = lambda x: x - if not args.by_queue: + if not by_queue: for w in ws: worker_queues = filter_queues(w.queue_names()) - if not args.raw: - print('%s %s: %s' % (w.name, state_symbol(w.get_state()), ', '.join(worker_queues))) + if not raw: + click.echo('%s %s: %s' % (w.name, state_symbol(w.get_state()), ', '.join(worker_queues))) else: - print('worker %s %s %s' % (w.name, w.get_state(), ','.join(worker_queues))) + click.echo('worker %s %s %s' % (w.name, w.get_state(), ','.join(worker_queues))) else: # Create reverse lookup table queues = dict([(q, []) for q in qs]) @@ -121,78 +119,60 @@ def show_workers(args): queues_str = ", ".join(sorted(map(lambda w: '%s (%s)' % (w.name, state_symbol(w.get_state())), queues[q]))) # noqa else: queues_str = '–' - print('%s %s' % (pad(q.name + ':', max_qname + 1), queues_str)) + click.echo('%s %s' % (pad(q.name + ':', max_qname + 1), queues_str)) - if not args.raw: - print('%d workers, %d queues' % (len(ws), len(qs))) + if not raw: + click.echo('%d workers, %d queues' % (len(ws), len(qs))) -def show_both(args): - show_queues(args) - if not args.raw: - print('') - show_workers(args) - if not args.raw: - print('') +def show_both(queues, raw, by_queue): + show_queues(queues, raw, by_queue) + if not raw: + click.echo('') + show_workers(queues, raw, by_queue) + if not raw: + click.echo('') import datetime - print('Updated: %s' % datetime.datetime.now()) - + click.echo('Updated: %s' % datetime.datetime.now()) -def parse_args(): - parser = argparse.ArgumentParser(description='RQ command-line monitor.') - add_standard_arguments(parser) - parser.add_argument('--path', '-P', default='.', help='Specify the import path.') - parser.add_argument('--interval', '-i', metavar='N', type=float, default=2.5, help='Updates stats every N seconds (default: don\'t poll)') # noqa - parser.add_argument('--raw', '-r', action='store_true', default=False, help='Print only the raw numbers, no bar charts') # noqa - parser.add_argument('--only-queues', '-Q', dest='only_queues', default=False, action='store_true', help='Show only queue info') # noqa - parser.add_argument('--only-workers', '-W', dest='only_workers', default=False, action='store_true', help='Show only worker info') # noqa - parser.add_argument('--by-queue', '-R', dest='by_queue', default=False, action='store_true', help='Shows workers by queue') # noqa - parser.add_argument('--empty-failed-queue', '-X', dest='empty_failed_queue', default=False, action='store_true', help='Empties the failed queue, then quits') # noqa - parser.add_argument('queues', nargs='*', help='The queues to poll') - return parser.parse_args() - -def interval(val, func, args): +def refresh(val, func, *args): while True: - if val and sys.stdout.isatty(): - os.system('clear') - func(args) - if val and sys.stdout.isatty(): + if val: + click.clear() + func(*args) + if val: time.sleep(val) else: break -def main(): - args = parse_args() - - if args.path: - sys.path = args.path.split(':') + sys.path +@click.command() +@click.option('--path', '-P', default='.', help='Specify the import path.') +@click.option('--interval', '-i', default=2.5, help='Updates stats every N seconds (default: don\'t poll)') # noqa +@click.option('--raw', '-r', is_flag=True, help='Print only the raw numbers, no bar charts') # noqa +@click.option('--only-queues', '-Q', is_flag=True, help='Show only queue info') # noqa +@click.option('--only-workers', '-W', is_flag=True, help='Show only worker info') # noqa +@click.option('--by-queue', '-R', is_flag=True, help='Shows workers by queue') # noqa +@click.argument('queues', nargs=-1) +def info(path, interval, raw, only_queues, only_workers, by_queue, queues): + """RQ command-line monitor.""" - settings = {} - if args.config: - settings = read_config_file(args.config) - - setup_default_arguments(args, settings) - - setup_redis(args) + if path: + sys.path = path.split(':') + sys.path try: - if args.empty_failed_queue: - num_jobs = get_failed_queue().empty() - print('{} jobs removed from failed queue'.format(num_jobs)) + if only_queues: + func = show_queues + elif only_workers: + func = show_workers else: - if args.only_queues: - func = show_queues - elif args.only_workers: - func = show_workers - else: - func = show_both + func = show_both - interval(args.interval, func, args) + refresh(interval, func, queues, raw, by_queue) except ConnectionError as e: - print(e) + click.echo(e) sys.exit(1) except KeyboardInterrupt: - print() + click.echo() sys.exit(0) diff --git a/setup.py b/setup.py index 5ac56b8..3aeddc2 100644 --- a/setup.py +++ b/setup.py @@ -43,7 +43,7 @@ setup( install_requires=get_dependencies(), entry_points='''\ [console_scripts] - rq = rq.scripts.rq:rq + rq = rq.scripts.rq_cli:main rqworker = rq.scripts.rqworker:main rqinfo = rq.scripts.rqinfo:main ''', From adc24b6fe0bcf3b95e8eb44b1601dab1ee1aacb3 Mon Sep 17 00:00:00 2001 From: zhangliyong Date: Thu, 21 Aug 2014 11:00:24 +0800 Subject: [PATCH 08/27] Fix import error --- rq/scripts/rq_cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rq/scripts/rq_cli.py b/rq/scripts/rq_cli.py index a9470af..172d777 100755 --- a/rq/scripts/rq_cli.py +++ b/rq/scripts/rq_cli.py @@ -11,7 +11,7 @@ import redis from rq import get_failed_queue, Queue, use_connection from rq.exceptions import InvalidJobOperationError -from rqinfo import info +from .rqinfo import info @click.group() From c90da5336ed711ee8d1954e58e2f660122a3a49b Mon Sep 17 00:00:00 2001 From: zhangliyong Date: Thu, 21 Aug 2014 14:41:10 +0800 Subject: [PATCH 09/27] Avoid using use_connection, initial queues directly using redis connection --- rq/scripts/rq_cli.py | 24 ++++++++++++++++-------- rq/scripts/rqinfo.py | 7 +++++-- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/rq/scripts/rq_cli.py b/rq/scripts/rq_cli.py index 172d777..c69adc4 100755 --- a/rq/scripts/rq_cli.py +++ b/rq/scripts/rq_cli.py @@ -8,7 +8,7 @@ from __future__ import (absolute_import, division, print_function, import click import redis -from rq import get_failed_queue, Queue, use_connection +from rq import get_failed_queue, Queue from rq.exceptions import InvalidJobOperationError from .rqinfo import info @@ -17,16 +17,21 @@ from .rqinfo import info @click.group() @click.option('--url', '-u', envvar='URL', help='URL describing Redis connection details.') -def main(url): +@click.pass_context +def main(ctx, url): + """Entrance of RQ CLI""" if url is None: url = "redis://localhost:6379/0" redis_conn = redis.from_url(url) - use_connection(redis_conn) + + ctx.obj = {} + ctx.obj['connection'] = redis_conn @main.command() @click.argument('queues', nargs=-1) -def empty(queues): +@click.pass_context +def empty(ctx, queues): """[QUEUES]: queues to empty, default: failed queue \b @@ -37,18 +42,21 @@ def empty(queues): 10 jobs removed from default queue 2 jobs removed from high queue """ - queues = list(map(Queue, queues)) + conn = ctx.obj['connection'] + queues = [Queue(queue, connection=conn) for queue in queues] if not queues: - queues = (get_failed_queue(),) + queues = (get_failed_queue(connection=conn),) for queue in queues: num_jobs = queue.empty() click.echo('{} jobs removed from {} queue'.format(num_jobs, queue.name)) @main.command() -def requeue(): +@click.pass_context +def requeue(ctx): """Requeue all failed jobs in failed queue""" - failed_queue = get_failed_queue() + conn = ctx.obj['connection'] + failed_queue = get_failed_queue(connection=conn) job_ids = failed_queue.job_ids click.echo('Requeue failed jobs: {}'.format(len(job_ids))) requeue_failed_num = 0 diff --git a/rq/scripts/rqinfo.py b/rq/scripts/rqinfo.py index d9a51a2..fa402a8 100755 --- a/rq/scripts/rqinfo.py +++ b/rq/scripts/rqinfo.py @@ -9,7 +9,7 @@ import click from functools import partial from redis.exceptions import ConnectionError -from rq import Queue, Worker +from rq import Queue, Worker, use_connection red = partial(click.style, fg='red') @@ -155,12 +155,15 @@ def refresh(val, func, *args): @click.option('--only-workers', '-W', is_flag=True, help='Show only worker info') # noqa @click.option('--by-queue', '-R', is_flag=True, help='Shows workers by queue') # noqa @click.argument('queues', nargs=-1) -def info(path, interval, raw, only_queues, only_workers, by_queue, queues): +@click.pass_context +def info(ctx, path, interval, raw, only_queues, only_workers, by_queue, queues): """RQ command-line monitor.""" if path: sys.path = path.split(':') + sys.path + conn = ctx.obj['connection'] + use_connection(conn) try: if only_queues: func = show_queues From 1e5a8b58a131453ce5dd73ebd997528885927ee9 Mon Sep 17 00:00:00 2001 From: zhangliyong Date: Thu, 21 Aug 2014 15:14:39 +0800 Subject: [PATCH 10/27] Use -y option to confirm emptying failed queue by default --- rq/scripts/rq_cli.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/rq/scripts/rq_cli.py b/rq/scripts/rq_cli.py index c69adc4..94a04d1 100755 --- a/rq/scripts/rq_cli.py +++ b/rq/scripts/rq_cli.py @@ -29,13 +29,19 @@ def main(ctx, url): @main.command() +@click.option('--yes', '-y', is_flag=True, + help='Empty failed queue by default') @click.argument('queues', nargs=-1) @click.pass_context -def empty(ctx, queues): - """[QUEUES]: queues to empty, default: failed queue +def empty(ctx, yes, queues): + """[QUEUES]: queues to empty \b $ rq empty + Do you want to empty failed queue? [y/N]: y + 2 jobs removed from failed queue + \b + $ rq empty -y 2 jobs removed from failed queue \b $ rq empty default high @@ -45,7 +51,9 @@ def empty(ctx, queues): conn = ctx.obj['connection'] queues = [Queue(queue, connection=conn) for queue in queues] if not queues: - queues = (get_failed_queue(connection=conn),) + if yes or click.confirm('Do you want to empty failed queue?', + abort=True): + queues = (get_failed_queue(connection=conn),) for queue in queues: num_jobs = queue.empty() click.echo('{} jobs removed from {} queue'.format(num_jobs, queue.name)) From 0c4e28bd625e2885b5b2cd712377f51abe0bea61 Mon Sep 17 00:00:00 2001 From: zhangliyong Date: Fri, 22 Aug 2014 10:08:15 +0800 Subject: [PATCH 11/27] Use 'with Connection' instead of 'use_connection' --- rq/scripts/rqinfo.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rq/scripts/rqinfo.py b/rq/scripts/rqinfo.py index fa402a8..7f96c5f 100755 --- a/rq/scripts/rqinfo.py +++ b/rq/scripts/rqinfo.py @@ -9,7 +9,7 @@ import click from functools import partial from redis.exceptions import ConnectionError -from rq import Queue, Worker, use_connection +from rq import Queue, Worker, Connection red = partial(click.style, fg='red') @@ -163,7 +163,6 @@ def info(ctx, path, interval, raw, only_queues, only_workers, by_queue, queues): sys.path = path.split(':') + sys.path conn = ctx.obj['connection'] - use_connection(conn) try: if only_queues: func = show_queues @@ -172,7 +171,8 @@ def info(ctx, path, interval, raw, only_queues, only_workers, by_queue, queues): else: func = show_both - refresh(interval, func, queues, raw, by_queue) + with Connection(conn): + refresh(interval, func, queues, raw, by_queue) except ConnectionError as e: click.echo(e) sys.exit(1) From 1ab92602e802a3a33fca5b5f549a665f3c6d4cc4 Mon Sep 17 00:00:00 2001 From: zhangliyong Date: Fri, 22 Aug 2014 10:08:53 +0800 Subject: [PATCH 12/27] Add testcase for rq_cli --- tests/test_scripts.py | 45 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/tests/test_scripts.py b/tests/test_scripts.py index 88689c3..54b0104 100644 --- a/tests/test_scripts.py +++ b/tests/test_scripts.py @@ -2,8 +2,14 @@ from __future__ import (absolute_import, division, print_function, unicode_literals) +from click.testing import CliRunner +from rq import get_failed_queue from rq.compat import is_python_version -from rq.scripts import read_config_file +from rq.job import Job +from rq.scripts import read_config_file, rq_cli + +from tests import RQTestCase +from tests.fixtures import div_by_zero if is_python_version((2, 7), (3, 2)): from unittest import TestCase @@ -16,3 +22,40 @@ class TestScripts(TestCase): settings = read_config_file("tests.dummy_settings") self.assertIn("REDIS_HOST", settings) self.assertEqual(settings['REDIS_HOST'], "testhost.example.com") + + +class TestRQCli(RQTestCase): + """Test rq_cli script""" + def setUp(self): + super(TestRQCli, self).setUp() + db_num = self.testconn.connection_pool.connection_kwargs['db'] + self.redis_url = 'redis://127.0.0.1:6379/%d' % db_num + + job = Job.create(func=div_by_zero, args=(1, 2, 3)) + job.origin = 'fake' + job.save() + get_failed_queue().quarantine(job, Exception('Some fake error')) # noqa + + def test_empty(self): + """rq -u empty -y""" + runner = CliRunner() + result = runner.invoke(rq_cli.main, + ['-u', self.redis_url, 'empty', "-y"]) + self.assertEqual(result.exit_code, 0) + self.assertEqual(result.output, '1 jobs removed from failed queue\n') + + def test_requeue(self): + """rq -u requeue""" + runner = CliRunner() + result = runner.invoke(rq_cli.main, ['-u', self.redis_url, 'requeue']) + self.assertEqual(result.exit_code, 0) + self.assertIn('Requeue failed jobs: 1', result.output) + self.assertIn('Requeue failed: 0', result.output) + + def test_info(self): + """rq -u info -i 0""" + runner = CliRunner() + result = runner.invoke(rq_cli.main, + ['-u', self.redis_url, 'info', '-i 0']) + self.assertEqual(result.exit_code, 0) + self.assertIn('1 queues, 1 jobs total', result.output) From 1c97a5506400c86bf363ab0570052e96fc868d38 Mon Sep 17 00:00:00 2001 From: zhangliyong Date: Fri, 22 Aug 2014 10:45:26 +0800 Subject: [PATCH 13/27] compat str.format syntax with py26 --- rq/scripts/rq_cli.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rq/scripts/rq_cli.py b/rq/scripts/rq_cli.py index 94a04d1..602bc59 100755 --- a/rq/scripts/rq_cli.py +++ b/rq/scripts/rq_cli.py @@ -56,7 +56,7 @@ def empty(ctx, yes, queues): queues = (get_failed_queue(connection=conn),) for queue in queues: num_jobs = queue.empty() - click.echo('{} jobs removed from {} queue'.format(num_jobs, queue.name)) + click.echo('{0} jobs removed from {1} queue'.format(num_jobs, queue.name)) @main.command() @@ -66,7 +66,7 @@ def requeue(ctx): conn = ctx.obj['connection'] failed_queue = get_failed_queue(connection=conn) job_ids = failed_queue.job_ids - click.echo('Requeue failed jobs: {}'.format(len(job_ids))) + click.echo('Requeue failed jobs: {0}'.format(len(job_ids))) requeue_failed_num = 0 with click.progressbar(job_ids) as job_bar: for job_id in job_bar: @@ -75,7 +75,7 @@ def requeue(ctx): except InvalidJobOperationError: requeue_failed_num += 1 - click.secho('Requeue failed: {}'.format( + click.secho('Requeue failed: {0}'.format( requeue_failed_num), fg='red') From 37748e5aceba91c6238c22a3be44c4f938b2a609 Mon Sep 17 00:00:00 2001 From: zhangliyong Date: Fri, 22 Aug 2014 10:54:25 +0800 Subject: [PATCH 14/27] Make pep8 --- rq/scripts/rq_cli.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rq/scripts/rq_cli.py b/rq/scripts/rq_cli.py index 602bc59..f86153d 100755 --- a/rq/scripts/rq_cli.py +++ b/rq/scripts/rq_cli.py @@ -56,7 +56,8 @@ def empty(ctx, yes, queues): queues = (get_failed_queue(connection=conn),) for queue in queues: num_jobs = queue.empty() - click.echo('{0} jobs removed from {1} queue'.format(num_jobs, queue.name)) + click.echo('{0} jobs removed from {1} queue'.format( + num_jobs, queue.name)) @main.command() From 5670f251d8f8b53a22693d807dc7a80df452e7cf Mon Sep 17 00:00:00 2001 From: zhangliyong Date: Mon, 1 Sep 2014 14:04:48 +0700 Subject: [PATCH 15/27] Add '--all' option and [JOB_IDS] argument to specify what to requeue --- rq/scripts/rq_cli.py | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/rq/scripts/rq_cli.py b/rq/scripts/rq_cli.py index f86153d..d0df189 100755 --- a/rq/scripts/rq_cli.py +++ b/rq/scripts/rq_cli.py @@ -61,13 +61,31 @@ def empty(ctx, yes, queues): @main.command() +@click.option('--all', '-a', 'is_all', is_flag=True, + help='Requeue all failed jobs') +@click.argument('job_ids', nargs=-1) @click.pass_context -def requeue(ctx): - """Requeue all failed jobs in failed queue""" +def requeue(ctx, is_all, job_ids): + """[JOB_IDS] Job_ids in FailedQueue to requeue + + \b + $ rq requeue -a + Requeueing 10 jobs from FailedQueue + [####################################] 100% + Unable to requeue 0 jobs from FailedQueue + + \b + $ rq requeue a28bd044-65f3-42dd-96ee-acfcea155ba7\ + ac5559e1-90a0-4ab5-8e68-0d854b47b969 + Requeueing 2 jobs from FailedQueue + [####################################] 100% + Unable to requeue 1 jobs from FailedQueue + """ conn = ctx.obj['connection'] failed_queue = get_failed_queue(connection=conn) - job_ids = failed_queue.job_ids - click.echo('Requeue failed jobs: {0}'.format(len(job_ids))) + if not job_ids and is_all: + job_ids = failed_queue.job_ids + click.echo('Requeueing {0} jobs from FailedQueue'.format(len(job_ids))) requeue_failed_num = 0 with click.progressbar(job_ids) as job_bar: for job_id in job_bar: @@ -76,7 +94,7 @@ def requeue(ctx): except InvalidJobOperationError: requeue_failed_num += 1 - click.secho('Requeue failed: {0}'.format( + click.secho('Unable to requeue {0} jobs from FailedQueue'.format( requeue_failed_num), fg='red') From f734708ad437b618a34ab917f7de7d3241b3b2f1 Mon Sep 17 00:00:00 2001 From: zhangliyong Date: Mon, 1 Sep 2014 14:06:14 +0700 Subject: [PATCH 16/27] Make pythonic --- rq/scripts/rqinfo.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rq/scripts/rqinfo.py b/rq/scripts/rqinfo.py index 7f96c5f..abf7d2b 100755 --- a/rq/scripts/rqinfo.py +++ b/rq/scripts/rqinfo.py @@ -43,7 +43,7 @@ def state_symbol(state): def show_queues(queues, raw, by_queue): - if len(queues): + if queues: qs = list(map(Queue, queues)) else: qs = Queue.all() @@ -78,7 +78,7 @@ def show_queues(queues, raw, by_queue): def show_workers(queues, raw, by_queue): - if len(queues): + if queues: qs = list(map(Queue, queues)) def any_matching_queue(worker): From 8782b11f1e78453d84c5d03e9c7cbce04355a1c5 Mon Sep 17 00:00:00 2001 From: zhangliyong Date: Mon, 1 Sep 2014 14:08:36 +0700 Subject: [PATCH 17/27] Adjust test_requeue --- tests/test_scripts.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/test_scripts.py b/tests/test_scripts.py index 54b0104..c92a908 100644 --- a/tests/test_scripts.py +++ b/tests/test_scripts.py @@ -49,8 +49,9 @@ class TestRQCli(RQTestCase): runner = CliRunner() result = runner.invoke(rq_cli.main, ['-u', self.redis_url, 'requeue']) self.assertEqual(result.exit_code, 0) - self.assertIn('Requeue failed jobs: 1', result.output) - self.assertIn('Requeue failed: 0', result.output) + self.assertIn('Requeueing 1 jobs from FailedQueue', result.output) + self.assertIn('Unable to requeue 0 jobs from FailedQueue', + result.output) def test_info(self): """rq -u info -i 0""" From 0ddd1748682bc6f6193c9ef1be33a83c9c02c08b Mon Sep 17 00:00:00 2001 From: zhangliyong Date: Mon, 1 Sep 2014 14:13:40 +0700 Subject: [PATCH 18/27] Fix invoking requeue command bug in test_requeue --- tests/test_scripts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_scripts.py b/tests/test_scripts.py index c92a908..3f2a659 100644 --- a/tests/test_scripts.py +++ b/tests/test_scripts.py @@ -47,7 +47,7 @@ class TestRQCli(RQTestCase): def test_requeue(self): """rq -u requeue""" runner = CliRunner() - result = runner.invoke(rq_cli.main, ['-u', self.redis_url, 'requeue']) + result = runner.invoke(rq_cli.main, ['-u', self.redis_url, 'requeue', '-a']) self.assertEqual(result.exit_code, 0) self.assertIn('Requeueing 1 jobs from FailedQueue', result.output) self.assertIn('Unable to requeue 0 jobs from FailedQueue', From 5883bb9efef61cbe6eded53f65e8899444d8cfa8 Mon Sep 17 00:00:00 2001 From: zhangliyong Date: Mon, 1 Sep 2014 14:16:28 +0700 Subject: [PATCH 19/27] Make pep8 --- tests/test_scripts.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_scripts.py b/tests/test_scripts.py index 3f2a659..826eef2 100644 --- a/tests/test_scripts.py +++ b/tests/test_scripts.py @@ -47,7 +47,8 @@ class TestRQCli(RQTestCase): def test_requeue(self): """rq -u requeue""" runner = CliRunner() - result = runner.invoke(rq_cli.main, ['-u', self.redis_url, 'requeue', '-a']) + result = runner.invoke(rq_cli.main, + ['-u', self.redis_url, 'requeue', '-a']) self.assertEqual(result.exit_code, 0) self.assertIn('Requeueing 1 jobs from FailedQueue', result.output) self.assertIn('Unable to requeue 0 jobs from FailedQueue', From ae1681e7a02d2750b2a57d71ed277f7547e22551 Mon Sep 17 00:00:00 2001 From: zhangliyong Date: Mon, 1 Sep 2014 14:19:24 +0700 Subject: [PATCH 20/27] Change doc of rq cli --- rq/scripts/rq_cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rq/scripts/rq_cli.py b/rq/scripts/rq_cli.py index d0df189..d88ed0d 100755 --- a/rq/scripts/rq_cli.py +++ b/rq/scripts/rq_cli.py @@ -19,7 +19,7 @@ from .rqinfo import info help='URL describing Redis connection details.') @click.pass_context def main(ctx, url): - """Entrance of RQ CLI""" + """RQ CLI""" if url is None: url = "redis://localhost:6379/0" redis_conn = redis.from_url(url) From c796e3249d5ed7b120805082144a15536b596da7 Mon Sep 17 00:00:00 2001 From: zhangliyong Date: Tue, 2 Sep 2014 10:04:02 +0700 Subject: [PATCH 21/27] Fix click dependency version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 3aeddc2..1d84412 100644 --- a/setup.py +++ b/setup.py @@ -17,7 +17,7 @@ def get_version(): def get_dependencies(): - deps = ['redis >= 2.7.0', 'click > 3.0'] + deps = ['redis >= 2.7.0', 'click >= 3.0'] if sys.version_info < (2, 7) or \ (sys.version_info >= (3, 0) and sys.version_info < (3, 1)): deps += ['importlib'] From 4248c934ab92942873f32e63fa61596fad0ef11d Mon Sep 17 00:00:00 2001 From: zhangliyong Date: Tue, 2 Sep 2014 10:07:15 +0700 Subject: [PATCH 22/27] Remove unused function 'gettersize' --- rq/utils.py | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/rq/utils.py b/rq/utils.py index d85235e..d875b26 100644 --- a/rq/utils.py +++ b/rq/utils.py @@ -11,38 +11,11 @@ from __future__ import (absolute_import, division, print_function, import importlib import datetime import logging -import os import sys from .compat import is_python_version, as_text -def gettermsize(): - def ioctl_GWINSZ(fd): - try: - import fcntl - import struct - import termios - cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234')) - except: - return None - return cr - cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2) - if not cr: - try: - fd = os.open(os.ctermid(), os.O_RDONLY) - cr = ioctl_GWINSZ(fd) - os.close(fd) - except: - pass - if not cr: - try: - cr = (os.environ['LINES'], os.environ['COLUMNS']) - except: - cr = (25, 80) - return int(cr[1]), int(cr[0]) - - class _Colorizer(object): def __init__(self): esc = "\x1b[" From 3eabe76690be28e706b79edf648ca2d9d349241d Mon Sep 17 00:00:00 2001 From: zhangliyong Date: Tue, 2 Sep 2014 11:06:35 +0700 Subject: [PATCH 23/27] Move back rqinfo command for backward compatibility --- rq/scripts/rqinfo.py | 62 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/rq/scripts/rqinfo.py b/rq/scripts/rqinfo.py index abf7d2b..736a148 100755 --- a/rq/scripts/rqinfo.py +++ b/rq/scripts/rqinfo.py @@ -6,13 +6,16 @@ from __future__ import (absolute_import, division, print_function, import sys import time import click +import argparse from functools import partial from redis.exceptions import ConnectionError -from rq import Queue, Worker, Connection +from rq import get_failed_queue, Queue, Worker, Connection +from rq.scripts import (add_standard_arguments, read_config_file, + setup_default_arguments, setup_redis) -red = partial(click.style, fg='red') +red = partial(click.style, fg='red') green = partial(click.style, fg='green') yellow = partial(click.style, fg='yellow') @@ -179,3 +182,58 @@ def info(ctx, path, interval, raw, only_queues, only_workers, by_queue, queues): except KeyboardInterrupt: click.echo() sys.exit(0) + + +### The following code is for backward compatibility, will be removed in future +def parse_args(): + parser = argparse.ArgumentParser(description='RQ command-line monitor.') + add_standard_arguments(parser) + parser.add_argument('--path', '-P', default='.', help='Specify the import path.') + parser.add_argument('--interval', '-i', metavar='N', type=float, default=2.5, help='Updates stats every N seconds (default: don\'t poll)') # noqa + parser.add_argument('--raw', '-r', action='store_true', default=False, help='Print only the raw numbers, no bar charts') # noqa + parser.add_argument('--only-queues', '-Q', dest='only_queues', default=False, action='store_true', help='Show only queue info') # noqa + parser.add_argument('--only-workers', '-W', dest='only_workers', default=False, action='store_true', help='Show only worker info') # noqa + parser.add_argument('--by-queue', '-R', dest='by_queue', default=False, action='store_true', help='Shows workers by queue') # noqa + parser.add_argument('--empty-failed-queue', '-X', dest='empty_failed_queue', default=False, action='store_true', help='Empties the failed queue, then quits') # noqa + parser.add_argument('queues', nargs='*', help='The queues to poll') + return parser.parse_args() + +def main(): + # warn users this command is deprecated, use `rq info` + import warnings + warnings.simplefilter('always', DeprecationWarning) + warnings.warn("This command will be remove in future, " + "use `rq info` instead", DeprecationWarning) + + args = parse_args() + + if args.path: + sys.path = args.path.split(':') + sys.path + + settings = {} + if args.config: + settings = read_config_file(args.config) + + setup_default_arguments(args, settings) + + setup_redis(args) + + try: + if args.empty_failed_queue: + num_jobs = get_failed_queue().empty() + print('{} jobs removed from failed queue'.format(num_jobs)) + else: + if args.only_queues: + func = show_queues + elif args.only_workers: + func = show_workers + else: + func = show_both + + refresh(args.interval, func, args.queues, args.raw, args.by_queue) + except ConnectionError as e: + print(e) + sys.exit(1) + except KeyboardInterrupt: + print() + sys.exit(0) From fc803f5d0d3119ba6816c989518f319472e843b9 Mon Sep 17 00:00:00 2001 From: Vincent Driessen Date: Sat, 6 Sep 2014 08:04:09 +0200 Subject: [PATCH 24/27] Fix various flake8 complaints. --- rq/queue.py | 4 ++-- rq/scripts/rq_cli.py | 12 ++++-------- rq/scripts/rqinfo.py | 14 +++++++------- rq/scripts/rqworker.py | 2 -- tests/test_scripts.py | 12 ++++-------- 5 files changed, 17 insertions(+), 27 deletions(-) diff --git a/rq/queue.py b/rq/queue.py index 22aa160..86f0406 100644 --- a/rq/queue.py +++ b/rq/queue.py @@ -138,10 +138,10 @@ class Queue(object): def remove(self, job_or_id, pipeline=None): """Removes Job from queue, accepts either a Job instance or ID.""" job_id = job_or_id.id if isinstance(job_or_id, self.job_class) else job_or_id - + if pipeline is not None: pipeline.lrem(self.key, 0, job_id) - + return self.connection._lrem(self.key, 0, job_id) def compact(self): diff --git a/rq/scripts/rq_cli.py b/rq/scripts/rq_cli.py index d88ed0d..3e5403c 100755 --- a/rq/scripts/rq_cli.py +++ b/rq/scripts/rq_cli.py @@ -15,8 +15,7 @@ from .rqinfo import info @click.group() -@click.option('--url', '-u', envvar='URL', - help='URL describing Redis connection details.') +@click.option('--url', '-u', envvar='URL', help='URL describing Redis connection details.') @click.pass_context def main(ctx, url): """RQ CLI""" @@ -29,8 +28,7 @@ def main(ctx, url): @main.command() -@click.option('--yes', '-y', is_flag=True, - help='Empty failed queue by default') +@click.option('--yes', '-y', is_flag=True, help='Empty failed queue by default') @click.argument('queues', nargs=-1) @click.pass_context def empty(ctx, yes, queues): @@ -51,8 +49,7 @@ def empty(ctx, yes, queues): conn = ctx.obj['connection'] queues = [Queue(queue, connection=conn) for queue in queues] if not queues: - if yes or click.confirm('Do you want to empty failed queue?', - abort=True): + if yes or click.confirm('Do you want to empty failed queue?', abort=True): queues = (get_failed_queue(connection=conn),) for queue in queues: num_jobs = queue.empty() @@ -61,8 +58,7 @@ def empty(ctx, yes, queues): @main.command() -@click.option('--all', '-a', 'is_all', is_flag=True, - help='Requeue all failed jobs') +@click.option('--all', '-a', 'is_all', is_flag=True, help='Requeue all failed jobs') @click.argument('job_ids', nargs=-1) @click.pass_context def requeue(ctx, is_all, job_ids): diff --git a/rq/scripts/rqinfo.py b/rq/scripts/rqinfo.py index 736a148..16c0a32 100755 --- a/rq/scripts/rqinfo.py +++ b/rq/scripts/rqinfo.py @@ -3,18 +3,17 @@ from __future__ import (absolute_import, division, print_function, unicode_literals) +import argparse import sys import time -import click -import argparse from functools import partial +import click from redis.exceptions import ConnectionError -from rq import get_failed_queue, Queue, Worker, Connection +from rq import Connection, get_failed_queue, Queue, Worker from rq.scripts import (add_standard_arguments, read_config_file, setup_default_arguments, setup_redis) - red = partial(click.style, fg='red') green = partial(click.style, fg='green') yellow = partial(click.style, fg='yellow') @@ -184,7 +183,7 @@ def info(ctx, path, interval, raw, only_queues, only_workers, by_queue, queues): sys.exit(0) -### The following code is for backward compatibility, will be removed in future +# TODO: The following code is for backward compatibility, should be removed in future def parse_args(): parser = argparse.ArgumentParser(description='RQ command-line monitor.') add_standard_arguments(parser) @@ -198,12 +197,13 @@ def parse_args(): parser.add_argument('queues', nargs='*', help='The queues to poll') return parser.parse_args() + def main(): # warn users this command is deprecated, use `rq info` import warnings warnings.simplefilter('always', DeprecationWarning) - warnings.warn("This command will be remove in future, " - "use `rq info` instead", DeprecationWarning) + warnings.warn("This command will be removed in future, " + "use `rq info` instead", DeprecationWarning) args = parse_args() diff --git a/rq/scripts/rqworker.py b/rq/scripts/rqworker.py index b6371fd..c238c8a 100644 --- a/rq/scripts/rqworker.py +++ b/rq/scripts/rqworker.py @@ -4,8 +4,6 @@ from __future__ import (absolute_import, division, print_function, unicode_literals) import argparse -import logging -import logging.config import os import sys diff --git a/tests/test_scripts.py b/tests/test_scripts.py index 826eef2..8c5e0fc 100644 --- a/tests/test_scripts.py +++ b/tests/test_scripts.py @@ -39,25 +39,21 @@ class TestRQCli(RQTestCase): def test_empty(self): """rq -u empty -y""" runner = CliRunner() - result = runner.invoke(rq_cli.main, - ['-u', self.redis_url, 'empty', "-y"]) + result = runner.invoke(rq_cli.main, ['-u', self.redis_url, 'empty', "-y"]) self.assertEqual(result.exit_code, 0) self.assertEqual(result.output, '1 jobs removed from failed queue\n') def test_requeue(self): """rq -u requeue""" runner = CliRunner() - result = runner.invoke(rq_cli.main, - ['-u', self.redis_url, 'requeue', '-a']) + result = runner.invoke(rq_cli.main, ['-u', self.redis_url, 'requeue', '-a']) self.assertEqual(result.exit_code, 0) self.assertIn('Requeueing 1 jobs from FailedQueue', result.output) - self.assertIn('Unable to requeue 0 jobs from FailedQueue', - result.output) + self.assertIn('Unable to requeue 0 jobs from FailedQueue', result.output) def test_info(self): """rq -u info -i 0""" runner = CliRunner() - result = runner.invoke(rq_cli.main, - ['-u', self.redis_url, 'info', '-i 0']) + result = runner.invoke(rq_cli.main, ['-u', self.redis_url, 'info', '-i 0']) self.assertEqual(result.exit_code, 0) self.assertIn('1 queues, 1 jobs total', result.output) From 8f1e066f15763e64cffcf1722759a391b790755b Mon Sep 17 00:00:00 2001 From: Vincent Driessen Date: Sat, 6 Sep 2014 08:16:02 +0200 Subject: [PATCH 25/27] Various little style fixes. --- rq/scripts/rq_cli.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/rq/scripts/rq_cli.py b/rq/scripts/rq_cli.py index 3e5403c..4ebab61 100755 --- a/rq/scripts/rq_cli.py +++ b/rq/scripts/rq_cli.py @@ -1,7 +1,6 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- """ -rq command line tool +RQ command line tool """ from __future__ import (absolute_import, division, print_function, unicode_literals) From 07dda7471002062c69dac4a3f6ab8c808565a9f3 Mon Sep 17 00:00:00 2001 From: Vincent Driessen Date: Sat, 6 Sep 2014 08:18:18 +0200 Subject: [PATCH 26/27] Change options of the `rq empty` command. * Does not ask confirmation * Does not need `--yes` option anymore * Added --all, to clear all queues * No implicit emptying of the failed queue. If you want to empty the failed queue, just use `$ rq empty failed` --- rq/scripts/rq_cli.py | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/rq/scripts/rq_cli.py b/rq/scripts/rq_cli.py index 4ebab61..1d77ec4 100755 --- a/rq/scripts/rq_cli.py +++ b/rq/scripts/rq_cli.py @@ -27,33 +27,23 @@ def main(ctx, url): @main.command() -@click.option('--yes', '-y', is_flag=True, help='Empty failed queue by default') +@click.option('--all', '-a', is_flag=True, help='Empty all queues') @click.argument('queues', nargs=-1) @click.pass_context -def empty(ctx, yes, queues): - """[QUEUES]: queues to empty - - \b - $ rq empty - Do you want to empty failed queue? [y/N]: y - 2 jobs removed from failed queue - \b - $ rq empty -y - 2 jobs removed from failed queue - \b - $ rq empty default high - 10 jobs removed from default queue - 2 jobs removed from high queue - """ +def empty(ctx, all, queues): + """Empty given queues.""" conn = ctx.obj['connection'] - queues = [Queue(queue, connection=conn) for queue in queues] + if all: + queues = Queue.all(connection=conn) + else: + queues = [Queue(queue, connection=conn) for queue in queues] + if not queues: - if yes or click.confirm('Do you want to empty failed queue?', abort=True): - queues = (get_failed_queue(connection=conn),) + click.echo('Nothing to do') + for queue in queues: num_jobs = queue.empty() - click.echo('{0} jobs removed from {1} queue'.format( - num_jobs, queue.name)) + click.echo('{0} jobs removed from {1} queue'.format(num_jobs, queue.name)) @main.command() From 5c96c6125512c9baa352d83cf3eed3d42fce49f6 Mon Sep 17 00:00:00 2001 From: Vincent Driessen Date: Sat, 6 Sep 2014 08:25:03 +0200 Subject: [PATCH 27/27] Change `rq requeue` subtly, mostly docs and vars. --- rq/scripts/rq_cli.py | 44 +++++++++++++++++++------------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/rq/scripts/rq_cli.py b/rq/scripts/rq_cli.py index 1d77ec4..8e0490a 100755 --- a/rq/scripts/rq_cli.py +++ b/rq/scripts/rq_cli.py @@ -5,6 +5,8 @@ RQ command line tool from __future__ import (absolute_import, division, print_function, unicode_literals) +import sys + import click import redis from rq import get_failed_queue, Queue @@ -47,40 +49,32 @@ def empty(ctx, all, queues): @main.command() -@click.option('--all', '-a', 'is_all', is_flag=True, help='Requeue all failed jobs') +@click.option('--all', '-a', is_flag=True, help='Requeue all failed jobs') @click.argument('job_ids', nargs=-1) @click.pass_context -def requeue(ctx, is_all, job_ids): - """[JOB_IDS] Job_ids in FailedQueue to requeue - - \b - $ rq requeue -a - Requeueing 10 jobs from FailedQueue - [####################################] 100% - Unable to requeue 0 jobs from FailedQueue - - \b - $ rq requeue a28bd044-65f3-42dd-96ee-acfcea155ba7\ - ac5559e1-90a0-4ab5-8e68-0d854b47b969 - Requeueing 2 jobs from FailedQueue - [####################################] 100% - Unable to requeue 1 jobs from FailedQueue - """ +def requeue(ctx, all, job_ids): + """Requeue failed jobs.""" conn = ctx.obj['connection'] failed_queue = get_failed_queue(connection=conn) - if not job_ids and is_all: + + if all: job_ids = failed_queue.job_ids - click.echo('Requeueing {0} jobs from FailedQueue'.format(len(job_ids))) - requeue_failed_num = 0 - with click.progressbar(job_ids) as job_bar: - for job_id in job_bar: + + if not job_ids: + click.echo('Nothing to do') + sys.exit(0) + + click.echo('Requeueing {0} jobs from failed queue'.format(len(job_ids))) + fail_count = 0 + with click.progressbar(job_ids) as job_ids: + for job_id in job_ids: try: failed_queue.requeue(job_id) except InvalidJobOperationError: - requeue_failed_num += 1 + fail_count += 1 - click.secho('Unable to requeue {0} jobs from FailedQueue'.format( - requeue_failed_num), fg='red') + if fail_count > 0: + click.secho('Unable to requeue {0} jobs from failed queue'.format(fail_count), fg='red') main.add_command(info)