Giter Club home page Giter Club logo

mrq's Introduction

MRQ

Build Status MIT License

MRQ is a distributed task queue for python built on top of mongo, redis and gevent.

Full documentation is available on readthedocs

Why?

MRQ is an opinionated task queue. It aims to be simple and beautiful like RQ while having performances close to Celery

MRQ was first developed at Pricing Assistant and its initial feature set matches the needs of worker queues with heterogenous jobs (IO-bound & CPU-bound, lots of small tasks & a few large ones).

Main Features

  • Simple code: We originally switched from Celery to RQ because Celery's code was incredibly complex and obscure (Slides). MRQ should be as easy to understand as RQ and even easier to extend.
  • Great dashboard: Have visibility and control on everything: queued jobs, current jobs, worker status, ...
  • Per-job logs: Get the log output of each task separately in the dashboard
  • Gevent worker: IO-bound tasks can be done in parallel in the same UNIX process for maximum throughput
  • Supervisord integration: CPU-bound tasks can be split across several UNIX processes with a single command-line flag
  • Job management: You can retry, requeue, cancel jobs from the code or the dashboard.
  • Performance: Bulk job queueing, easy job profiling
  • Easy configuration: Every aspect of MRQ is configurable through command-line flags or a configuration file
  • Job routing: Like Celery, jobs can have default queues, timeout and ttl values.
  • Builtin scheduler: Schedule tasks by interval or by time of the day
  • Strategies: Sequential or parallel dequeue order, also a burst mode for one-time or periodic batch jobs.
  • Subqueues: Simple command-line pattern for dequeuing multiple sub queues, using auto discovery from worker side.
  • Thorough testing: Edge-cases like worker interrupts, Redis failures, ... are tested inside a Docker container.
  • Greenlet tracing: See how much time was spent in each greenlet to debug CPU-intensive jobs.
  • Integrated memory leak debugger: Track down jobs leaking memory and find the leaks with objgraph.

Dashboard Screenshots

Job view

Worker view

Get Started

This 5-minute tutorial will show you how to run your first jobs with MRQ.

Installation

  • Make sure you have installed the dependencies : Redis and MongoDB
  • Install MRQ with pip install mrq
  • Start a mongo server with mongod &
  • Start a redis server with redis-server &

Write your first task

Create a new directory and write a simple task in a file called tasks.py :

$ mkdir test-mrq && cd test-mrq
$ touch __init__.py
$ vim tasks.py
from mrq.task import Task
import urllib2


class Fetch(Task):

    def run(self, params):

        with urllib2.urlopen(params["url"]) as f:
          t = f.read()
          return len(t)

Run it synchronously

You can now run it from the command line using mrq-run:

$ mrq-run tasks.Fetch url http://www.google.com

2014-12-18 15:44:37.869029 [DEBUG] mongodb_jobs: Connecting to MongoDB at 127.0.0.1:27017/mrq...
2014-12-18 15:44:37.880115 [DEBUG] mongodb_jobs: ... connected.
2014-12-18 15:44:37.880305 [DEBUG] Starting tasks.Fetch({'url': 'http://www.google.com'})
2014-12-18 15:44:38.158572 [DEBUG] Job None success: 0.278229s total
17655

Run it asynchronously

Let's schedule the same task 3 times with different parameters:

$ mrq-run --queue fetches tasks.Fetch url http://www.google.com &&
  mrq-run --queue fetches tasks.Fetch url http://www.yahoo.com &&
  mrq-run --queue fetches tasks.Fetch url http://www.wordpress.com

