{ "info": { "author": "Luke Arno", "author_email": "luke.arno@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.2", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Topic :: Software Development :: Libraries", "Topic :: Utilities" ], "description": "# Redbike\n\nA simple, flexible scheduler for pools of distributed workers.\n\nRedbike is a helpful building block with intentionally limited features.\nIt's easy to schedule and distribute work however you like.\n\nRedbike is available from the Python Package Index:\n\n```bash\n$ pip install redbike\n```\n## High Level\n\nRedbike has a simple design, centered around a few data structures in Redis.\n\n* A registry of job schedules (a [hash](http://redis.io/topics/data-types#hashes))\n* A registry of job statuses (another [hash](http://redis.io/topics/data-types#hashes)) format: \"EVENT:TIMESTAMP\"\n* A timeline of scheduled work (a [sorted set](http://redis.io/topics/data-types#sorted-sets) scored by timestamp of next run)\n* Any number of job queues ([lists](http://redis.io/topics/data-types#lists))\n* A single dispatcher process to enqueue work that is due on the timeline\n* Expiring keys to keep track of jobs that have started running and not yet returned or timed out.\n* Any number of worker processes\n\n## Configuration\n\n```bash\n$ redbike --config=/etc/redbike.conf ...\n```\n\nRedbike needs to know the worker class, the prefix to use for all of\nits keys and the location of the time file (see below). Also\nit needs to know how to connect to Redis. By default it looks in \n`.redbike.conf` but you can specify any file.\n\nConnection information is found in a `[redbike-redis]` stanza and\nmirrors the arguments of py-redis' `StrictRedis` class. The rest\nof the settings are found in a `[redbike]` stanza.\nOther information in the config file is ignored, so you can use\na shared config as long as it has something like this in it:\n\n```ini\n[redbike]\nprefix: myapp\nworker: somepackage.somemodule:MyWorkerClass('initstring')\ntimefile: /var/log/myapp.redbike.timefile\n```\n\nIn Python:\n\n```python\nbike = Redbike(MyWorkerClass('initstring'),\n prefix='myapp',\n timefile='/var/log/myapp.redbike.timefile')\n```\n\n## Entering Jobs\n\n```bash\n$ redbike set [--after=]\n```\n\nTo run jobs in redbike just enter a JOBID and schedule. Schedules\ncan be in iCal [RRULE](http://www.kanzaki.com/docs/ical/rrule.html)\nformat or one of the following special values:\n\n* `NOW` - run once right away\n* `AT:TIMESTAMP` - run once at the specified time\n* `CONTINUE` - just re-queue right away\n* `STOP` - don't run anymore\n \nIf `--after` is provided, it will override the timefile (see below)\nand when (or if) to schedule each job will be based on this value.\n\nThe set operation does not wait for the dispatcher, and enters\nthe job directly into the timeline or work queue where\nappropriate.\n\nIn Python:\n\n```python\nbike.set('JOB1:A', 'NOW')\n```\n\n## Dispatch and the Time File\n\n```bash\n$ redbike dispatch [] [--schedules= [--after=]]\n```\n\nDispatch keeps checking the timeline and places jobs into work queues\nwhen they are due.\n\nThe dispatcher continually updates the contents of the timefile with\nthe current timestamp as it runs. When starting dispatch or setting\nschedules, the time in the timefile is used to determine when and if\nthe next run of the job should occur. When no `--after`\nargument is provided and no timefile is found, the default value is\nthe current time.\n\nA CSV of JOBID,SHEDULE pairs can also be provided. These schedules\nwill be set before dispatch begins. \n\n## Consuming Work\n\n```bash\n$ redbike work []\n```\n\nRedbike consumes jobs from the work queues using the worker class's\n`queue_names()` method and passes them to the worker's `work()` method.\nIf `StopWork` is raised, the job's schedule is set to `STOP`. If `UnsetJob`\nis raised, the job will be unset (removed from the rotation). If\nany other exception is raised it is logged and the job is not \nrescheduled. If the job takes longer than the timeout it is also not \nrescheduled. Otherwise the job's schedule is checked and it\nreturns to the queue or timeline if appropriate.\n\n## Writing a Worker\n\nRedbike includes a simple worker class that is flexible enough for\nmany cases. Just override its `work()` method. \n\n```python\n# mymodule.py\nfrom redbike import RoundRobin, StopWork\n\nclass Worker(RoundRobin):\n\n def work(self, jobid):\n should_stop = do_something(jobid)\n if should_stop:\n raise StopWork(\"Don't run this job any more!\")\n```\n\nThis class chooses work queues based on the portion of the\nJOBID following the last `:`. It is initialized with a colon\nseparated string specifying the queues to work and the order\nin which to work them. If, for instance, you want to put jobs\ninto two queues and have queue \"A\" worked twice as often as\nqueue \"B\", this would do the trick:\n\n```bash\n$ redbike set job1:A CONTINUE\n$ redbike set job2:B CONTINUE\n$ redbike work mymodule:Work(\"A:A:B\")\n```\n## Backoff\n\nWorkers with `CONTINUE` schedules may sometimes wish to \nintroduce a backoff. The worker's `work()` method may\nreturn an interger value of backoff seconds and the job\nwill be entered into the timeline to be enqueued for \nwork again after the specified backoff has elapsed.\n\n## Outstanding Jobs\n\nWhen workers consume jobs from the queue, they set a key\nwith an expiration and unique value to mark the occasion. When\na worker completes normally, it removes that key and reschedules.\nIf that key no longer exists or the value is changed, it is \nconsidered timed-out it will not reschedule. This behavior \nprevents the worker from stepping on schedule changes (typically\nmade by `set()` and `unset()`) that may have happened while the\njob was being worked.\n\n## Timeouts\n\nTimeouts can be controlled by your worker class. Just define\na `timeout(self, queue_name)` and return an integer\nfor timeout in seconds or `None` to use the default timeout.\nThe default default timeout is 10 seconds. You can also override\nthis in your `[redbike]` config stanza with a `default-timeout`\nsetting.\n\nYou should set a timeout that your jobs wont overrun unless it\nis ok for them to overlap.\n\n## Stopping\n\n```bash\n$ redbike control HALT\n```\n\nBoth dispatcher and worker processes watch for a control key\nto be set to `HALT` in Redis and stop immediately after completing\ntheir current task.\n\n## Failure Modes\n\nRedbike does its best to fail gracefully but managing the failure \nmodes of your workload is out of scope. How to approach it \ndepends on how you feel about things like the same scheduled \ninstance of a job getting worked twice or getting missed when\nthings crash and burn. That said, there are a few commands that\ncan help.\n\nJobs which may have fallen out of circulation and need to be reset\ncan be found by time of their last status.\n\n```bash\n$ redbike statuses [--before=]\nJOBID,status\nJOBID,status\n...\n```\n\nOutput is in CSV format.\n\nStatuses are set throughout the lifecycle of jobs in Redbike.\n\n* TML - entered into the timeline\n* ENQ - entered into a work queue\n* BAD - failed to schedule due to a bad RRULE\n* WRK - picked up by a worker\n* STP - stopped when the worked raise StopWork\n* DIE - worker raised an unexpected exception\n\nTo dump the schedules of all the jobs:\n\n```bash\n$ redbike schedules\nJOBID,schedule\nJOBID,schedule\n...\n```\n\nHere again, output is in CSV format.\n\nFinally, to spy on an individual job:\n\n```bash\n$ redbike tell \n```\n\nThis will output a json representation like this:\n\n```json\n{\n \"status\": \"ENQ:1381720578\", \n \"next_run\": null, \n \"schedule\": \"CONTINUE\"\n}\n```\n\n## Removing Unwanted Jobs\n\nOnce a job is no longer relevant and you want to take it out of\nrotation:\n\n```bash\n$ redbike unset \n```\n\nThe job will complete if it is already running, but will otherwise\nbe removed and not worked.", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://github.com/lukearno/redbike", "keywords": null, "license": "MIT", "maintainer": null, "maintainer_email": null, "name": "redbike", "package_url": "https://pypi.org/project/redbike/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/redbike/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://github.com/lukearno/redbike" }, "release_url": "https://pypi.org/project/redbike/0.13.1/", "requires_dist": null, "requires_python": null, "summary": "A simple, flexible scheduler for pools of distributed workers.", "version": "0.13.1" }, "last_serial": 1479680, "releases": { "0.10.0": [ { "comment_text": "", "digests": { "md5": "74b05da51518991e42979d5b0a61b5e1", "sha256": "530ff20b19354885b1bb73eed38d95cfe0570feebf3e4e22505994eaa1dd82b6" }, "downloads": -1, "filename": "redbike-0.10.0.tar.gz", "has_sig": false, "md5_digest": "74b05da51518991e42979d5b0a61b5e1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8906, "upload_time": "2014-01-23T05:12:44", "url": "https://files.pythonhosted.org/packages/f2/16/6e2a9d686b102596b67153b4587ed46690465c5ce89f9c29c64b109f029a/redbike-0.10.0.tar.gz" } ], "0.11.0": [ { "comment_text": "", "digests": { "md5": "3841dfd92625c2a8662b63f6763079da", "sha256": "35a474b2b5070932d7f706d88955e5ce1ae8dd878e2d6483147d0730409544cf" }, "downloads": -1, "filename": "redbike-0.11.0.tar.gz", "has_sig": false, "md5_digest": "3841dfd92625c2a8662b63f6763079da", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9285, "upload_time": "2014-01-30T03:53:01", "url": "https://files.pythonhosted.org/packages/0a/4e/1827726ff0a9066de63900501d97b023a1d69cfd015bc30532caa59af499/redbike-0.11.0.tar.gz" } ], "0.11.1": [ { "comment_text": "", "digests": { "md5": "9e3e4d2a31ffc896a45c0028740d1184", "sha256": "b982943a1b329c2efdacf1894d61b4e5022be4ca010f6e2cd7911ad1f2bcebe0" }, "downloads": -1, "filename": "redbike-0.11.1.tar.gz", "has_sig": false, "md5_digest": "9e3e4d2a31ffc896a45c0028740d1184", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9281, "upload_time": "2014-03-18T22:25:21", "url": "https://files.pythonhosted.org/packages/dd/ba/9ae4f9d199df0644ed5bfa15b2349ffb8cb48782d6c0ba2243340a75a07f/redbike-0.11.1.tar.gz" } ], "0.12.0": [ { "comment_text": "", "digests": { "md5": "f7284d4f70671482ee6709777138a743", "sha256": "a1ac7ea1481fde306190bdf0593b1ce573ebf4523f7d4e0bdaaa9edfb313a12b" }, "downloads": -1, "filename": "redbike-0.12.0.tar.gz", "has_sig": false, "md5_digest": "f7284d4f70671482ee6709777138a743", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10172, "upload_time": "2014-03-26T19:23:45", "url": "https://files.pythonhosted.org/packages/e3/96/d85f9bb4ec5a1080bb2c050543a3137a653bc807a6902b5ef10052b22139/redbike-0.12.0.tar.gz" } ], "0.13.0": [ { "comment_text": "", "digests": { "md5": "c84d9eaecea39dc02292c450271ecfad", "sha256": "c3be6855bed107009294a03a3317bc1282c9289488d5b7715c8918e543c2fafe" }, "downloads": -1, "filename": "redbike-0.13.0.tar.gz", "has_sig": false, "md5_digest": "c84d9eaecea39dc02292c450271ecfad", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9828, "upload_time": "2014-10-17T22:40:11", "url": "https://files.pythonhosted.org/packages/c5/f2/84846af15e1e4eafd4c6bfb695ccd7ae444ae55a179f59ede597b80090bd/redbike-0.13.0.tar.gz" } ], "0.13.1": [ { "comment_text": "", "digests": { "md5": "19ced796ccb1d10c9761863c005e062e", "sha256": "a0c0374186ef79b97e1b3087899c5e174e797f0e7757954b8080682872554da4" }, "downloads": -1, "filename": "redbike-0.13.1.tar.gz", "has_sig": false, "md5_digest": "19ced796ccb1d10c9761863c005e062e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9833, "upload_time": "2015-03-27T04:20:14", "url": "https://files.pythonhosted.org/packages/da/1b/abdd482ef75bc0988a082c2226ea50132c50037002ced0418ba5703c03a2/redbike-0.13.1.tar.gz" } ], "0.7.0": [ { "comment_text": "", "digests": { "md5": "825e0ee21b73e74ae66ccf1729b07df9", "sha256": "d93fca4ec78dda5ae7c112d42ca9e67c5779dcb4f6baea1758d43f6d1689c369" }, "downloads": -1, "filename": "redbike-0.7.0.tar.gz", "has_sig": false, "md5_digest": "825e0ee21b73e74ae66ccf1729b07df9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7676, "upload_time": "2013-10-14T08:38:49", "url": "https://files.pythonhosted.org/packages/91/2a/8ba586a2049c3dafa2bc13ba827ba98c07880e40f41686a1958fbea73461/redbike-0.7.0.tar.gz" } ], "0.8.0": [ { "comment_text": "", "digests": { "md5": "4e4239fb60d7a00dfd4f4c27f2fa2049", "sha256": "b776b949341163bd1d1811c00a5cf1b79f4eb17e861449020b8d8ce921bfc0c1" }, "downloads": -1, "filename": "redbike-0.8.0.tar.gz", "has_sig": false, "md5_digest": "4e4239fb60d7a00dfd4f4c27f2fa2049", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8355, "upload_time": "2013-10-17T06:03:33", "url": "https://files.pythonhosted.org/packages/2c/37/8c32f24e4a32b6f23c05743a788ef9aed463be1c39e5413bad77c4d94d0a/redbike-0.8.0.tar.gz" } ], "0.8.1": [ { "comment_text": "", "digests": { "md5": "9b2434a4da2ced805fee6b4e53b02627", "sha256": "9f7f5302cbdfededc8a2d7a9ef0b16fda47c3708126cfa808d4ebf99a9ef89a8" }, "downloads": -1, "filename": "redbike-0.8.1.tar.gz", "has_sig": false, "md5_digest": "9b2434a4da2ced805fee6b4e53b02627", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8378, "upload_time": "2013-10-21T18:23:33", "url": "https://files.pythonhosted.org/packages/c1/0f/4a63da3dce4de9d0794366f6ab712c509951b8446be2838dc4af42e69317/redbike-0.8.1.tar.gz" } ], "0.8.2": [ { "comment_text": "", "digests": { "md5": "aec479584f1f584e8b35657882bca7a0", "sha256": "f7e0a9b0c586c7999dc968edcdf21019215636fb10b63aadc3335aa9edaf73eb" }, "downloads": -1, "filename": "redbike-0.8.2.tar.gz", "has_sig": false, "md5_digest": "aec479584f1f584e8b35657882bca7a0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8374, "upload_time": "2013-10-23T06:17:36", "url": "https://files.pythonhosted.org/packages/66/a1/a95145fd93f82410c8cce2286c6b5df5c208d3b77d3b142c7f5e80ccf042/redbike-0.8.2.tar.gz" } ], "0.8.3": [ { "comment_text": "", "digests": { "md5": "c3dfcba8ece7d4c42eba16a9ac6bf006", "sha256": "ab5e6285c61154938a7f4c3fbcd476afe7259ca7b42dddb0888940cbf9dd6b62" }, "downloads": -1, "filename": "redbike-0.8.3.tar.gz", "has_sig": false, "md5_digest": "c3dfcba8ece7d4c42eba16a9ac6bf006", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8455, "upload_time": "2013-10-23T08:22:19", "url": "https://files.pythonhosted.org/packages/89/b8/48484bb2e3c33b705dbe943b6a95467b51c197bafa15aa66e53468279237/redbike-0.8.3.tar.gz" } ], "0.8.4": [ { "comment_text": "", "digests": { "md5": "2029da2eb456e5fb5f7795d980126417", "sha256": "117b5c29fb84daf2c0f06ba9f868cdbd8abdfe19c582ca4600eee0dade97e940" }, "downloads": -1, "filename": "redbike-0.8.4.tar.gz", "has_sig": false, "md5_digest": "2029da2eb456e5fb5f7795d980126417", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8475, "upload_time": "2013-10-24T06:27:30", "url": "https://files.pythonhosted.org/packages/58/d9/2caeae196670d69a3a4383c6b51f614492a524461d096c9a8381f97021a2/redbike-0.8.4.tar.gz" } ], "0.8.5": [ { "comment_text": "", "digests": { "md5": "2bf1c1d1c80d5f9a349c1f5d747e0b08", "sha256": "fd9624da73bf9b33ba746b395d199c7ea34348c65ded8c87b5442d71d02072c8" }, "downloads": -1, "filename": "redbike-0.8.5.tar.gz", "has_sig": false, "md5_digest": "2bf1c1d1c80d5f9a349c1f5d747e0b08", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8477, "upload_time": "2013-10-25T05:46:00", "url": "https://files.pythonhosted.org/packages/a3/11/a2f84fdba0cda3aac8d47d0afc0c357365918db122b6efbd47851d11e2b5/redbike-0.8.5.tar.gz" } ], "0.9.0": [ { "comment_text": "", "digests": { "md5": "ed283c83e28caadfa440062b613f6a0a", "sha256": "35b06e044f4f7ce194ce9440ece537e9e6bc91592d17fd08319e84f6478c89aa" }, "downloads": -1, "filename": "redbike-0.9.0.tar.gz", "has_sig": false, "md5_digest": "ed283c83e28caadfa440062b613f6a0a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8525, "upload_time": "2013-11-25T22:02:22", "url": "https://files.pythonhosted.org/packages/7e/6b/de0f05872b2731e80803f182ebdbd8946037a9927d1ee2d5c0934690c9fa/redbike-0.9.0.tar.gz" } ], "0.9.1": [ { "comment_text": "", "digests": { "md5": "495122334a7cd9cc0cdd8691b61f028e", "sha256": "8c6348d3250179263f7423f445a37f20dc0f5b83a73a697a7d7d1fa3b8d3ed46" }, "downloads": -1, "filename": "redbike-0.9.1.tar.gz", "has_sig": false, "md5_digest": "495122334a7cd9cc0cdd8691b61f028e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8700, "upload_time": "2013-11-26T05:15:29", "url": "https://files.pythonhosted.org/packages/61/57/e45c5f039b013dd5fe11aaf26cdc1e9a4e9f177e47bd76d0f8a770dd9be7/redbike-0.9.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "19ced796ccb1d10c9761863c005e062e", "sha256": "a0c0374186ef79b97e1b3087899c5e174e797f0e7757954b8080682872554da4" }, "downloads": -1, "filename": "redbike-0.13.1.tar.gz", "has_sig": false, "md5_digest": "19ced796ccb1d10c9761863c005e062e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9833, "upload_time": "2015-03-27T04:20:14", "url": "https://files.pythonhosted.org/packages/da/1b/abdd482ef75bc0988a082c2226ea50132c50037002ced0418ba5703c03a2/redbike-0.13.1.tar.gz" } ] }