Skip to content

Commit 2e717e6

Browse files
committed
Add max_jobs test and fix #103
1 parent 132ceec commit 2e717e6

7 files changed

Lines changed: 38 additions & 14 deletions

File tree

README.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
Full documentation is available on [readthedocs](http://mrq.readthedocs.org/en/latest/)
66

7-
/!\ MRQ is not yet ready for public use. Soon!
8-
97
# Why?
108

119
MRQ is an opinionated task queue. It aims to be simple and beautiful like [RQ](http://python-rq.org) while having performances close to [Celery](http://celeryproject.org)

docs/command-line.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,12 @@ The following general flags can be passed as command-line arguments to either **
4040

4141
`mrq-worker` starts a new worker and takes one argument list:
4242

43-
- `queues`: The queues to listen on.Defaults to **default** , which will listen on all queues.
43+
- `queues`: The queues to listen on.Defaults to **default** , which will listen on all queues.
4444

4545
You can pass additional configuration flags:
4646

47-
- `--max_jobs`: Gevent:max number of jobs to do before quitting. Use as a temporary workaround for memory leaks in your tasks. Defaults to **0**
48-
- `--max_memory`: Max memory (in Mb) after which the process will be shut down. Use with `--processes [1-N]`
47+
- `--max_jobs`: Gevent:max number of jobs to do before quitting. Use as a workaround for memory leaks in your tasks. Defaults to **0**
48+
- `--max_memory`: Max memory (in Mb) after which the process will be shut down. Use with `--processes [1-N]`
4949
to have supervisord automatically respawn the worker when this happens. Defaults to **1**
5050
- `--grenlets, --gevent, --g`: Max number of greenlets to use. Defaults to **1**.
5151
- `--processes, --p`: Number of processes to launch with supervisord. Defaults to **0** (no supervisord).
@@ -87,11 +87,11 @@ To do this we added a ```--add_network_latency=0.1``` config option that will ad
8787
## mrq-run
8888

8989
`mrq-run` runs a one-off task. If you add the `--queue` option that will enqueue it to be later ran by a worker.
90-
90+
9191
- `taskpath`: Task to run.
9292
- `taskargs`: JSON-encoded arguments, or "key value" pairs.
9393
- `--queue`: Queue the task on this queue instead of running it right away.
94-
94+
9595
Typical usage is:
9696

9797
```

docs/configuration.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,13 @@ DEFAULT_JOB_CANCEL_TTL = 86400 #Seconds the tasks are kept in MongoDB when statu
5050
DEFAULT_JOB_TIMEOUT = 3600 #In seconds, delay before interrupting the job.Defaults to 3600 seconds which is 1 hour.
5151
DEFAULT_JOB_MAX_RETRIES = 3 #Set the status to "maxretries" after retrying that many times.Defaults to 3 seconds.
5252
DEFAULT_JOB_RETRY_DELAY = 3 #Seconds before a job in retry status is requeued again.Defaults to 3 seconds.
53-
USE_LARGE_JOB_IDS = False #Do not use compacted job IDs in Redis. For compatibility with 0.1.x only. Defaults to
53+
USE_LARGE_JOB_IDS = False #Do not use compacted job IDs in Redis. For compatibility with 0.1.x only. Defaults to
5454

5555
""" mrq-worker settings
5656
"""
57-
QUEUES = ("default",) # The queues to listen on.Defaults to default , which will listen on all queues.
58-
MAX_JOBS = 0 #Gevent:max number of jobs to do before quitting. Temp workaround for memory leaks.Defaults to 0
59-
MAX_MEMORY = 1 #Max memory (in Mb) after which the process will be shut down. Use with PROCESS = [1-N] to have supervisord automatically respawn the worker when this happens.Defaults to 1
57+
QUEUES = ("default",) # The queues to listen on.Defaults to default , which will listen on all queues.
58+
MAX_JOBS = 0 #Gevent:max number of jobs to do before quitting. Workaround for memory leaks in your tasks. Defaults to 0
59+
MAX_MEMORY = 1 #Max memory (in Mb) after which the process will be shut down. Use with PROCESS = [1-N] to have supervisord automatically respawn the worker when this happens.Defaults to 1
6060
GRENLETS = 1 #Max number of greenlets to use.Defaults to 1.
6161
PROCESSES = 0 #Number of processes to launch with supervisord.Defaults to 0.
6262
SUPERVISORD_TEMPLATE = "supervisord_templates/default.conf" #Path of supervisord template to use. Defaults to supervisord_templates/default.conf.

mrq/worker.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,12 @@ def work_loop(self, max_jobs=None):
411411

412412
free_pool_slots = self.gevent_pool.free_count()
413413

414+
if max_jobs:
415+
total_started = (self.pool_size - free_pool_slots) + self.done_jobs
416+
free_pool_slots = min(free_pool_slots, max_jobs - total_started)
417+
if free_pool_slots == 0:
418+
break
419+
414420
if free_pool_slots > 0:
415421
self.status = "wait"
416422
break
@@ -423,6 +429,9 @@ def work_loop(self, max_jobs=None):
423429

424430
max_jobs_per_queue = free_pool_slots - len(jobs)
425431

432+
if max_jobs_per_queue <= 0:
433+
break
434+
426435
if self.config["dequeue_strategy"] == "parallel":
427436
max_jobs_per_queue = 1
428437

@@ -432,9 +441,6 @@ def work_loop(self, max_jobs=None):
432441
worker=self
433442
)
434443

435-
if len(jobs) >= free_pool_slots:
436-
break
437-
438444
for job in jobs:
439445

440446
# TODO investigate spawn_raw?

tests/tasks/redis.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from mrq.task import Task
22
from mrq.context import connections, subpool_map
3+
import gevent
34

45

56
class MultiRedis(Task):
@@ -19,7 +20,10 @@ class Disconnections(Task):
1920

2021
def run(self, params):
2122

23+
get_clients = lambda: [c for c in connections.redis.client_list() if c.get("cmd") != "client"]
24+
2225
def inner(i):
26+
print "Greenlet #%s, %s clients so far" % (id(gevent.getcurrent()), len(get_clients()))
2327
return connections.redis.get("test")
2428

2529
if params["subpool_size"]:

tests/test_general.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,4 @@ def test_general_exception_status(worker):
143143
assert job1["status"] == "failed"
144144
assert "raise" in job1["traceback"]
145145
assert "xyz" in job1["traceback"]
146+

tests/test_interrupts.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,3 +304,18 @@ def test_interrupt_redis_started_jobs(worker):
304304
assert Queue("xxx").size() == 2
305305
assert Queue("default").size() == 0
306306
assert connections.redis.zcard(Queue.redis_key_started()) == 0
307+
308+
309+
def test_interrupt_maxjobs(worker):
310+
311+
# The worker will stop after doing 5 jobs
312+
worker.start(flags="--max_jobs 5 --greenlets 2", queues="test1 default")
313+
314+
worker.send_tasks("tests.tasks.general.Add", [
315+
{"a": i, "b": 1, "sleep": 0}
316+
for i in range(12)
317+
], block=False)
318+
319+
time.sleep(2)
320+
321+
assert Queue("default").size() == 7

0 commit comments

Comments
 (0)