2014-12-18 15:49:05.688627 [DEBUG] mongodb_jobs: Connecting to MongoDB at 127.0.0.1:27017/mrq...
2014-12-18 15:49:05.705400 [DEBUG] mongodb_jobs: ... connected.
2014-12-18 15:49:05.729364 [INFO] redis: Connecting to Redis at 127.0.0.1...
5492f771520d1887bfdf4b0f
2014-12-18 15:49:05.957912 [DEBUG] mongodb_jobs: Connecting to MongoDB at 127.0.0.1:27017/mrq...
2014-12-18 15:49:05.967419 [DEBUG] mongodb_jobs: ... connected.
2014-12-18 15:49:05.983925 [INFO] redis: Connecting to Redis at 127.0.0.1...
5492f771520d1887c2d7d2db
2014-12-18 15:49:06.182351 [DEBUG] mongodb_jobs: Connecting to MongoDB at 127.0.0.1:27017/mrq...
2014-12-18 15:49:06.193314 [DEBUG] mongodb_jobs: ... connected.
2014-12-18 15:49:06.209336 [INFO] redis: Connecting to Redis at 127.0.0.1...
5492f772520d1887c5b32881

You can see that instead of executing the tasks and returning their results right away, mrq-run has added them to the queue named fetches and printed their IDs.

Now start MRQ's dasbhoard with mrq-dashboard & and go check your newly created queue and jobs on localhost:5555

They are ready to be dequeued by a worker. Start one with mrq-worker and follow it on the dashboard as it executes the queued jobs in parallel.

$ mrq-worker fetches

2014-12-18 15:52:57.362209 [INFO] Starting Gevent pool with 10 worker greenlets (+ report, logs, adminhttp)
2014-12-18 15:52:57.388033 [INFO] redis: Connecting to Redis at 127.0.0.1...
2014-12-18 15:52:57.389488 [DEBUG] mongodb_jobs: Connecting to MongoDB at 127.0.0.1:27017/mrq...
2014-12-18 15:52:57.390996 [DEBUG] mongodb_jobs: ... connected.
2014-12-18 15:52:57.391336 [DEBUG] mongodb_logs: Connecting to MongoDB at 127.0.0.1:27017/mrq...
2014-12-18 15:52:57.392430 [DEBUG] mongodb_logs: ... connected.
2014-12-18 15:52:57.523329 [INFO] Fetching 1 jobs from ['fetches']
2014-12-18 15:52:57.567311 [DEBUG] Starting tasks.Fetch({u'url': u'http://www.google.com'})
2014-12-18 15:52:58.670492 [DEBUG] Job 5492f771520d1887bfdf4b0f success: 1.135268s total
2014-12-18 15:52:57.523329 [INFO] Fetching 1 jobs from ['fetches']
2014-12-18 15:52:57.567747 [DEBUG] Starting tasks.Fetch({u'url': u'http://www.yahoo.com'})
2014-12-18 15:53:01.897873 [DEBUG] Job 5492f771520d1887c2d7d2db success: 4.361895s total
2014-12-18 15:52:57.523329 [INFO] Fetching 1 jobs from ['fetches']
2014-12-18 15:52:57.568080 [DEBUG] Starting tasks.Fetch({u'url': u'http://www.wordpress.com'})
2014-12-18 15:53:00.685727 [DEBUG] Job 5492f772520d1887c5b32881 success: 3.149119s total
2014-12-18 15:52:57.523329 [INFO] Fetching 1 jobs from ['fetches']
2014-12-18 15:52:57.523329 [INFO] Fetching 1 jobs from ['fetches']

You can interrupt the worker with Ctrl-C once it is finished.

Going further

This was a preview on the very basic features of MRQ. What makes it actually useful is that:

  • You can run multiple workers in parallel. Each worker can also run multiple greenlets in parallel.
  • Workers can dequeue from multiple queues
  • You can queue jobs from your Python code to avoid using mrq-run from the command-line.

These features will be demonstrated in a future example of a simple web crawler.

More

Full documentation is available on readthedocs

mrq's People

Contributors

adipasquale avatar antoine-collet avatar balajeerc avatar benjisg avatar chenull avatar deveil avatar dmarkey avatar ecebuzz avatar florianludwig avatar florianperucki avatar ggueret avatar ialwaysbecoding avatar karpitsky avatar kraptor avatar maelorn avatar mehdigmira avatar melalj avatar mongin avatar mraerino avatar msabramo avatar nicozivy avatar orlandobcrra avatar pauleuh avatar romarci avatar sylvinus avatar thomas-b avatar timgates42 avatar tume avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mrq's Issues

how to set timeout ?

i have set TIMEOUT=3600 in mrq-config.py,but it is also says the timeout is 300,i don'e know how to set the timeout correctly,any help would be appreacicated!

More Mongo/Redis disconnect tests

Test disconnecting at other stages:

  • long-running queries in tasks & worker
  • specific spots in the worker code: how to make reproducible?

Task progress

from mrq.context import progress

... in a task ....
progress(0.42)
  • Show in dashboard
  • Where to store? Redis? Worker logs?
  • What happens with subtasks?

implement mrq --version

for now we have to do

$ python
from version import version
version.VERSION

which is not very convenient

documentation setup

I have some documentation I'd like to add, is there any plans to set-up any documentation other than README.md?

I can add to the readme for now, just thought it would be worth starting a discussion :)

pep8 style

The code style is not very pep8-like
we can use autopep8 to convert code style according to pep8

does the mongodb support the multiprocess

as the mrq use supervisor to manage the process ,i want to use mongodb to write/read the data in job,is the mongodb support the multiprocess?
use mongodb read/write in environment(--gevent 3 --processes 40) it emeges errors:
CursorNotFound: cursor id '36660188981453623' not valid at server
how to resolve?
any help will be appreaciated?

Log scale for zset ETA graphes

Sparklines make this one a bit complicated... the actual value must be the log one, and then we'd need to exponentiate it again in the tooltip. Set the log factor in the raw_queues config?

Task callbacks

Have a task called with the results of a group of task when they finish (success/failed?)

More consistent API

Iif you do mrq-run mrq-test.Fetch '{"url":"xx"}' it will be run in the same python process, but if you do mrq-run --async mrq-test.Fetch it will be queued and return the job ID.

From the code the default is different, send_task() is async by default but can be used with send_task(sync=True).

We need to rename a couple things there to be consistent :)

Also, from mrq.queue import send_task is not the best we can do.

0.0.46 requires redis 2.6.0+

Upon upgrading to 0.0.46 from 0.0.36 I realized we need redis 2.6.0.
Not sure how you want to specify dependencies in the README, but thought it should be noted :)

IO monitoring

Would be incredibly useful to have a list of current IO in the Dashboard:

  • MongoDB/Redis queries
  • HTTP
  • ?

We'd collect them by monkey patching in a few places (like we already do for Mongo) and store them in worker logs.

Unique jobs

We want some jobs to be only queued once.

Store a hash of the task+params ?

Rate limiting

Implement a ratelimit() primitive backed by Redis on top of which we could add more useful features

very slow when use mongodb in the mrq job's function

@sylvinus
if use mongodb in the jobs,it will be more slow due to the mongodb used to update job's status in the mrq,and the gevent context switch from mongodb will be expensive! It will be a disaster when many mongodb connections from job's function.
any suggestion available?

RequeueLostJobs improvements

The current "ascending IDs" algorithm doesn't quite work. List queues and requeue tasks when redis=0 and mongo>0 ?

PyPy support

Gevent's support for PyPy doesn't seem great, check with the PyPy team.

Bulk queues

For maximum throughput with expendable jobs, we should have "Bulk" queues that don't store anything in Mongo and store just the data they need in a Redis list/set/zset

Task event handlers

Currently there is no way to handle a job timeout from within the task it's self, for jobs where timeouts are acceptable but need to cleanup, @sylvinus suggested we add event handlers for the on_retry, on_exception and on_timeout exceptions.

Just starting a discussion on the design/implementation of the event handlers :)

on_retry(self, exception)
on_exception(self, exception)
on_timeout(self)

and perhaps

on_success(self)?

fix scheduler's daily time feature

this will allow scheduling tasks at a specific time of the day.

it's already in there but does not work and the test is commented out.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.